vor marketing zu website umbenennung. stripe ist lauffähig
This commit is contained in:
@@ -13,11 +13,13 @@ const currencyFormatter = new Intl.NumberFormat("de-DE", {
|
||||
});
|
||||
|
||||
function PackageSummary({ pkg }: { pkg: CheckoutPackage }) {
|
||||
const isFree = pkg.price === 0;
|
||||
|
||||
return (
|
||||
<Card className="shadow-sm">
|
||||
<Card className={`shadow-sm ${isFree ? "opacity-75" : ""}`}>
|
||||
<CardHeader className="space-y-1">
|
||||
<CardTitle className="flex items-center gap-3 text-2xl">
|
||||
<PackageIcon className="h-6 w-6 text-primary" />
|
||||
<CardTitle className={`flex items-center gap-3 text-2xl ${isFree ? "text-muted-foreground" : ""}`}>
|
||||
<PackageIcon className={`h-6 w-6 ${isFree ? "text-muted-foreground" : "text-primary"}`} />
|
||||
{pkg.name}
|
||||
</CardTitle>
|
||||
<CardDescription className="text-base text-muted-foreground">
|
||||
@@ -26,10 +28,10 @@ function PackageSummary({ pkg }: { pkg: CheckoutPackage }) {
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
<div className="flex items-baseline gap-2">
|
||||
<span className="text-3xl font-semibold">
|
||||
<span className={`text-3xl font-semibold ${isFree ? "text-muted-foreground" : ""}`}>
|
||||
{pkg.price === 0 ? "Kostenlos" : currencyFormatter.format(pkg.price)}
|
||||
</span>
|
||||
<Badge variant="secondary" className="uppercase tracking-wider text-xs">
|
||||
<Badge variant={isFree ? "outline" : "secondary"} className="uppercase tracking-wider text-xs">
|
||||
{pkg.type === "reseller" ? "Reseller" : "Endkunde"}
|
||||
</Badge>
|
||||
</div>
|
||||
@@ -37,7 +39,7 @@ function PackageSummary({ pkg }: { pkg: CheckoutPackage }) {
|
||||
<ul className="space-y-3">
|
||||
{pkg.features.map((feature, index) => (
|
||||
<li key={index} className="flex items-start gap-3 text-sm text-muted-foreground">
|
||||
<Check className="mt-0.5 h-4 w-4 text-primary" />
|
||||
<Check className={`mt-0.5 h-4 w-4 ${isFree ? "text-muted-foreground" : "text-primary"}`} />
|
||||
<span>{feature}</span>
|
||||
</li>
|
||||
))}
|
||||
@@ -49,17 +51,23 @@ function PackageSummary({ pkg }: { pkg: CheckoutPackage }) {
|
||||
}
|
||||
|
||||
function PackageOption({ pkg, isActive, onSelect }: { pkg: CheckoutPackage; isActive: boolean; onSelect: () => void }) {
|
||||
const isFree = pkg.price === 0;
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onSelect}
|
||||
className={`w-full rounded-md border bg-background p-4 text-left transition focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 ${
|
||||
isActive ? "border-primary shadow-sm" : "border-border hover:border-primary/40"
|
||||
isActive
|
||||
? "border-primary shadow-sm"
|
||||
: isFree
|
||||
? "border-border hover:border-primary/40 opacity-75 hover:opacity-100"
|
||||
: "border-border hover:border-primary/40"
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between text-sm font-medium">
|
||||
<span>{pkg.name}</span>
|
||||
<span className="text-muted-foreground">
|
||||
<span className={isFree ? "text-muted-foreground" : ""}>{pkg.name}</span>
|
||||
<span className={isFree ? "text-muted-foreground font-normal" : "text-muted-foreground"}>
|
||||
{pkg.price === 0 ? "Kostenlos" : currencyFormatter.format(pkg.price)}
|
||||
</span>
|
||||
</div>
|
||||
@@ -72,9 +80,28 @@ export const PackageStep: React.FC = () => {
|
||||
const { selectedPackage, packageOptions, setSelectedPackage, resetPaymentState, nextStep } = useCheckoutWizard();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
|
||||
// Early return if no package is selected
|
||||
if (!selectedPackage) {
|
||||
return (
|
||||
<div className="text-center py-8">
|
||||
<p className="text-muted-foreground">Kein Paket ausgewählt. Bitte wähle ein Paket aus der Paketübersicht.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const comparablePackages = useMemo(() => {
|
||||
return packageOptions.filter((pkg) => pkg.type === selectedPackage.type);
|
||||
}, [packageOptions, selectedPackage.type]);
|
||||
// Filter by type and sort: free packages first, then by price ascending
|
||||
return packageOptions
|
||||
.filter((pkg: CheckoutPackage) => pkg.type === selectedPackage.type)
|
||||
.sort((a: CheckoutPackage, b: CheckoutPackage) => {
|
||||
// Free packages first
|
||||
if (a.price === 0 && b.price > 0) return -1;
|
||||
if (a.price > 0 && b.price === 0) return 1;
|
||||
// Then sort by price ascending
|
||||
return a.price - b.price;
|
||||
});
|
||||
}, [packageOptions, selectedPackage]);
|
||||
|
||||
const handlePackageChange = (pkg: CheckoutPackage) => {
|
||||
if (pkg.id === selectedPackage.id) {
|
||||
|
||||
Reference in New Issue
Block a user