Les comptes déjà créés ne sont pas inscrits. Le choix est facultatif à l’inscription et dans les paramètres. Un lien public demande confirmation avant d’arrêter les actualités, sans toucher aux messages de compte.
122 lines
4.4 KiB
TypeScript
122 lines
4.4 KiB
TypeScript
'use client'
|
|
|
|
import { Suspense, useEffect, useState } from 'react'
|
|
import Link from 'next/link'
|
|
import { useSearchParams } from 'next/navigation'
|
|
import { CheckCircle2, AlertCircle, Mail } from 'lucide-react'
|
|
import { useLanguage } from '@/lib/i18n'
|
|
import { confirmMarketingUnsubscribe, previewUnsubscribeToken } from '@/app/actions/marketing-unsubscribe'
|
|
|
|
function UnsubscribeContent() {
|
|
const { t } = useLanguage()
|
|
const searchParams = useSearchParams()
|
|
const token = searchParams.get('token') || ''
|
|
const [status, setStatus] = useState<'idle' | 'saving' | 'ok' | 'already' | 'invalid'>(
|
|
token ? 'idle' : 'invalid',
|
|
)
|
|
|
|
useEffect(() => {
|
|
if (!token) return
|
|
let cancelled = false
|
|
void previewUnsubscribeToken(token).then((result) => {
|
|
if (!cancelled && !result.valid) setStatus('invalid')
|
|
})
|
|
return () => {
|
|
cancelled = true
|
|
}
|
|
}, [token])
|
|
|
|
const confirm = async () => {
|
|
if (!token) {
|
|
setStatus('invalid')
|
|
return
|
|
}
|
|
setStatus('saving')
|
|
const result = await confirmMarketingUnsubscribe(token)
|
|
if (result.invalid || !result.ok) setStatus('invalid')
|
|
else if (result.already) setStatus('already')
|
|
else setStatus('ok')
|
|
}
|
|
|
|
if (status === 'ok' || status === 'already') {
|
|
return (
|
|
<div className="bg-white dark:bg-[var(--background)]/50 border border-[var(--border)] p-8 md:p-10 rounded-[48px] shadow-2xl text-center space-y-6">
|
|
<div className="w-14 h-14 mx-auto rounded-2xl bg-emerald-500/10 flex items-center justify-center">
|
|
<CheckCircle2 size={28} className="text-emerald-600" />
|
|
</div>
|
|
<div className="space-y-2">
|
|
<h1 className="text-2xl font-serif font-bold">{t('unsubscribe.successTitle')}</h1>
|
|
<p className="text-sm text-[var(--muted-foreground)] leading-relaxed">
|
|
{t('unsubscribe.successBody')}
|
|
</p>
|
|
</div>
|
|
<Link href="/login" className="block text-sm font-medium text-[var(--color-brand-accent)] hover:underline">
|
|
{t('unsubscribe.backToSignIn')}
|
|
</Link>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (status === 'invalid') {
|
|
return (
|
|
<div className="bg-white dark:bg-[var(--background)]/50 border border-[var(--border)] p-8 md:p-10 rounded-[48px] shadow-2xl text-center space-y-6">
|
|
<div className="w-14 h-14 mx-auto rounded-2xl bg-red-500/10 flex items-center justify-center">
|
|
<AlertCircle size={28} className="text-red-500" />
|
|
</div>
|
|
<div className="space-y-2">
|
|
<h1 className="text-2xl font-serif font-bold">{t('unsubscribe.invalidTitle')}</h1>
|
|
<p className="text-sm text-[var(--muted-foreground)] leading-relaxed">
|
|
{t('unsubscribe.invalidBody')}
|
|
</p>
|
|
</div>
|
|
<Link href="/settings/general" className="block text-sm font-medium text-[var(--color-brand-accent)] hover:underline">
|
|
{t('unsubscribe.openSettings')}
|
|
</Link>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="bg-white dark:bg-[var(--background)]/50 border border-[var(--border)] p-8 md:p-10 rounded-[48px] shadow-2xl text-center space-y-6">
|
|
<div className="w-14 h-14 mx-auto rounded-2xl bg-[var(--color-brand-accent)]/10 flex items-center justify-center">
|
|
<Mail size={28} className="text-[var(--color-brand-accent)]" />
|
|
</div>
|
|
<div className="space-y-2">
|
|
<h1 className="text-2xl font-serif font-bold">{t('unsubscribe.title')}</h1>
|
|
<p className="text-sm text-[var(--muted-foreground)] leading-relaxed">
|
|
{t('unsubscribe.body')}
|
|
</p>
|
|
</div>
|
|
<form
|
|
onSubmit={(e) => {
|
|
e.preventDefault()
|
|
void confirm()
|
|
}}
|
|
className="space-y-3"
|
|
>
|
|
<button
|
|
type="submit"
|
|
disabled={status === 'saving'}
|
|
className="w-full bg-[var(--foreground)] text-[var(--background)] py-4 rounded-2xl font-bold uppercase tracking-[0.2em] text-[10px] transition-all hover:shadow-xl active:scale-[0.98] disabled:opacity-50"
|
|
>
|
|
{t('unsubscribe.confirm')}
|
|
</button>
|
|
<Link
|
|
href="/home"
|
|
className="block text-xs text-[var(--muted-foreground)] hover:text-[var(--foreground)]"
|
|
>
|
|
{t('unsubscribe.keep')}
|
|
</Link>
|
|
</form>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default function UnsubscribePage() {
|
|
return (
|
|
<Suspense fallback={null}>
|
|
<UnsubscribeContent />
|
|
</Suspense>
|
|
)
|
|
}
|