111 lines
3.8 KiB
TypeScript
111 lines
3.8 KiB
TypeScript
import { useSeoMeta } from '@unhead/react';
|
|
import { Link } from 'react-router-dom';
|
|
import { Hammer, ChevronRight } from 'lucide-react';
|
|
import { useTranslation } from '@/contexts/language';
|
|
import { cn } from '@/lib/utils';
|
|
import { DIY_CATEGORIES, DIY_CARDS, DIY_ACTIONS, type DiyCard } from '@/lib/diyGuides';
|
|
|
|
/**
|
|
* DIY — resources for making your own boards, ramps and concrete spots, with
|
|
* cross-links into the rest of the app (find a builder, map a spot, sell).
|
|
* Content lives in `src/lib/diyGuides.ts`. Cards with no destination yet render
|
|
* unclickable with a "Coming soon" badge.
|
|
*/
|
|
function DiyCardView({ card }: { card: DiyCard }) {
|
|
const { t } = useTranslation();
|
|
|
|
const body = (
|
|
<>
|
|
<span className="text-2xl leading-none" aria-hidden>{card.emoji}</span>
|
|
<span className="min-w-0 flex-1">
|
|
<span className="flex items-center gap-2">
|
|
<span className="font-bold text-white">{t(card.titleKey)}</span>
|
|
{card.comingSoon && (
|
|
<span className="flex-shrink-0 rounded-full border border-white/15 bg-white/5 px-2 py-0.5 text-[9px] font-black uppercase tracking-wider text-gray-400">
|
|
{t('diyUi.comingSoon')}
|
|
</span>
|
|
)}
|
|
</span>
|
|
<span className="mt-0.5 block text-xs leading-relaxed text-gray-400">{t(card.blurbKey)}</span>
|
|
</span>
|
|
{card.to && <ChevronRight className="mt-0.5 h-4 w-4 flex-shrink-0 text-gray-500" />}
|
|
</>
|
|
);
|
|
|
|
const base = 'flex items-start gap-3 rounded-2xl border border-white/10 p-4 transition-colors';
|
|
|
|
if (!card.to) {
|
|
// Coming soon — deliberately not a link.
|
|
return (
|
|
<div
|
|
aria-disabled="true"
|
|
className={cn(base, 'cursor-default border-dashed bg-white/[0.015]')}
|
|
>
|
|
{body}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Link
|
|
to={card.to}
|
|
className={cn(base, 'bg-white/[0.03] hover:border-[#ccff00]/40 hover:bg-white/[0.06]')}
|
|
>
|
|
{body}
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
export default function DiyPage() {
|
|
const { t } = useTranslation();
|
|
|
|
useSeoMeta({
|
|
title: t('seoUi.diyTitle'),
|
|
description: t('seoUi.diyDesc'),
|
|
});
|
|
|
|
return (
|
|
<div className="container mx-auto max-w-5xl px-4 py-8">
|
|
{/* Header */}
|
|
<header className="mb-6">
|
|
<h1 className="flex items-center gap-2 text-3xl md:text-4xl font-black uppercase tracking-tight text-white">
|
|
<Hammer className="h-7 w-7 text-[#ccff00]" />
|
|
{t('diyUi.title')}
|
|
</h1>
|
|
<p className="mt-2 text-sm text-gray-400 max-w-2xl">{t('diyUi.tagline')}</p>
|
|
</header>
|
|
|
|
{/* Resource sections */}
|
|
{DIY_CATEGORIES.map((cat) => {
|
|
const cards = DIY_CARDS.filter((c) => c.category === cat.id);
|
|
if (cards.length === 0) return null;
|
|
return (
|
|
<section key={cat.id} id={cat.id} className="mb-10 scroll-mt-28">
|
|
<h2 className="mb-3 flex items-center gap-2 text-lg font-black uppercase tracking-wide text-[#ccff00]">
|
|
<span aria-hidden>{cat.emoji}</span>
|
|
{t(cat.titleKey)}
|
|
</h2>
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
|
{cards.map((card) => <DiyCardView key={card.id} card={card} />)}
|
|
</div>
|
|
</section>
|
|
);
|
|
})}
|
|
|
|
{/* Do it with people — cross-links into the app */}
|
|
<section className="mb-10">
|
|
<h2 className="mb-3 flex items-center gap-2 text-lg font-black uppercase tracking-wide text-[#ccff00]">
|
|
<span aria-hidden>🤝</span>
|
|
{t('diyUi.doItWithPeople')}
|
|
</h2>
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
|
|
{DIY_ACTIONS.map((card) => <DiyCardView key={card.id} card={card} />)}
|
|
</div>
|
|
</section>
|
|
|
|
<p className="mt-6 text-center text-[11px] leading-relaxed text-gray-600">
|
|
{t('diyUi.footer')}
|
|
</p>
|
|
</div>
|
|
);
|
|
}
|