'use client'; import { useState } from 'react'; import type { Action, GameView } from '@/game/engine'; import { junctionTransportChoice, junctionTransportDestinations, junctionTransportOrigins, } from '@/game/junction-transport-options'; import type { HomeworldShipmentSources } from '@/game/homeworld-shipment-options'; import { Button } from './ui/button'; import { Input } from './ui/input'; export function JunctionTransport({ game: g, act, busy, }: { game: GameView; act: (action: Action) => void; busy: boolean; }) { const origins = junctionTransportOrigins(g); const destinations = junctionTransportDestinations(g); const [origin, setOrigin] = useState(origins[0]?.id ?? ''); const [destination, setDestination] = useState(destinations[0]?.id ?? ''); const [sources, setSources] = useState({}); const [allyPayment, setAllyPayment] = useState(0); const option = g.junctionTransport; const me = g.players.find((p) => p.id === g.me); if (!option || !me || ![option.owner, option.recipient].includes(me.id)) return null; const recipient = g.players.find((p) => p.id === option.recipient); if (me.id === option.owner) return (
Offer Junction transport

Junction allows you to offer {recipient?.name ?? 'the active faction'}{' '} cross-shipment at half or full price, including travel to and from Homeworlds. They choose whether to use it for their shipment.

{g.karamaShipping?.player === option.recipient && (

Junction’s permission and offered tariff resist Karama. If the recipient uses this offer, their separate purchased price ends unused; its played card is not refunded.

)} {option.offer && (

Current offer: {option.offer.rate} price.

)} {option.blocked && ( {option.blocked} )}
{(['half', 'full'] as const).map((rate) => ( ))}
); const selectedOrigin = origins.find((candidate) => candidate.id === origin); const selected = Object.fromEntries( (selectedOrigin?.pools ?? []).flatMap((pool) => { const chosen = sources[pool.key]; return chosen && chosen.normal + chosen.elite > 0 ? [[pool.key, chosen]] : []; }), ); const quote = junctionTransportChoice(g, destination, selected, allyPayment); return (
Junction transport{option.offer ? ` · ${option.offer.rate} price` : ''}

Guild’s offer allows one transport from an Arrakis territory or Homeworld, including a return to your own Homeworld. This uses your shipment; movement remains available.

{!option.offer ? ( Guild has not offered transport for this shipment. Your ordinary actions remain available. ) : ( <>

One force costs one spice to a Homeworld or stronghold, two elsewhere. The Guild’s {option.offer.rate}-price offer applies to the total; fractions round up.

{quote.forfeitPurchasedRate && (

This immune Junction offer keeps its {option.offer.rate} tariff and normal payment recipients. Your separate purchased Karama price will end unused if you accept; its played card is not refunded. You may instead choose an ordinary purchased-price route.

)} {option.blocked && ( {option.blocked} )}
{selectedOrigin?.pools.map((pool) => (

{pool.name} {pool.sector && pool.sector === g.storm ? ' · blocked by storm' : ''}

{(['normal', 'elite'] as const) .filter((kind) => kind === 'normal' || pool.elite > 0) .map((kind) => ( ))}
))} {me.ally && ( )}

Your available spice: {me.spice ?? 0}. Allied pledge:{' '} {g.aid.available}.

{quote.amount} forces ({quote.elite} special) · {quote.cost} spice {quote.amount > 0 ? ` · you pay ${quote.ownPayment}, ally pays ${quote.allyPayment}` : ''} {quote.advisors ? ' · arrives as advisors' : ''}. {quote.blocked ? ` ${quote.blocked}` : ''}
)}
); }