import { useState, useEffect, useMemo } from 'react'; import { X, CheckCircle, Loader2, Minus, Plus } from 'lucide-react'; import { useConfigurableCaps, useConfigureSubscription } from '../hooks/useConfigurableCaps'; interface ConfiguratorPanelProps { onClose: () => void; onSuccess?: () => void; } /** * "Anpassen" panel — lets a customer scale every configurable capability * (extra seats / sites / commands) UP-ONLY from the plan's included baseline. * Shows a live monthly delta and applies the change via POST /subscription/configure * (immediate prorated billing handled server-side). */ export function ConfiguratorPanel({ onClose, onSuccess }: ConfiguratorPanelProps) { const { data, isLoading, isError } = useConfigurableCaps(); const configure = useConfigureSubscription(); const [totals, setTotals] = useState>({}); const [isComplete, setIsComplete] = useState(false); const [error, setError] = useState(null); // Seed local desired totals from the server snapshot once it loads. useEffect(() => { if (!data?.items) return; const seed: Record = {}; for (const item of data.items) seed[item.capabilityKey] = item.currentTotal; setTotals(seed); }, [data]); useEffect(() => { if (!isComplete) return; const timer = setTimeout(() => { onSuccess?.(); onClose(); }, 1800); return () => clearTimeout(timer); }, [isComplete, onSuccess, onClose]); const currency = (data?.currency ?? 'EUR').toUpperCase(); const items = data?.items ?? []; const clamp = (total: number, included: number, max: number | null) => { let next = Math.floor(total); if (next < included) next = included; if (max != null && next > max) next = max; return next; }; const monthlyDelta = useMemo(() => { let sum = 0; for (const item of items) { const total = totals[item.capabilityKey] ?? item.included; const extra = Math.max(0, total - item.included); if (extra > 0 && item.unitPrice) sum += extra * item.unitPrice; } return Number(sum.toFixed(2)); }, [items, totals]); const dirty = useMemo( () => items.some((item) => (totals[item.capabilityKey] ?? item.currentTotal) !== item.currentTotal), [items, totals], ); const handleApply = () => { setError(null); const payload = items.map((item) => ({ capabilityKey: item.capabilityKey, quantity: totals[item.capabilityKey] ?? item.included, })); configure.mutate(payload, { onSuccess: () => setIsComplete(true), onError: (err) => setError((err as Error).message || 'Failed to apply changes'), }); }; const label = (name: Record) => name.en ?? Object.values(name)[0] ?? ''; return ( <>