import * as React from 'react';
import { __ } from '@wordpress/i18n';
import { BookingApi } from './api';
import { majorText, minorAmount, money } from './pricing';
import type { Booking } from './types';
export interface FinancialState {
required_amount: number;
paid_amount: number;
refunded_amount: number;
net_paid_amount: number;
outstanding_amount: number;
refund_due: number;
payment_status: string;
}
interface CancellationQuote extends FinancialState {
standard_fee: number;
calculated_fee: number;
minutes_before_start: number;
}
export function FinancialSummary({ booking: b }: {
booking: Booking;
}) {
return
- {__('Original booking price', 'abece-booking')}
- {money(b.final_amount, b.currency)}
- {__('Paid', 'abece-booking')}
- {money(b.financial.paid_amount, b.currency)}
- {__('Refunded', 'abece-booking')}
- {money(b.financial.refunded_amount, b.currency)}
{b.status === 'cancelled' && <>- {__('Cancellation fee', 'abece-booking')}
- {money(b.cancellation_fee, b.currency)}
>}{b.status === 'no_show' && <>- {__('No-show fee', 'abece-booking')}
- {money(b.no_show_fee, b.currency)}
>}- {__('Outstanding', 'abece-booking')}
- {money(b.financial.outstanding_amount, b.currency)}
- {__('Refund due', 'abece-booking')}
- {money(b.financial.refund_due, b.currency)}
;
}
export function CancellationForm({ booking: b, api, onChanged }: {
booking: Booking;
api: BookingApi;
onChanged: (b: Booking) => void;
}) {
const [scopeOpen, setScopeOpen] = React.useState(false);
const scoped = false;
const [reason, setReason] = React.useState('');
const [mode, setMode] = React.useState('standard');
const [custom, setCustom] = React.useState('0');
const [quote, setQuote] = React.useState<{
key: string;
value: CancellationQuote;
} | null>(null);
const [error, setError] = React.useState('');
const [busy, setBusy] = React.useState(false);
const [revision, setRevision] = React.useState(0);
const key = JSON.stringify([b.id, mode, custom, reason, revision]);
function payload() { return { mode, reason, ...(mode === 'custom' ? { custom_fee: minorAmount(custom, b.currency, true) } : {}) }; }
React.useEffect(() => {
let live = true;
setQuote(null);
setError('');
const timer = window.setTimeout(() => {
let body;
try {
body = payload();
}
catch (e) {
setError((e as Error).message);
return;
}
api.request(`bookings/${b.id}/cancellation-quote`, 'POST', body).then(value => { if (live)
setQuote({ key, value }); }).catch(e => { if (live)
setError(e.message); });
}, 200);
return () => { live = false; window.clearTimeout(timer); };
}, [api, key]);
async function confirm() {
if (quote?.key !== key)
return;
setBusy(true);
setError('');
try {
onChanged(await api.request(`bookings/${b.id}/cancel`, 'POST', { ...payload(), expected_fee: quote.value.calculated_fee }));
}
catch (e) {
setError((e as Error).message);
setRevision(v => v + 1);
}
finally {
setBusy(false);
}
}
const current = quote?.key === key ? quote.value : null;
return <>{false}>;
}
export function RefundForm({ booking: b, api, onChanged }: {
booking: Booking;
api: BookingApi;
onChanged: (b: Booking) => void;
}) {
const [amount, setAmount] = React.useState(majorText(b.financial.refund_due, b.currency));
const [reason, setReason] = React.useState('');
const [busy, setBusy] = React.useState(false);
const [error, setError] = React.useState('');
const operation = React.useRef({ body: '', key: '' });
async function submit(e: React.FormEvent) {
e.preventDefault();
setBusy(true);
setError('');
try {
const body = { amount: minorAmount(amount, b.currency, true), reason };
const serialized = JSON.stringify(body);
if (operation.current.body !== serialized)
operation.current = { body: serialized, key: crypto.randomUUID() };
onChanged(await api.request(`bookings/${b.id}/refund`, 'POST', { ...body, idempotency_key: operation.current.key }));
}
catch (e) {
setError((e as Error).message);
}
finally {
setBusy(false);
}
}
return ;
}
export declare function FollowingBookingsOperation(props: {
booking: Booking;
api: BookingApi;
onChanged: (b: Booking) => void;
operation: "cancel" | "void";
initial: Record;
onBusyChange?: (busy: boolean) => void;
}): React.JSX.Element;