Files
GearBox/src/client/routes/collection/index.tsx
Jean-Luc Makiola a576f53d33
All checks were successful
CI / ci (push) Successful in 1m8s
CI / e2e (push) Has been skipped
CI / deploy (push) Successful in 13s
fix(27): lint fixes — unused param, import order, formatting
2026-04-10 23:54:46 +02:00

75 lines
2.0 KiB
TypeScript

import { createFileRoute, Link } from "@tanstack/react-router";
import { AnimatePresence, motion } from "framer-motion";
import { useRef } from "react";
import { z } from "zod";
import { CollectionView } from "../../components/CollectionView";
import { PlanningView } from "../../components/PlanningView";
const searchSchema = z.object({
tab: z.enum(["gear", "planning"]).catch("gear"),
});
export const Route = createFileRoute("/collection/")({
validateSearch: searchSchema,
component: CollectionPage,
});
const TAB_ORDER = ["gear", "planning"] as const;
const TAB_LABELS: Record<(typeof TAB_ORDER)[number], string> = {
gear: "Gear",
planning: "Planning",
};
const slideVariants = {
enter: (dir: number) => ({ x: `${dir * 15}%`, opacity: 0 }),
center: { x: 0, opacity: 1 },
exit: (dir: number) => ({ x: `${dir * -15}%`, opacity: 0 }),
};
function CollectionPage() {
const { tab } = Route.useSearch();
const prevTab = useRef(tab);
const direction =
TAB_ORDER.indexOf(tab) >= TAB_ORDER.indexOf(prevTab.current) ? 1 : -1;
prevTab.current = tab;
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6 overflow-x-hidden">
{/* Tab navigation */}
<div className="flex justify-center mb-6">
<div className="flex bg-gray-100 rounded-full p-0.5 gap-0.5">
{TAB_ORDER.map((t) => (
<Link
key={t}
to="/collection"
search={{ tab: t }}
className={`px-4 py-1.5 text-sm font-medium rounded-full transition-colors ${
tab === t
? "bg-gray-700 text-white"
: "text-gray-600 hover:bg-gray-200"
}`}
>
{TAB_LABELS[t]}
</Link>
))}
</div>
</div>
<AnimatePresence mode="wait" initial={false} custom={direction}>
<motion.div
key={tab}
custom={direction}
variants={slideVariants}
initial="enter"
animate="center"
exit="exit"
transition={{ duration: 0.12, ease: "easeInOut" }}
>
{tab === "gear" ? <CollectionView /> : <PlanningView />}
</motion.div>
</AnimatePresence>
</div>
);
}