Support Truthtrance No-Field shipment promises
Verify and publish checkpoint container / container (push) Canceled after 0s

This commit is contained in:
Quintine committed 2026-10-29 10:07:00 +11:00
1 parent 9ab9b9a613
commit 7fccd62814
16 files changed
+658 -32

No files matched your search

+23 -2
View File
@@ -8,15 +8,18 @@ import {
} from '@/game/shipment-promises';
import { shipmentExpressionInputError, shipmentExpressionInputSize } from '@/game/shipment-expression-input';
import { ShipmentClauseFields } from './shipment-claim-fields';
import { TruthNoFieldShipmentFields } from './truth-no-field-shipment-fields';
import { Button } from './ui/button';
const newLeaf = (): ShipmentExpression => ({ territory: 'carthag', minimum: 1 });
/** Hook-free controlled tree. Stateful leaf descendants are rendered by React. */
export function ShipmentExpressionFields({ value, id = 'truth-shipment', disabled, onChange }: {
export function ShipmentExpressionFields({ value, id = 'truth-shipment', disabled, allowNoField = false, onChange }: {
value: ShipmentExpression;
id?: string;
disabled: boolean;
/** Expose the public marker question only for an eligible Richese target. */
allowNoField?: boolean;
onChange: (expression: ShipmentExpression) => void;
}) {
const size = shipmentExpressionInputSize(value);
@@ -30,6 +33,7 @@ export function ShipmentExpressionFields({ value, id = 'truth-shipment', disable
remove?: () => ShipmentExpression,
): ReactElement => {
const group = 'op' in node;
const marker = !group && 'kind' in node && node.kind === 'noField';
const allowed = (next: ShipmentExpression) => !disabled && !shipmentExpressionInputError(replace(next));
const change = (next: ShipmentExpression) => commit(replace(next));
const wrap = (op: 'and' | 'or'): ShipmentExpression => ({ op, terms: [node, newLeaf()] });
@@ -63,7 +67,24 @@ export function ShipmentExpressionFields({ value, id = 'truth-shipment', disable
</div>
</> : 'constant' in node ? <p className="notice" role="alert">
Frozen current facts are unavailable in a pure shipment question. Remove this condition.
</p> : <ShipmentClauseFields id={`${id}-${path}`} value={node} onChange={change} />}
</p> : <>
{(allowNoField || marker) && <>
<label htmlFor={`${id}-${path}-condition-type`}>Shipment condition type</label>
<select id={`${id}-${path}-condition-type`} value={marker ? 'noField' : 'physical'}
disabled={disabled} onChange={event => {
const kind = event.currentTarget.value;
if (kind === 'physical') change(newLeaf());
else if (kind === 'noField' && allowNoField) change({ kind: 'noField' });
}}>
<option value="physical">Physical forces from reserves</option>
<option value="noField" disabled={!allowNoField}>Owned No-Field from reserves</option>
</select>
</>}
{marker ? <>
{!allowNoField && <p className="notice">Choose Richese for a No-Field shipment condition, or change this condition to physical forces.</p>}
<TruthNoFieldShipmentFields id={`${id}-${path}`} value={node} disabled={disabled || !allowNoField} onChange={change} />
</> : 'minimum' in node ? <ShipmentClauseFields id={`${id}-${path}`} value={node} onChange={change} /> : null}
</>}
<div className="flex flex-wrap gap-2">
<Button type="button" data-shipment-expression-control={`and-${path}`} disabled={!allowed(wrap('and'))}
onClick={() => change(wrap('and'))}>Group with AND</Button>