geschenkgutscheine implementiert ("Paket verschenken"). Neuer Upload-Provider: Sparkbooth.
This commit is contained in:
@@ -3,6 +3,7 @@ import { Badge } from '@/components/ui/badge';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { useLocalizedRoutes } from '@/hooks/useLocalizedRoutes';
|
||||
import { useLocale } from '@/hooks/useLocale';
|
||||
import MarketingLayout from '@/layouts/mainWebsite';
|
||||
import { Head, Link } from '@inertiajs/react';
|
||||
import { CheckCircle2, Sparkles } from 'lucide-react';
|
||||
@@ -18,6 +19,7 @@ interface DemoPageProps {
|
||||
const DemoPage: React.FC<DemoPageProps> = ({ demoToken }) => {
|
||||
const { t } = useTranslation('marketing');
|
||||
const { localizedPath } = useLocalizedRoutes();
|
||||
const locale = useLocale();
|
||||
const embedUrl = demoToken ? `/e/${demoToken}` : '/e/demo?demo=1';
|
||||
|
||||
const demo = t('demo_page', { returnObjects: true }) as {
|
||||
@@ -50,6 +52,16 @@ const DemoPage: React.FC<DemoPageProps> = ({ demoToken }) => {
|
||||
<Button asChild size="lg" variant="ghost" className="text-pink-600 hover:text-pink-700 dark:text-pink-300">
|
||||
<Link href={localizedPath('/so-funktionierts')}>{demo.secondaryCta}</Link>
|
||||
</Button>
|
||||
<Button
|
||||
asChild
|
||||
size="lg"
|
||||
variant="outline"
|
||||
className="border-pink-200 text-pink-600 hover:bg-pink-50 dark:border-pink-800 dark:text-pink-200"
|
||||
>
|
||||
<Link href={localizedPath(locale === 'en' ? '/gift-card' : '/gutschein')}>
|
||||
{t('packages.gift_cta', 'Paket verschenken')}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
|
||||
259
resources/js/pages/marketing/GiftVoucher.tsx
Normal file
259
resources/js/pages/marketing/GiftVoucher.tsx
Normal file
@@ -0,0 +1,259 @@
|
||||
import React from 'react';
|
||||
import MarketingLayout from '@/layouts/mainWebsite';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Gift } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { fetchGiftVoucherTiers, createGiftVoucherCheckout, type GiftVoucherTier } from '@/lib/giftVouchers';
|
||||
import { useLocalizedRoutes } from '@/hooks/useLocalizedRoutes';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
function useGiftVoucherTiers(initial: GiftVoucherTier[] = []) {
|
||||
const [tiers, setTiers] = React.useState<GiftVoucherTier[]>(initial);
|
||||
const [loading, setLoading] = React.useState(initial.length === 0);
|
||||
const [error, setError] = React.useState<string | null>(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (initial.length > 0) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
fetchGiftVoucherTiers()
|
||||
.then(setTiers)
|
||||
.catch((err) => setError(err?.message || 'Failed to load tiers'))
|
||||
.finally(() => setLoading(false));
|
||||
}, [initial]);
|
||||
|
||||
return { tiers, loading, error };
|
||||
}
|
||||
|
||||
function GiftVoucherPage({ tiers: initialTiers = [] }: { tiers: GiftVoucherTier[] }) {
|
||||
const { t } = useTranslation('marketing');
|
||||
const { locale } = useLocalizedRoutes();
|
||||
const { tiers, loading, error } = useGiftVoucherTiers(initialTiers);
|
||||
const [submitting, setSubmitting] = React.useState(false);
|
||||
const [serverError, setServerError] = React.useState<string | null>(null);
|
||||
const [form, setForm] = React.useState({
|
||||
tier_key: initialTiers.find((t) => t.can_checkout)?.key ?? '',
|
||||
purchaser_email: '',
|
||||
recipient_email: '',
|
||||
recipient_name: '',
|
||||
message: '',
|
||||
accept_terms: false,
|
||||
});
|
||||
const [errors, setErrors] = React.useState<Record<string, string | null>>({});
|
||||
|
||||
const selectedTierKey = form.tier_key;
|
||||
|
||||
const updateField = (key: keyof typeof form, value: string | boolean) => {
|
||||
setForm((prev) => ({ ...prev, [key]: value }));
|
||||
};
|
||||
|
||||
const validate = (): boolean => {
|
||||
const nextErrors: Record<string, string | null> = {};
|
||||
|
||||
if (!form.tier_key) {
|
||||
nextErrors.tier_key = t('gift.error_select_tier');
|
||||
}
|
||||
|
||||
if (!form.purchaser_email || !form.purchaser_email.includes('@')) {
|
||||
nextErrors.purchaser_email = t('gift.error_purchaser_email', 'Please enter a valid email.');
|
||||
}
|
||||
|
||||
if (form.recipient_email && !form.recipient_email.includes('@')) {
|
||||
nextErrors.recipient_email = t('gift.error_recipient_email', 'Please enter a valid email.');
|
||||
}
|
||||
|
||||
if (!form.accept_terms) {
|
||||
nextErrors.accept_terms = t('gift.accept_terms_required');
|
||||
}
|
||||
|
||||
setErrors(nextErrors);
|
||||
|
||||
return Object.keys(nextErrors).length === 0;
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
if (!validate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setSubmitting(true);
|
||||
setServerError(null);
|
||||
try {
|
||||
const successUrl = window.location.origin + `/${locale}/success?type=gift`;
|
||||
const returnUrl = window.location.origin + `/${locale}/gift-card`;
|
||||
const response = await createGiftVoucherCheckout({
|
||||
tier_key: form.tier_key,
|
||||
purchaser_email: form.purchaser_email,
|
||||
recipient_email: form.recipient_email || undefined,
|
||||
recipient_name: form.recipient_name || undefined,
|
||||
message: form.message || undefined,
|
||||
success_url: successUrl,
|
||||
return_url: returnUrl,
|
||||
});
|
||||
|
||||
if (response.checkout_url) {
|
||||
window.location.assign(response.checkout_url);
|
||||
} else {
|
||||
setServerError(t('gift.error_checkout'));
|
||||
}
|
||||
} catch (err: any) {
|
||||
setServerError(err?.message || t('gift.error_checkout'));
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<MarketingLayout title={t('gift.title')}>
|
||||
<section className="relative overflow-hidden bg-gradient-to-b from-background via-muted/40 to-background">
|
||||
<div className="absolute inset-0 opacity-10 blur-3xl bg-[radial-gradient(circle_at_20%_20%,#60a5fa,transparent_30%),radial-gradient(circle_at_80%_10%,#a855f7,transparent_25%),radial-gradient(circle_at_50%_80%,#22c55e,transparent_25%)]" />
|
||||
<div className="relative mx-auto flex max-w-5xl flex-col gap-10 px-4 py-16 sm:px-6 lg:px-8">
|
||||
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div className="space-y-3">
|
||||
<div className="inline-flex items-center gap-2 rounded-full bg-primary/10 px-3 py-1 text-xs font-semibold uppercase tracking-wide text-primary">
|
||||
<Gift className="h-4 w-4" />
|
||||
{t('gift.badge')}
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold leading-tight text-foreground sm:text-5xl font-display">
|
||||
{t('gift.headline')}
|
||||
</h1>
|
||||
<p className="max-w-3xl text-lg text-muted-foreground">{t('gift.subline')}</p>
|
||||
<p className="text-sm text-muted-foreground">{t('gift.validity')}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{error && <div className="rounded-md border border-destructive/50 bg-destructive/5 p-3 text-sm text-destructive">{error}</div>}
|
||||
|
||||
<div className="grid gap-6 lg:grid-cols-3">
|
||||
<div className="lg:col-span-2">
|
||||
{loading ? (
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
{Array.from({ length: 4 }).map((_, idx) => (
|
||||
<div key={idx} className="h-32 animate-pulse rounded-xl bg-muted" />
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
{tiers.map((tier) => (
|
||||
<Card
|
||||
key={tier.key}
|
||||
className={cn(
|
||||
'cursor-pointer transition hover:shadow-md',
|
||||
selectedTierKey === tier.key ? 'border-primary shadow-lg' : '',
|
||||
!tier.can_checkout && 'opacity-60'
|
||||
)}
|
||||
onClick={() => tier.can_checkout && setValue('tier_key', tier.key, { shouldValidate: true })}
|
||||
onClick={() => tier.can_checkout && updateField('tier_key', tier.key)}
|
||||
>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center justify-between">
|
||||
<span>{tier.label}</span>
|
||||
<span className="text-xl font-semibold">
|
||||
{tier.amount.toLocaleString()} {tier.currency}
|
||||
</span>
|
||||
</CardTitle>
|
||||
<CardDescription>{t('gift.card_subline')}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="text-sm text-muted-foreground space-y-1">
|
||||
<p>{t('gift.card_body')}</p>
|
||||
{!tier.can_checkout && <p className="text-destructive">{t('gift.not_available')}</p>}
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{errors.tier_key && <p className="mt-2 text-sm text-destructive">{errors.tier_key}</p>}
|
||||
<div className="mt-6 rounded-xl border border-primary/20 bg-primary/5 px-5 py-4 text-sm text-foreground shadow-sm">
|
||||
<p className="font-semibold">{t('gift.withdrawal.title')}</p>
|
||||
<p className="text-muted-foreground">{t('gift.withdrawal.body')}</p>
|
||||
<Button asChild variant="link" className="px-0 text-primary">
|
||||
<a href={locale === 'en' ? '/en/withdrawal' : '/de/widerrufsbelehrung'}>
|
||||
{t('gift.withdrawal.link', 'Widerrufsbelehrung öffnen')}
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Card className="shadow-lg">
|
||||
<CardHeader>
|
||||
<CardTitle>{t('gift.form_title')}</CardTitle>
|
||||
<CardDescription>{t('gift.form_subtitle')}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
<div className="space-y-1">
|
||||
<Label htmlFor="purchaser_email">{t('gift.purchaser_email')}</Label>
|
||||
<Input
|
||||
id="purchaser_email"
|
||||
type="email"
|
||||
placeholder="you@example.com"
|
||||
value={form.purchaser_email}
|
||||
onChange={(e) => updateField('purchaser_email', e.target.value)}
|
||||
/>
|
||||
{errors.purchaser_email && <p className="text-sm text-destructive">{errors.purchaser_email}</p>}
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label htmlFor="recipient_name">{t('gift.recipient_name')}</Label>
|
||||
<Input
|
||||
id="recipient_name"
|
||||
placeholder={t('gift.recipient_name_placeholder')}
|
||||
value={form.recipient_name}
|
||||
onChange={(e) => updateField('recipient_name', e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label htmlFor="recipient_email">{t('gift.recipient_email')}</Label>
|
||||
<Input
|
||||
id="recipient_email"
|
||||
type="email"
|
||||
placeholder="friend@example.com"
|
||||
value={form.recipient_email}
|
||||
onChange={(e) => updateField('recipient_email', e.target.value)}
|
||||
/>
|
||||
{errors.recipient_email && <p className="text-sm text-destructive">{errors.recipient_email}</p>}
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label htmlFor="message">{t('gift.message')}</Label>
|
||||
<Textarea
|
||||
id="message"
|
||||
rows={3}
|
||||
placeholder={t('gift.message_placeholder')}
|
||||
value={form.message}
|
||||
onChange={(e) => updateField('message', e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-start gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="accept_terms"
|
||||
className="mt-1 h-4 w-4 rounded border-muted-foreground/50"
|
||||
checked={form.accept_terms}
|
||||
onChange={(e) => updateField('accept_terms', e.target.checked)}
|
||||
/>
|
||||
<Label htmlFor="accept_terms" className="text-sm leading-tight text-muted-foreground">
|
||||
{t('gift.accept_terms')}
|
||||
</Label>
|
||||
</div>
|
||||
{errors.accept_terms && <p className="text-sm text-destructive">{errors.accept_terms}</p>}
|
||||
{serverError && <p className="text-sm text-destructive">{serverError}</p>}
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Button className="w-full" size="lg" disabled={submitting || loading} onClick={onSubmit}>
|
||||
{submitting ? t('gift.processing') : t('gift.cta')}
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</MarketingLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export default GiftVoucherPage;
|
||||
|
||||
GiftVoucherPage.layout = (page: React.ReactNode) => page;
|
||||
@@ -3,6 +3,7 @@ import { Head, Link } from '@inertiajs/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import MarketingLayout from '@/layouts/mainWebsite';
|
||||
import { useLocalizedRoutes } from '@/hooks/useLocalizedRoutes';
|
||||
import { useLocale } from '@/hooks/useLocale';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
@@ -40,6 +41,7 @@ const iconByUseCase: Record<string, React.ReactNode> = {
|
||||
const HowItWorks: React.FC = () => {
|
||||
const { t, ready } = useTranslation('marketing');
|
||||
const { localizedPath } = useLocalizedRoutes();
|
||||
const locale = useLocale();
|
||||
|
||||
if (!ready) {
|
||||
return (
|
||||
@@ -158,6 +160,16 @@ const HowItWorks: React.FC = () => {
|
||||
{hero.secondaryCta}
|
||||
</Link>
|
||||
</Button>
|
||||
<Button
|
||||
asChild
|
||||
size="lg"
|
||||
variant="ghost"
|
||||
className="text-pink-600 hover:bg-pink-50 dark:text-pink-200 dark:hover:bg-pink-900/30"
|
||||
>
|
||||
<Link href={localizedPath(locale === 'en' ? '/gift-card' : '/gutschein')}>
|
||||
{t('packages.gift_cta', 'Paket verschenken')}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
|
||||
@@ -14,6 +14,7 @@ import MarketingLayout from '@/layouts/mainWebsite';
|
||||
import { useAnalytics } from '@/hooks/useAnalytics';
|
||||
import { useCtaExperiment } from '@/hooks/useCtaExperiment';
|
||||
import { useLocalizedRoutes } from '@/hooks/useLocalizedRoutes';
|
||||
import { useLocale } from '@/hooks/useLocale';
|
||||
import { ArrowRight, Check, Star } from 'lucide-react';
|
||||
|
||||
interface Package {
|
||||
@@ -251,6 +252,7 @@ const Packages: React.FC<PackagesProps> = ({ endcustomerPackages, resellerPackag
|
||||
const mobileEndcustomerRef = useRef<HTMLDivElement | null>(null);
|
||||
const mobileResellerRef = useRef<HTMLDivElement | null>(null);
|
||||
const { localizedPath } = useLocalizedRoutes();
|
||||
const locale = useLocale();
|
||||
const { t } = useTranslation('marketing');
|
||||
const { t: tCommon } = useTranslation('common');
|
||||
const {
|
||||
@@ -883,6 +885,16 @@ const PackageDetailGrid: React.FC<PackageDetailGridProps> = ({
|
||||
{t('packages.contact_us')}
|
||||
</Link>
|
||||
</Button>
|
||||
<Button
|
||||
asChild
|
||||
size="lg"
|
||||
variant="ghost"
|
||||
className="rounded-full text-gray-900 hover:bg-white/60 dark:text-gray-100 dark:hover:bg-gray-800/70"
|
||||
>
|
||||
<Link href={localizedPath(locale === 'en' ? '/gift-card' : '/gutschein')}>
|
||||
{t('packages.gift_cta', 'Paket verschenken')}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-300">
|
||||
{t('packages.hero_secondary')}
|
||||
|
||||
@@ -2,67 +2,74 @@ import React from 'react';
|
||||
import { usePage, router } from '@inertiajs/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import MarketingLayout from '@/layouts/mainWebsite';
|
||||
import { Loader } from 'lucide-react';
|
||||
import { Loader, CheckCircle } from 'lucide-react';
|
||||
import { useLocalizedRoutes } from '@/hooks/useLocalizedRoutes';
|
||||
import { useLocale } from '@/hooks/useLocale';
|
||||
import { ADMIN_HOME_PATH } from '@/admin/constants';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
const Success: React.FC = () => {
|
||||
const { auth } = usePage<{ auth: { user?: { email_verified_at?: string | null } } }>().props;
|
||||
type SuccessProps = {
|
||||
type?: string;
|
||||
};
|
||||
|
||||
const GiftSuccess: React.FC = () => {
|
||||
const { t } = useTranslation('marketing');
|
||||
const { localizedPath } = useLocalizedRoutes();
|
||||
const locale = useLocale();
|
||||
|
||||
return (
|
||||
<MarketingLayout title={t('success.gift_title')}>
|
||||
<div className="min-h-screen bg-gradient-to-b from-background via-muted/30 to-background py-16">
|
||||
<div className="mx-auto max-w-3xl space-y-6 px-4 text-center sm:px-6">
|
||||
<CheckCircle className="mx-auto h-12 w-12 text-green-500" />
|
||||
<h1 className="text-3xl font-bold text-foreground">{t('success.gift_title')}</h1>
|
||||
<p className="text-muted-foreground">{t('success.gift_description')}</p>
|
||||
<div className="rounded-xl border bg-card p-6 text-left shadow-sm">
|
||||
<h2 className="text-lg font-semibold">{t('success.gift_bullets_title')}</h2>
|
||||
<ul className="mt-3 list-disc space-y-2 pl-5 text-muted-foreground">
|
||||
<li>{t('success.gift_bullet_email')}</li>
|
||||
<li>{t('success.gift_bullet_validity')}</li>
|
||||
<li>{t('success.gift_bullet_redeem')}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="flex justify-center">
|
||||
<Button asChild size="lg">
|
||||
<a href={localizedPath('/', locale || undefined)}>{t('success.gift_cta_home')}</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</MarketingLayout>
|
||||
);
|
||||
};
|
||||
|
||||
const AuthRedirectSuccess: React.FC<{ emailVerified?: boolean | null }> = ({ emailVerified }) => {
|
||||
const { t } = useTranslation('success');
|
||||
const { localizedPath } = useLocalizedRoutes();
|
||||
|
||||
if (auth.user && auth.user.email_verified_at) {
|
||||
if (emailVerified) {
|
||||
router.visit(ADMIN_HOME_PATH, { preserveState: false });
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen bg-gray-50">
|
||||
<div className="flex min-h-screen items-center justify-center bg-gray-50">
|
||||
<div className="text-center">
|
||||
<Loader className="animate-spin inline-block w-8 h-8 border border-2 border-blue-600 border-t-transparent rounded-full mx-auto mb-2" />
|
||||
<Loader className="mx-auto mb-2 inline-block h-8 w-8 animate-spin rounded-full border border-2 border-blue-600 border-t-transparent" />
|
||||
<p className="text-gray-600">{t('redirecting')}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (auth.user && !auth.user.email_verified_at) {
|
||||
return (
|
||||
<MarketingLayout title={t('verify_email')}>
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-md w-full bg-white rounded-lg shadow-md p-8">
|
||||
<div className="text-center">
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-4">{t('verify_email')}</h2>
|
||||
<p className="text-gray-600 mb-6">{t('check_email')}</p>
|
||||
<form method="POST" action="/email/verification-notification">
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-md font-medium transition duration-300"
|
||||
>
|
||||
{t('resend_verification')}
|
||||
</button>
|
||||
</form>
|
||||
<p className="mt-4 text-sm text-gray-600">
|
||||
{t('already_registered')}{' '}
|
||||
<a href={localizedPath('/login')} className="text-blue-600 hover:text-blue-500">
|
||||
{t('login')}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</MarketingLayout>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<MarketingLayout title={t('complete_purchase')}>
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-md w-full bg-white rounded-lg shadow-md p-8">
|
||||
<div className="flex min-h-screen items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="w-full max-w-md rounded-lg bg-white p-8 shadow-md">
|
||||
<div className="text-center">
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-4">{t('complete_purchase')}</h2>
|
||||
<p className="text-gray-600 mb-6">{t('login_to_continue')}</p>
|
||||
<h2 className="mb-4 text-2xl font-bold text-gray-900">{t('complete_purchase')}</h2>
|
||||
<p className="mb-6 text-gray-600">{t('login_to_continue')}</p>
|
||||
<a
|
||||
href={localizedPath('/login')}
|
||||
className="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-md font-medium transition duration-300 block mb-2"
|
||||
className="mb-2 block rounded-md bg-blue-600 px-6 py-2 font-medium text-white transition duration-300 hover:bg-blue-700"
|
||||
>
|
||||
{t('login')}
|
||||
</a>
|
||||
@@ -79,6 +86,18 @@ const Success: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const Success: React.FC<SuccessProps> = () => {
|
||||
const { auth } = usePage<{ auth: { user?: { email_verified_at?: string | null } } }>().props;
|
||||
const searchParams = typeof window !== 'undefined' ? new URLSearchParams(window.location.search) : new URLSearchParams();
|
||||
const type = searchParams.get('type');
|
||||
|
||||
if (type === 'gift') {
|
||||
return <GiftSuccess />;
|
||||
}
|
||||
|
||||
return <AuthRedirectSuccess emailVerified={auth.user?.email_verified_at} />;
|
||||
};
|
||||
|
||||
Success.layout = (page: React.ReactNode) => page;
|
||||
|
||||
export default Success;
|
||||
|
||||
Reference in New Issue
Block a user