Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,8 @@
"Readme*": "AUTHORS, Authors, BACKERS*, Backers*, CHANGELOG*, CITATION*, CODEOWNERS, CODE_OF_CONDUCT*, CONTRIBUTING*, CONTRIBUTORS, COPYING*, CREDITS, Changelog*, Citation*, Code_Of_Conduct*, Codeowners, Contributing*, Contributors, Copying*, Credits, GOVERNANCE.MD, Governance.md, HISTORY.MD, History.md, LICENSE*, License*, MAINTAINERS, Maintainers, README-*, README_*, RELEASE_NOTES*, ROADMAP.MD, Readme-*, Readme_*, Release_Notes*, Roadmap.md, SECURITY.MD, SPONSORS*, Security.md, Sponsors*, authors, backers*, changelog*, citation*, code_of_conduct*, codeowners, contributing*, contributors, copying*, credits, governance.md, history.md, license*, maintainers, readme-*, readme_*, release_notes*, roadmap.md, security.md, sponsors*",
"README*": "AUTHORS, Authors, BACKERS*, Backers*, CHANGELOG*, CITATION*, CODEOWNERS, CODE_OF_CONDUCT*, CONTRIBUTING*, CONTRIBUTORS, COPYING*, CREDITS, Changelog*, Citation*, Code_Of_Conduct*, Codeowners, Contributing*, Contributors, Copying*, Credits, GOVERNANCE.MD, Governance.md, HISTORY.MD, History.md, LICENSE*, License*, MAINTAINERS, Maintainers, README-*, README_*, RELEASE_NOTES*, ROADMAP.MD, Readme-*, Readme_*, Release_Notes*, Roadmap.md, SECURITY.MD, SPONSORS*, Security.md, Sponsors*, authors, backers*, changelog*, citation*, code_of_conduct*, codeowners, contributing*, contributors, copying*, credits, governance.md, history.md, license*, maintainers, readme-*, readme_*, release_notes*, roadmap.md, security.md, sponsors*",
"Dockerfile": "*.dockerfile, .devcontainer.*, .dockerignore, captain-definition, compose.*, docker-compose.*, dockerfile*"
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
}
}
4 changes: 2 additions & 2 deletions app/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import i18next from "i18next"
import LanguageDetector from "i18next-browser-languagedetector"
import Fetch from "i18next-fetch-backend"
import Backend from "i18next-http-backend"
import { StrictMode, startTransition } from "react"
import { hydrateRoot } from "react-dom/client"
import { I18nextProvider, initReactI18next } from "react-i18next"
Expand All @@ -13,7 +13,7 @@ async function hydrate() {
await i18next
.use(initReactI18next) // Tell i18next to use the react-i18next plugin
.use(LanguageDetector) // Setup a client-side language detector
.use(Fetch) // Setup your backend
.use(Backend) // Setup your backend
.init({
...i18n, // spread the configuration
// This function detects the namespaces your routes rendered while SSR use
Expand Down
2 changes: 1 addition & 1 deletion app/library/icon/icons/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion app/library/icon/icons/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// This file is generated by icon spritesheet generator

export const iconNames = [
"ShoppingCart",
"Ghost",
] as const

export type IconName = typeof iconNames[number]
20 changes: 19 additions & 1 deletion app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useTranslation } from "react-i18next"
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router"
import { Links, Meta, Outlet, Scripts, ScrollRestoration, isRouteErrorResponse, useRouteError } from "react-router"
import type { LinksFunction } from "react-router"
import { useChangeLanguage } from "remix-i18next/react"
import type { Route } from "./+types/root"
Expand Down Expand Up @@ -49,3 +49,21 @@ export const Layout = ({ children }: { children: React.ReactNode }) => {
</html>
)
}

export const ErrorBoundary = () => {
const error = useRouteError()
const { t } = useTranslation()

const errorStatusCode = isRouteErrorResponse(error) ? error.status : "500"

return (
<div className="placeholder-index relative h-full min-h-screen w-screen flex items-center justify-center dark:bg-white sm:pb-16 sm:pt-8">
<div className="relative mx-auto max-w-[90rem] sm:px-6 lg:px-8">
<div className="relative min-h-72 flex flex-col justify-center sm:overflow-hidden sm:rounded-2xl p-1 md:p-4 lg:p-6">
<h1 className="text-center w-full text-red-600 text-2xl pb-2">{t(`error.${errorStatusCode}.title`)}</h1>
<p className="text-lg text-center w-full">{t(`error.${errorStatusCode}.description`)}</p>
</div>
</div>
</div>
)
}
38 changes: 38 additions & 0 deletions app/routes/$.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useTranslation } from "react-i18next"
import { Link, useNavigate } from "react-router"
import { Icon } from "~/library/icon/Icon"

export default function Route404() {
const navigate = useNavigate()
const { t } = useTranslation()

return (
<div className="min-h-screen bg-gradient-to-b from-gray-50 to-gray-100 flex items-center justify-center p-4">
<div className="max-w-2xl w-full text-center">
<div className="mb-8 flex justify-center">
<Icon name="Ghost" className="h-24 w-24 text-indigo-600 animate-float" />
</div>

<h1 className="text-6xl font-bold text-gray-900 mb-4">404</h1>
<h2 className="text-3xl font-semibold text-gray-800 mb-4">{t("error.404.title")}</h2>
<p className="text-gray-600 mb-8 text-lg">{t("error.404.description")}</p>

<div className="flex flex-col sm:flex-row gap-4 justify-center">
<button
type="button"
onClick={() => navigate(-1)}
className="inline-flex cursor-pointer items-center justify-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-indigo-700 bg-indigo-100 hover:bg-indigo-200 transition-colors duration-300"
>
{t("navigation.back")}
</button>
<Link
to="/"
className="inline-flex cursor-pointer items-center justify-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 transition-colors duration-300"
>
{t("navigation.home")}
</Link>
</div>
</div>
</div>
)
}
11 changes: 11 additions & 0 deletions app/tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,15 @@

@theme {
/* Your theme styles go here */
--animate-float: float 3s ease-in-out infinite;

@keyframes float {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-10px);
}
}
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"hono": "4.6.12",
"i18next": "24.2.1",
"i18next-browser-languagedetector": "8.0.0",
"i18next-fetch-backend": "6.0.0",
"i18next-http-backend": "3.0.2",
"isbot": "5.1.17",
"pretty-cache-header": "1.0.0",
"react": "19.0.0",
Expand Down Expand Up @@ -68,7 +68,7 @@
"lefthook": "1.8.4",
"playwright": "1.49.0",
"prompt": "1.3.0",
"react-router-devtools": "1.1.0",
"react-router-devtools": "1.1.3",
"tailwindcss": "4.0.0",
"tsx": "4.19.2",
"typescript": "5.6.3",
Expand Down
Loading