import { useState, useEffect } from "react"; import { Modal, Button, Form, Table, Alert } from "react-bootstrap"; import { generateQr, GroupState, OrderGroup, OrderGroupMember, QrRecipient } from "../../../../types"; import { sanitizeQrMessage } from "../../Utils"; import { computeFeeShare, computeMemberTotal, countActiveMembers, isActiveMember } from "../../utils/groupFees"; type Props = { isOpen: boolean; onClose: () => void; onSuccess?: () => void; group: OrderGroup; payerLogin: string; bankAccount: string; bankAccountHolder: string; groupId?: string; }; type DinerEntry = { login: string; member: OrderGroupMember; included: boolean; }; export default function PayForGroupModal({ isOpen, onClose, onSuccess, group, payerLogin, bankAccount, bankAccountHolder, groupId }: Readonly) { const [diners, setDiners] = useState([]); const [error, setError] = useState(null); const [loading, setLoading] = useState(false); const [success, setSuccess] = useState(false); useEffect(() => { if (!isOpen) return; const entries: DinerEntry[] = (Object.entries(group.members) as [string, OrderGroupMember][]).map(([login, member]) => ({ login, member, // Standardně zahrnout všechny, kdo nejsou plátce a něco si objednali. included: login !== payerLogin && isActiveMember(member), })); setDiners(entries); setError(null); setSuccess(false); }, [isOpen, group, payerLogin]); const fees = group.fees ?? 0; const shipping = group.shipping ?? 0; const tip = group.tip ?? 0; const totalFees = fees + shipping + tip; // Poplatky se dělí jen mezi aktivní strávníky (kdo si reálně něco objednal). const activeCount = countActiveMembers(group.members); const feeShare = computeFeeShare(totalFees, activeCount); const feeParams = { totalFees, discountType: group.discountType, discountValue: group.discountValue ?? 0 }; const getMemberTotal = (entry: DinerEntry): number => computeMemberTotal(entry.member, feeParams, feeShare, activeCount); const includedNonPayers = diners.filter(d => d.included && d.login !== payerLogin); const handleInclude = (login: string, checked: boolean) => { setDiners(prev => prev.map(d => d.login === login ? { ...d, included: checked } : d)); }; const handleGenerate = async () => { setError(null); const recipients: QrRecipient[] = []; for (const d of diners) { if (!d.included || d.login === payerLogin) continue; const total = getMemberTotal(d); if (total <= 0) { setError(`Celková částka pro ${d.login} musí být kladná`); return; } const note = d.member.note?.trim(); recipients.push({ login: d.login, purpose: sanitizeQrMessage(note || `Objednávka ${group.name}`), amount: total, }); } if (recipients.length === 0) { setError("Nebyl vybrán žádný příjemce"); return; } setLoading(true); try { const response = await generateQr({ body: { recipients, bankAccount, bankAccountHolder, ...(groupId ? { groupId } : {}) }, }); if (response.error) { setError((response.error as any).error || 'Nastala chyba při generování QR kódů'); } else { setSuccess(true); onSuccess?.(); setTimeout(() => onClose(), 2000); } } catch (e: any) { setError(e.message || 'Nastala chyba při generování QR kódů'); } finally { setLoading(false); } }; const hasFees = totalFees > 0; // Generování QR je poslední krok objednávky — server skupinu zároveň překlopí do stavu Doručeno const willBeMarkedDelivered = group.state !== GroupState.DELIVERED; return (

Generovat QR — {group.name}

{success ? ( QR kódy byly úspěšně vygenerovány! Uživatelé je uvidí v sekci „Nevyřízené platby". ) : ( <> {willBeMarkedDelivered && ( Objednávka není ve stavu Doručeno — vygenerováním QR kódů se do tohoto stavu automaticky přepne. )}

Zaplatili jste za skupinu. Vyberte, komu vygenerovat QR kód k úhradě.

{error && ( setError(null)} dismissible> {error} )} {hasFees && (
{fees > 0 && Poplatky: {fees / 100} Kč} {shipping > 0 && Doprava: {shipping / 100} Kč} {tip > 0 && Spropitné: {tip / 100} Kč} → {feeShare / 100} Kč/os.
)} {group.discountValue != null && group.discountValue > 0 && (
Sleva: {group.discountType === 'percent' ? `${group.discountValue}%` : `${group.discountValue / 100} Kč`}
)} {hasFees && } {diners.map(d => { const isPayer = d.login === payerLogin; const active = isActiveMember(d.member); const total = getMemberTotal(d); const surcharge = d.member.surchargeAmount ?? 0; return ( {hasFees && ( )} ); })}
Člen Základ PříplatekPoplatekCelkem
{isPayer ? ( plátce ) : !active ? ( jen objednává ) : ( handleInclude(d.login, e.target.checked)} /> )} {d.login} {d.member.surchargeText && ( ({d.member.surchargeText}) )} {(d.member.amount ?? 0) > 0 ? `${d.member.amount! / 100} Kč` : —} {surcharge > 0 ? `${surcharge / 100} Kč` : —} {active && feeShare > 0 ? `${feeShare / 100} Kč` : '—'} {total > 0 ? `${total / 100} Kč` : —}
)}
{!success && ( <> Příjemci: {includedNonPayers.length} )} {success && ( )}
); }