SkateSpots/src/pages/TrustPage.tsx
SkateSpots d1fae2688c feat(trust): attribute the badge and add a /trust explainer
Legibility pass: a trust verdict has to be explainable and sourced.

- TrustBadge tooltips now attribute the claim (from your network / the
  community provider / the provider you chose) and link to /trust.
- New /trust page: the three states, why absence is not distrust, who
  computes it, presence-is-not-endorsement, and point-of-view. Public,
  linked from the badge; added to the smoke-test route list.
- New trustUi.* keys and four walletUi.trust attribution keys (en/es).
2026-10-09 17:30:00 +07:00

127 lines
3.7 KiB
TypeScript

import { useSeoMeta } from '@unhead/react';
import { Link } from 'react-router-dom';
import { Shield, CheckCircle2, HelpCircle, Flag, Users, Scale, AlertTriangle } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useTranslation } from '@/contexts/language';
function Section({
icon: Icon,
color,
title,
children,
}: {
icon: React.ComponentType<{ className?: string; style?: React.CSSProperties }>;
color: string;
title: string;
children: React.ReactNode;
}) {
return (
<section className="rounded-2xl border border-white/8 bg-white/3 p-5">
<div className="mb-3 flex items-center gap-3">
<div
className="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-xl"
style={{ background: `${color}1a`, border: `1px solid ${color}40` }}
>
<Icon className="h-5 w-5" style={{ color }} />
</div>
<h2 className="text-lg font-black uppercase tracking-wide text-white">{title}</h2>
</div>
<div className="space-y-3 text-sm leading-relaxed text-gray-400">{children}</div>
</section>
);
}
function Point({
icon: Icon,
color,
title,
desc,
}: {
icon: React.ComponentType<{ className?: string; style?: React.CSSProperties }>;
color: string;
title: string;
desc: string;
}) {
return (
<div className="flex items-start gap-3">
<Icon className="mt-0.5 h-4 w-4 flex-shrink-0" style={{ color }} />
<div>
<p className="font-bold text-white">{title}</p>
<p>{desc}</p>
</div>
</div>
);
}
/**
* Public explainer for the trust buckets. The badge has to be legible and
* attributable, and absence has to be explained (it is the common case), or the
* whole feature reads as an opaque verdict.
*/
export default function TrustPage() {
const { t } = useTranslation();
useSeoMeta({
title: t('trustUi.seoTitle'),
description: t('trustUi.seoDescription'),
});
return (
<div className="container max-w-3xl space-y-5 py-10">
<header className="space-y-3">
<div className="flex items-center gap-3">
<Shield className="h-8 w-8 text-[#ccff00]" />
<h1 className="text-3xl font-black uppercase tracking-wide text-white">
{t('trustUi.title')}
</h1>
</div>
<p className="text-gray-400">{t('trustUi.intro')}</p>
</header>
<Section icon={Scale} color="#13d2e5" title={t('trustUi.statesTitle')}>
<Point
icon={CheckCircle2}
color="#22c55e"
title={t('trustUi.verifiedTitle')}
desc={t('trustUi.verifiedDesc')}
/>
<Point
icon={HelpCircle}
color="#8c929e"
title={t('trustUi.unknownTitle')}
desc={t('trustUi.unknownDesc')}
/>
<Point
icon={Flag}
color="#ef4444"
title={t('trustUi.flaggedTitle')}
desc={t('trustUi.flaggedDesc')}
/>
</Section>
<Section icon={AlertTriangle} color="#f59e0b" title={t('trustUi.absenceTitle')}>
<p>{t('trustUi.absenceDesc')}</p>
</Section>
<Section icon={Users} color="#6366f1" title={t('trustUi.sourceTitle')}>
<p>{t('trustUi.sourceDesc')}</p>
</Section>
<Section icon={Flag} color="#ef4444" title={t('trustUi.endorsementTitle')}>
<p>{t('trustUi.endorsementDesc')}</p>
</Section>
<Section icon={Scale} color="#13d2e5" title={t('trustUi.povTitle')}>
<p>{t('trustUi.povDesc')}</p>
</Section>
<div className="flex justify-center pt-2">
<Link to="/settings">
<Button className="gap-2 bg-[#ccff00] text-black hover:bg-[#ccff00]/90">
{t('trustUi.settingsCta')}
</Button>
</Link>
</div>
</div>
);
}