Files
Dune/components/shipment-quote.tsx
T

100 lines
3.1 KiB
TypeScript

export type ShipmentQuoteProps = {
id?: string;
label?: string;
physicalForces?: number;
noField?: true;
quote: {
cost: number;
normalCost: number;
ownPayment: number;
pledgedPayment: number;
} | null;
funding: {
ownSpice: number;
pledgedSpice: number;
};
unavailableReasons?: readonly string[];
};
/** Displays only caller-supplied prices and private funding already authorized for
* this viewer. The caller validates the selection and controls action availability.
*/
export function ShipmentQuote({
id,
label = 'Reserve shipment',
physicalForces,
noField,
quote,
funding,
unavailableReasons = [],
}: ShipmentQuoteProps) {
return (
<section
id={id}
className="notice shipment-quote flex min-w-0 flex-col gap-3 text-sm leading-6"
aria-label={`${label} cost and funding`}
>
<div>
{label !== 'Reserve shipment' && (
<p className="m-0 font-semibold">{label}</p>
)}
<p className="m-0 text-base font-semibold text-[#efd9a8]">
{quote ? `Shipment cost: ${quote.cost} spice` : 'Shipment cost'}
</p>
{quote ? (
quote.normalCost !== quote.cost && (
<p className="m-0 text-sm leading-6">
Normal cost: {quote.normalCost} spice. The applicable rate is
included in your shipment cost.
</p>
)
) : (
<p className="m-0 text-sm leading-6">
{noField ? 'Choose a valid marker, force group and funding to see the payment breakdown.'
: 'Choose valid forces and funding to see the payment breakdown.'}
</p>
)}
</div>
<dl className="m-0 grid min-w-0 grid-cols-[minmax(0,1fr)_auto] gap-x-4 gap-y-1">
{physicalForces !== undefined && (
<>
<dt>Physical forces selected</dt>
<dd className="m-0 text-right tabular-nums">{physicalForces}</dd>
</>
)}
{noField && <>
<dt>Concealed No-Field selected</dt>
<dd className="m-0 text-right tabular-nums">1 marker</dd>
</>}
<dt>Your available spice</dt>
<dd className="m-0 text-right tabular-nums">{funding.ownSpice}</dd>
<dt>Available ally pledge</dt>
<dd className="m-0 text-right tabular-nums">{funding.pledgedSpice}</dd>
{quote && (
<>
<dt>Your payment</dt>
<dd className="m-0 text-right tabular-nums">{quote.ownPayment}</dd>
<dt>Ally pledge used</dt>
<dd className="m-0 text-right tabular-nums">
{quote.pledgedPayment}
</dd>
</>
)}
</dl>
{noField && <p className="m-0">
The concealed marker is billed as one shipment unit. It is excluded from the physical force count.
</p>}
{unavailableReasons.length > 0 && (
<div>
<p className="m-0 font-semibold">Shipment unavailable</p>
<ul className="m-0 list-disc space-y-1 pl-5">
{unavailableReasons.map((reason, index) => (
<li key={index}>{reason}</li>
))}
</ul>
</div>
)}
</section>
);
}