Mirror a real campaign and the live verified badge in the verify tutorial
The how-to demo card now reflects a real published campaign (the Agora App Development Fund) instead of invented placeholder copy: real title, organizer, banner image, and goal/progress. The verified badge is now a faithful copy of the live overlay CampaignVerificationBadge (dark translucent pill, ring-bordered avatar, sky-300 check, no count) for a single verifier, so the preview matches exactly how a verification surfaces on a real card. Drops the now-unused demo i18n keys (campaignTitle, campaignOrganizer, verifiedBadge) across all locales.
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
} from 'lucide-react';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
import { sanitizeUrl } from '@/lib/sanitizeUrl';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||
|
||||
/**
|
||||
@@ -247,6 +248,23 @@ export function VerifyTutorial({
|
||||
|
||||
// ── The animated mock card ───────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* A real published campaign (kind 33863) used as the demo subject so the
|
||||
* tutorial mirrors an actual card rather than invented placeholder copy.
|
||||
* Static by design — the tutorial is purely illustrative, so we read the
|
||||
* fields directly instead of fetching the event.
|
||||
*/
|
||||
const DEMO_CAMPAIGN = {
|
||||
title: 'Agora App Development Fund',
|
||||
organizer: 'Team Soapbox',
|
||||
story: 'Help fund the development of Agora!',
|
||||
banner:
|
||||
'https://blossom.primal.net/aade02e86584a7ab269550992d0266bae31059a34e6e08fddba1f6f5acb6e7d6.jpg',
|
||||
goalLabel: '$1,000',
|
||||
raisedLabel: '$670',
|
||||
pct: 67,
|
||||
} as const;
|
||||
|
||||
interface DemoStageProps {
|
||||
phaseIndex: number;
|
||||
menuVisible: boolean;
|
||||
@@ -270,11 +288,16 @@ function DemoStage({
|
||||
}: DemoStageProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
// When a verifier identity is supplied, the badge mirrors the live
|
||||
// verification badge (org avatar + name); otherwise it falls back to the
|
||||
// generic "Verified by you" label.
|
||||
const hasVerifier = !!verifierName?.trim();
|
||||
const verifierInitial = verifierName?.trim()?.[0]?.toUpperCase() ?? '?';
|
||||
// The badge replicates the live overlay `CampaignVerificationBadge`
|
||||
// (dark translucent pill, single ring-bordered avatar, sky check) so the
|
||||
// preview matches exactly how a verification surfaces on a real card.
|
||||
const badgePicture = sanitizeUrl(verifierPicture);
|
||||
const verifierInitials =
|
||||
(verifierName?.trim() || '')
|
||||
.slice(0, 2)
|
||||
.toUpperCase() || '?';
|
||||
|
||||
const bannerUrl = sanitizeUrl(DEMO_CAMPAIGN.banner);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -284,52 +307,41 @@ function DemoStage({
|
||||
)}
|
||||
aria-hidden="true"
|
||||
>
|
||||
{/* Mock campaign card */}
|
||||
{/* Mock campaign card — mirrors CampaignCard's structure. */}
|
||||
<div className="overflow-hidden rounded-2xl border border-border/60 bg-card shadow-md">
|
||||
{/* Banner */}
|
||||
<div className="relative h-40 bg-gradient-to-br from-sky-500/80 via-cyan-500/70 to-emerald-500/80">
|
||||
<div
|
||||
className="relative h-40 bg-gradient-to-br from-sky-500/80 via-cyan-500/70 to-emerald-500/80 bg-cover bg-center"
|
||||
style={bannerUrl ? { backgroundImage: `url("${bannerUrl}")` } : undefined}
|
||||
>
|
||||
{/* Top scrim for badge legibility — as on the real card. */}
|
||||
<div
|
||||
aria-hidden
|
||||
className="absolute inset-0 opacity-30 mix-blend-overlay"
|
||||
style={{
|
||||
backgroundImage:
|
||||
'radial-gradient(circle at 30% 30%, rgba(255,255,255,0.5), transparent 45%)',
|
||||
}}
|
||||
className="absolute inset-x-0 top-0 h-16 bg-gradient-to-b from-black/30 to-transparent"
|
||||
/>
|
||||
|
||||
{/* Verified badge (top-left) — appears in the final phase. When a
|
||||
verifier identity is supplied it previews that org's avatar +
|
||||
name; otherwise a generic "Verified by you" label. */}
|
||||
{/* Verified badge (top-left) — appears in the final phase. A faithful
|
||||
copy of the live overlay CampaignVerificationBadge for a single
|
||||
verifier: the org's avatar + sky check, no count text. */}
|
||||
<div
|
||||
className={cn(
|
||||
'absolute left-3 top-3 flex items-center gap-1.5 rounded-full bg-background/90 text-xs font-semibold text-foreground shadow-sm backdrop-blur transition-all duration-500',
|
||||
hasVerifier ? 'py-1 pl-1.5 pr-2.5' : 'px-2.5 py-1',
|
||||
'absolute left-3 top-3 z-10 inline-flex items-center gap-1 rounded-full bg-black/40 px-1.5 py-1 text-white backdrop-blur-md transition-all duration-500',
|
||||
verified
|
||||
? 'opacity-100 translate-y-0'
|
||||
: 'opacity-0 -translate-y-1 pointer-events-none',
|
||||
)}
|
||||
>
|
||||
{hasVerifier ? (
|
||||
<>
|
||||
<Avatar className="size-5 shrink-0 ring-2 ring-background">
|
||||
<AvatarImage
|
||||
src={verifierPicture || undefined}
|
||||
alt={verifierName}
|
||||
className="object-cover"
|
||||
/>
|
||||
<AvatarFallback className="bg-secondary text-[9px] font-semibold text-secondary-foreground">
|
||||
{verifierInitial}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<BadgeCheck className="size-4 text-primary" />
|
||||
<span className="max-w-[10rem] truncate">{verifierName}</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<BadgeCheck className="size-4 text-primary" />
|
||||
{t('organizations.tutorial.demo.verifiedBadge')}
|
||||
</>
|
||||
)}
|
||||
<span className="flex items-center -space-x-2">
|
||||
<Avatar className="size-6 ring-2 ring-background">
|
||||
{badgePicture && <AvatarImage src={badgePicture} alt="" className="object-cover" />}
|
||||
<AvatarFallback className="bg-secondary text-[9px] text-secondary-foreground">
|
||||
{verifierInitials}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
</span>
|
||||
<span className="ml-0.5 inline-flex items-center gap-1 pr-1 text-xs font-semibold">
|
||||
<BadgeCheck className="size-4 text-sky-300" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Three-dots button (top-right) */}
|
||||
@@ -373,23 +385,38 @@ function DemoStage({
|
||||
{/* Card body */}
|
||||
<div className="space-y-3 p-4">
|
||||
<div>
|
||||
<p className="font-semibold leading-snug">
|
||||
{t('organizations.tutorial.demo.campaignTitle')}
|
||||
<p className="font-semibold leading-snug truncate">
|
||||
{DEMO_CAMPAIGN.title}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{t('organizations.tutorial.demo.campaignOrganizer')}
|
||||
<p className="text-xs text-muted-foreground truncate">
|
||||
{DEMO_CAMPAIGN.story}
|
||||
</p>
|
||||
</div>
|
||||
{/* Fake progress bar */}
|
||||
{/* Progress — mirrors CampaignProgress (bar + raised / goal). */}
|
||||
<div className="space-y-1.5">
|
||||
<div className="h-2 w-full overflow-hidden rounded-full bg-muted">
|
||||
<div className="h-full w-2/3 rounded-full bg-primary" />
|
||||
<div className="h-2 w-full overflow-hidden rounded-full bg-foreground/15">
|
||||
<div
|
||||
className="h-full rounded-full bg-primary"
|
||||
style={{ width: `${DEMO_CAMPAIGN.pct}%` }}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-between text-xs text-muted-foreground">
|
||||
<span>0.45 BTC</span>
|
||||
<span>67%</span>
|
||||
<div className="flex items-baseline justify-between gap-2 text-sm">
|
||||
<span className="font-semibold">{DEMO_CAMPAIGN.raisedLabel}</span>
|
||||
<span className="text-muted-foreground">of {DEMO_CAMPAIGN.goalLabel} goal</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Organizer footer — mirrors CampaignCard's AuthorByline row. */}
|
||||
<div className="flex items-center gap-2 border-t border-border/60 pt-3 text-xs text-muted-foreground">
|
||||
<Avatar className="size-5">
|
||||
<AvatarFallback className="bg-secondary text-[9px] text-secondary-foreground">
|
||||
{DEMO_CAMPAIGN.organizer.slice(0, 1).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<span className="truncate font-medium text-foreground/80">
|
||||
{DEMO_CAMPAIGN.organizer}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
+1
-4
@@ -1107,10 +1107,7 @@
|
||||
"confirm": { "title": "أكِّد وانتهيت", "body": "أقرّ بأن الحملة أصلية. تنضم شارتك إلى البطاقة ليعلم المتبرعون أنك تقف خلفها." }
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "مياه نظيفة لموانزا",
|
||||
"campaignOrganizer": "بواسطة مؤسسة Mradi",
|
||||
"menuVerify": "وثّق هذه الحملة",
|
||||
"verifiedBadge": "موثّقة بواسطتك"
|
||||
"menuVerify": "وثّق هذه الحملة"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1620,10 +1620,7 @@
|
||||
}
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "Clean Water for Mwanza",
|
||||
"campaignOrganizer": "by Mradi Foundation",
|
||||
"menuVerify": "Verify this campaign",
|
||||
"verifiedBadge": "Verified by you"
|
||||
"menuVerify": "Verify this campaign"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1126,10 +1126,7 @@
|
||||
}
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "Agua limpia para Mwanza",
|
||||
"campaignOrganizer": "de la Fundación Mradi",
|
||||
"menuVerify": "Verificar esta campaña",
|
||||
"verifiedBadge": "Verificada por ti"
|
||||
"menuVerify": "Verificar esta campaña"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1117,10 +1117,7 @@
|
||||
"confirm": { "title": "تأیید کنید و کار تمام است", "body": "گواهی دهید که کمپین معتبر است. نشان شما به کارت افزوده میشود تا اهداکنندگان بدانند که شما پشتیبان آن هستید." }
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "آب پاکیزه برای Mwanza",
|
||||
"campaignOrganizer": "توسط بنیاد Mradi",
|
||||
"menuVerify": "این کمپین را تأیید کنید",
|
||||
"verifiedBadge": "تأییدشده توسط شما"
|
||||
"menuVerify": "این کمپین را تأیید کنید"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1565,10 +1565,7 @@
|
||||
}
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "De l'eau potable pour Mwanza",
|
||||
"campaignOrganizer": "par la Fondation Mradi",
|
||||
"menuVerify": "Vérifier cette campagne",
|
||||
"verifiedBadge": "Vérifié par vous"
|
||||
"menuVerify": "Vérifier cette campagne"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1559,10 +1559,7 @@
|
||||
"confirm": { "title": "पुष्टि करें और हो गया", "body": "प्रमाणित करें कि अभियान प्रामाणिक है। आपका बैज कार्ड में जुड़ जाता है ताकि दानदाताओं को पता चले कि आप इसके पीछे खड़े हैं।" }
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "Mwanza के लिए स्वच्छ जल",
|
||||
"campaignOrganizer": "Mradi Foundation द्वारा",
|
||||
"menuVerify": "इस अभियान को सत्यापित करें",
|
||||
"verifiedBadge": "आपके द्वारा सत्यापित"
|
||||
"menuVerify": "इस अभियान को सत्यापित करें"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1559,10 +1559,7 @@
|
||||
"confirm": { "title": "Konfirmasi & selesai", "body": "Tegaskan bahwa kampanye ini autentik. Lencana Anda akan muncul di kartu sehingga para donatur tahu Anda mendukungnya." }
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "Air Bersih untuk Mwanza",
|
||||
"campaignOrganizer": "oleh Mradi Foundation",
|
||||
"menuVerify": "Verifikasi kampanye ini",
|
||||
"verifiedBadge": "Diverifikasi oleh Anda"
|
||||
"menuVerify": "Verifikasi kampanye ini"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1117,10 +1117,7 @@
|
||||
"confirm": { "title": "បញ្ជាក់ ហើយអ្នកបានបញ្ចប់", "body": "បញ្ជាក់ថាយុទ្ធនាការនេះពិតប្រាកដ។ ផ្លាកសញ្ញារបស់អ្នកនឹងភ្ជាប់ទៅកាត ដើម្បីឱ្យអ្នកបរិច្ចាគដឹងថាអ្នកគាំទ្រវា។" }
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "ទឹកស្អាតសម្រាប់ Mwanza",
|
||||
"campaignOrganizer": "ដោយ Mradi Foundation",
|
||||
"menuVerify": "ផ្ទៀងផ្ទាត់យុទ្ធនាការនេះ",
|
||||
"verifiedBadge": "បានផ្ទៀងផ្ទាត់ដោយអ្នក"
|
||||
"menuVerify": "ផ្ទៀងផ្ទាត់យុទ្ធនាការនេះ"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1119,10 +1119,7 @@
|
||||
"confirm": { "title": "تایید کړئ او کار مو پای ته ورسېد", "body": "تصدیق کړئ چې کمپاین اصلي دی. ستاسو نښان د کارت سره یوځای کېږي ترڅو بسپنه ورکوونکي پوه شي چې تاسو یې ملاتړ کوئ." }
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "د موانزا لپاره پاکې اوبه",
|
||||
"campaignOrganizer": "د Mradi بنسټ لخوا",
|
||||
"menuVerify": "دا کمپاین تصدیق کړئ",
|
||||
"verifiedBadge": "ستاسو لخوا تصدیق شوی"
|
||||
"menuVerify": "دا کمپاین تصدیق کړئ"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1570,10 +1570,7 @@
|
||||
}
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "Água Limpa para Mwanza",
|
||||
"campaignOrganizer": "por Mradi Foundation",
|
||||
"menuVerify": "Verificar esta campanha",
|
||||
"verifiedBadge": "Verificado por você"
|
||||
"menuVerify": "Verificar esta campanha"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1570,10 +1570,7 @@
|
||||
}
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "Чистая вода для Mwanza",
|
||||
"campaignOrganizer": "от Mradi Foundation",
|
||||
"menuVerify": "Проверить эту кампанию",
|
||||
"verifiedBadge": "Проверено вами"
|
||||
"menuVerify": "Проверить эту кампанию"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1119,10 +1119,7 @@
|
||||
"confirm": { "title": "Simbisa uye wapedza", "body": "Pupura kuti mushandirapamwe ndewechokwadi. Bheji rako rinobatana nekadhi kuti vanopa vazive kuti unowutsigira." }
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "Mvura Yakachena yeMwanza",
|
||||
"campaignOrganizer": "naMradi Foundation",
|
||||
"menuVerify": "Simbisa mushandirapamwe uyu",
|
||||
"verifiedBadge": "Yasimbiswa newe"
|
||||
"menuVerify": "Simbisa mushandirapamwe uyu"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1558,10 +1558,7 @@
|
||||
"confirm": { "title": "Thibitisha na umemaliza", "body": "Shuhudia kuwa kampeni ni halisi. Beji yako huungana na kadi ili wafadhili wajue unaiunga mkono." }
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "Maji Safi kwa Mwanza",
|
||||
"campaignOrganizer": "na Mradi Foundation",
|
||||
"menuVerify": "Thibitisha kampeni hii",
|
||||
"verifiedBadge": "Imethibitishwa na wewe"
|
||||
"menuVerify": "Thibitisha kampeni hii"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1560,10 +1560,7 @@
|
||||
"confirm": { "title": "Onaylayın ve işlem tamam", "body": "Kampanyanın gerçek olduğunu teyit edin. Rozetiniz kartta yerini alır, böylece bağışçılar arkasında durduğunuzu bilir." }
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "Mwanza için Temiz Su",
|
||||
"campaignOrganizer": "Mradi Vakfı tarafından",
|
||||
"menuVerify": "Bu kampanyayı doğrula",
|
||||
"verifiedBadge": "Sizin tarafınızdan doğrulandı"
|
||||
"menuVerify": "Bu kampanyayı doğrula"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1119,10 +1119,7 @@
|
||||
"confirm": { "title": "確認後即完成", "body": "證明這個專案是真實的。你的徽章會加入卡片,讓捐款者知道你為它背書。" }
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "為姆萬扎提供潔淨用水",
|
||||
"campaignOrganizer": "由 Mradi 基金會發起",
|
||||
"menuVerify": "驗證此活動",
|
||||
"verifiedBadge": "已由你驗證"
|
||||
"menuVerify": "驗證此活動"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+1
-4
@@ -1119,10 +1119,7 @@
|
||||
"confirm": { "title": "确认即可完成", "body": "证明该活动真实可信。你的徽章会出现在卡片上,让捐赠者知道你为它背书。" }
|
||||
},
|
||||
"demo": {
|
||||
"campaignTitle": "为 Mwanza 提供清洁饮水",
|
||||
"campaignOrganizer": "由 Mradi 基金会发起",
|
||||
"menuVerify": "验证此活动",
|
||||
"verifiedBadge": "已由你验证"
|
||||
"menuVerify": "验证此活动"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user