42 lines
1.8 KiB
TypeScript
42 lines
1.8 KiB
TypeScript
'use client';
|
|
|
|
import type { Action } from '@/game/engine';
|
|
import { Button } from './ui/button';
|
|
|
|
/** The same public opportunity is shown regardless of the Emperor's spice. */
|
|
export type EmperorExtortionPriorityView = {
|
|
event: string;
|
|
recipient: string;
|
|
canContinue: boolean;
|
|
};
|
|
|
|
export type EmperorExtortionPriorityProps = {
|
|
game: {
|
|
emperorExtortionPriority: EmperorExtortionPriorityView | null;
|
|
players: readonly { id: string; name: string }[];
|
|
};
|
|
act: (action: Action) => void;
|
|
busy: boolean;
|
|
};
|
|
|
|
/** The payer's normal Extortion choice remains pending until the Emperor
|
|
* completes this optional alliance opportunity. */
|
|
export function EmperorExtortionPriority({ game, act, busy }: EmperorExtortionPriorityProps) {
|
|
const priority = game.emperorExtortionPriority;
|
|
if (!priority) return null;
|
|
const event = priority.event;
|
|
const recipient = game.players.find(player => player.id === priority.recipient)?.name ?? 'the ally';
|
|
const canAct = () => !busy && game.emperorExtortionPriority === priority &&
|
|
priority.event === event && typeof event === 'string' && event.length > 0 && priority.canContinue;
|
|
|
|
return <section className="notice space-y-3" aria-label="Emperor Extortion opportunity" aria-live="polite">
|
|
<h3>Emperor alliance opportunity</h3>
|
|
<p>Before {recipient} makes the Extortion choice, the Emperor may share spice with their ally. The existing gift control shows any available amount.</p>
|
|
{priority.canContinue ? <Button className="game-action min-h-11 whitespace-normal"
|
|
data-testid="emperor-extortion-continue" disabled={!canAct()}
|
|
onClick={() => { if (canAct()) act({type:'emperorExtortionContinue', event}); }}>
|
|
Continue to Extortion
|
|
</Button> : <p>Waiting for the Emperor to continue.</p>}
|
|
</section>;
|
|
}
|