From 80e9552d1139738c802aebf9092ebe7bda880002 Mon Sep 17 00:00:00 2001 From: SkateSpots Date: Fri, 2 Oct 2026 12:38:44 +0700 Subject: [PATCH] feat(card): 'Finish your card' checklist (photo, name, styles/level, crew) A card is only as good as its content, so the studio now shows what's missing with one-tap links to fix it, instead of a subtle amber hint. --- src/i18n/en.ts | 6 ++++++ src/i18n/es.ts | 6 ++++++ src/pages/RiderCardPage.tsx | 31 +++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/src/i18n/en.ts b/src/i18n/en.ts index a991ba8..d08cc4b 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -6387,6 +6387,12 @@ walletUi: { editSkaterProfile: 'add your styles & level', noPhoto: 'No profile photo yet —', addPhoto: 'add one in your profile', + finishTitle: 'Finish your card', + finishDesc: 'A photo and a Skater profile make it look real.', + checkPhoto: 'Profile photo', + checkName: 'Display name', + checkProfile: 'Styles & level', + checkCrew: 'Join a crew', accent: 'Accent colour', accentHint: 'Overrides the theme accent', accentClear: 'Use theme colour', diff --git a/src/i18n/es.ts b/src/i18n/es.ts index 3437138..b1699a6 100644 --- a/src/i18n/es.ts +++ b/src/i18n/es.ts @@ -6387,6 +6387,12 @@ walletUi: { editSkaterProfile: 'añade tus estilos y nivel', noPhoto: 'Aún no tienes foto de perfil —', addPhoto: 'añádela en tu perfil', + finishTitle: 'Completa tu carné', + finishDesc: 'Una foto y un perfil de skater lo hacen parecer real.', + checkPhoto: 'Foto de perfil', + checkName: 'Nombre visible', + checkProfile: 'Estilos y nivel', + checkCrew: 'Únete a una cuadrilla', accent: 'Color de acento', accentHint: 'Sustituye el acento del tema', accentClear: 'Usar color del tema', diff --git a/src/pages/RiderCardPage.tsx b/src/pages/RiderCardPage.tsx index 9e4f619..43a96ac 100644 --- a/src/pages/RiderCardPage.tsx +++ b/src/pages/RiderCardPage.tsx @@ -186,6 +186,15 @@ export default function RiderCardPage() { const derivedLevel = skaterProfile?.level ? (SKATER_LEVELS[skaterProfile.level]?.label ?? '') : (skaterProfile?.customLevel ?? ''); + + // "Finish your card" checklist — a card is only as good as what's on it. + const cardChecks = [ + { done: !!metadata?.picture, label: t('cardUi.studio.checkPhoto'), to: '/settings?section=profile' }, + { done: !!metadata?.name, label: t('cardUi.studio.checkName'), to: '/settings?section=profile' }, + { done: (skaterProfile?.styles?.length ?? 0) > 0 || !!skaterProfile?.level, label: t('cardUi.studio.checkProfile'), to: '/skaters' }, + { done: memberships.length > 0, label: t('cardUi.studio.checkCrew'), to: '/crews' }, + ]; + const incomplete = cardChecks.some((c) => !c.done); const { mutate: publishEvent } = useNostrPublish(); const { mutateAsync: uploadFile, isPending: uploadingLogo } = useUploadFile(); const { toast } = useToast(); @@ -659,6 +668,27 @@ export default function RiderCardPage() { {/* ══ RIGHT: inspector ══ */}
+ {/* Finish-your-card checklist (personal card) */} + {cardType === 'rider' && incomplete && ( +
+
{t('cardUi.studio.finishTitle')}
+

{t('cardUi.studio.finishDesc')}

+
+ {cardChecks.map((c) => ( + c.done ? ( + + ✓ {c.label} + + ) : ( + + + {c.label} + + ) + ))} +
+
+ )} + {/* Card type */}

{t('labUi.rider.cardType')}

@@ -814,6 +844,7 @@ export default function RiderCardPage() {

)} +