Files
fotospiel-app/resources/js/pages/marketing/checkout/CheckoutWizard.tsx

122 lines
3.9 KiB
TypeScript

import React, { useMemo } from "react";
import { useTranslation } from 'react-i18next';
import { Steps } from "@/components/ui/Steps";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
import { CheckoutWizardProvider, useCheckoutWizard } from "./WizardContext";
import type { CheckoutPackage, CheckoutStepId } from "./types";
import { PackageStep } from "./steps/PackageStep";
import { AuthStep } from "./steps/AuthStep";
import { PaymentStep } from "./steps/PaymentStep";
import { ConfirmationStep } from "./steps/ConfirmationStep";
interface CheckoutWizardProps {
initialPackage: CheckoutPackage;
packageOptions: CheckoutPackage[];
stripePublishableKey: string;
privacyHtml: string;
initialAuthUser?: {
id: number;
email: string;
name?: string;
pending_purchase?: boolean;
} | null;
initialStep?: CheckoutStepId;
}
const baseStepConfig: { id: CheckoutStepId; titleKey: string; descriptionKey: string; detailsKey: string }[] = [
{
id: "package",
titleKey: 'checkout.package_step.title',
descriptionKey: 'checkout.package_step.subtitle',
detailsKey: 'checkout.package_step.description'
},
{
id: "auth",
titleKey: 'checkout.auth_step.title',
descriptionKey: 'checkout.auth_step.subtitle',
detailsKey: 'checkout.auth_step.description'
},
{
id: "payment",
titleKey: 'checkout.payment_step.title',
descriptionKey: 'checkout.payment_step.subtitle',
detailsKey: 'checkout.payment_step.description'
},
{
id: "confirmation",
titleKey: 'checkout.confirmation_step.title',
descriptionKey: 'checkout.confirmation_step.subtitle',
detailsKey: 'checkout.confirmation_step.description'
},
];
const WizardBody: React.FC<{ stripePublishableKey: string; privacyHtml: string }> = ({ stripePublishableKey, privacyHtml }) => {
const { t } = useTranslation('marketing');
const { currentStep, nextStep, previousStep } = useCheckoutWizard();
const stepConfig = useMemo(() =>
baseStepConfig.map(step => ({
id: step.id,
title: t(step.titleKey),
description: t(step.descriptionKey),
details: t(step.detailsKey),
})),
[t]
);
const currentIndex = useMemo(() => stepConfig.findIndex((step) => step.id === currentStep), [currentStep]);
const progress = useMemo(() => {
if (currentIndex < 0) {
return 0;
}
return (currentIndex / (stepConfig.length - 1)) * 100;
}, [currentIndex, stepConfig]);
return (
<div className="space-y-8">
<div className="space-y-4">
<Progress value={progress} />
<Steps steps={stepConfig} currentStep={currentIndex >= 0 ? currentIndex : 0} />
</div>
<div className="space-y-6">
{currentStep === "package" && <PackageStep />}
{currentStep === "auth" && <AuthStep privacyHtml={privacyHtml} />}
{currentStep === "payment" && <PaymentStep stripePublishableKey={stripePublishableKey} />}
{currentStep === "confirmation" && <ConfirmationStep />}
</div>
<div className="flex items-center justify-between">
<Button variant="ghost" onClick={previousStep} disabled={currentIndex <= 0}>
{t('checkout.back')}
</Button>
<Button onClick={nextStep} disabled={currentIndex >= stepConfig.length - 1}>
{t('checkout.next')}
</Button>
</div>
</div>
);
};
export const CheckoutWizard: React.FC<CheckoutWizardProps> = ({
initialPackage,
packageOptions,
stripePublishableKey,
privacyHtml,
initialAuthUser,
initialStep,
}) => {
return (
<CheckoutWizardProvider
initialPackage={initialPackage}
packageOptions={packageOptions}
initialStep={initialStep}
initialAuthUser={initialAuthUser ?? undefined}
initialIsAuthenticated={Boolean(initialAuthUser)}
>
<WizardBody stripePublishableKey={stripePublishableKey} privacyHtml={privacyHtml} />
</CheckoutWizardProvider>
);
};