'use client'; import { useEffect, useMemo, useState } from 'react'; import { QrCode, Sparkles } from 'lucide-react'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/Dialog'; import { Button } from '@/components/ui/Button'; import { useCsrf } from '@/hooks/useCsrf'; import { useTranslation } from '@/hooks/useTranslation'; import { showToast } from '@/components/ui/Toast'; type Milestone = { id: string; qrTitle: string; threshold: number; defaultXHandle: string | null; preview: string; language: 'en' | 'de'; card: { title: string; label: string }; }; export function SocialMilestoneDialog() { const { fetchWithCsrf } = useCsrf(); const { locale } = useTranslation(); const [milestone, setMilestone] = useState(null); const [withName, setWithName] = useState(false); const [xHandle, setXHandle] = useState(''); const [saving, setSaving] = useState(false); useEffect(() => { fetch(`/api/social-milestones?locale=${locale}`) .then(async (response) => response.ok && setMilestone((await response.json()).milestone)) .catch(() => undefined); }, [locale]); useEffect(() => setXHandle(milestone?.defaultXHandle || ''), [milestone]); const copy = milestone?.language === 'de' ? { heading: 'Ein echter Erfolg', subtitle: 'hat gerade einen Scan-Meilenstein erreicht.', consent: 'Darf QR Master diesen Erfolg mit der unten stehenden Karte auf dem eigenen X-Account teilen?', name: 'Meinen X-Handle nennen', decline: 'Nein, danke', optOut: 'Nicht mehr anzeigen', self: 'Selbst teilen', approve: 'Auf QR Master posten', published: 'Der Beitrag wird jetzt auf dem QR Master X-Account veroeffentlicht.' } : { heading: 'A real milestone', subtitle: 'just reached a scan milestone.', consent: 'May QR Master share this success, including the card below, from our X account?', name: 'Mention my X handle', decline: 'No thanks', optOut: 'Do not show again', self: 'Share myself', approve: 'Post from QR Master', published: 'This will now be published from the QR Master X account.' }; const preview = useMemo(() => { if (!milestone || !withName || !xHandle.trim()) return milestone?.preview || ''; return `${milestone.preview} By @${xHandle.trim().replace(/^@/, '')}.`; }, [milestone, withName, xHandle]); const respond = async (action: 'approve_brand' | 'self_share' | 'decline' | 'opt_out') => { if (!milestone) return; setSaving(true); try { const response = await fetchWithCsrf(`/api/social-milestones/${milestone.id}`, { method: 'PATCH', body: JSON.stringify({ action, withName, xHandle, language: milestone.language }), }); const result = await response.json(); if (!response.ok) throw new Error(result.error || 'Could not save your choice'); if (action === 'self_share') { await navigator.clipboard?.writeText(preview); window.open(`https://x.com/intent/post?text=${encodeURIComponent(preview)}`, '_blank', 'noopener,noreferrer'); window.open('https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.qrmaster.net', '_blank', 'noopener,noreferrer'); showToast('Post text copied for LinkedIn.', 'success'); } else if (action === 'approve_brand') { showToast(copy.published, 'success'); } setMilestone(null); } catch (error) { showToast(error instanceof Error ? error.message : 'Could not save your choice', 'error'); } finally { setSaving(false); } }; if (!milestone) return null; return !open && setMilestone(null)}>
{copy.heading} {milestone.qrTitle} {copy.subtitle}
QR MASTERVerified
{milestone.threshold.toLocaleString(milestone.language === 'de' ? 'de-DE' : 'en-US')}
{milestone.language === 'de' ? 'eindeutige Scans' : 'unique scans'}
{milestone.card.label} ยท {milestone.card.title}

{copy.consent}

{preview}
{withName && setXHandle(event.target.value)} placeholder="@yourhandle" className="w-full rounded-md border border-slate-200 px-3 py-2 text-sm outline-none focus:border-violet-500 focus:ring-2 focus:ring-violet-100" />}
; }