mirror of
https://github.com/Patiun/com.gregkilmer.www.git
synced 2026-11-08 04:08:24 +00:00
Images and content updates
This commit is contained in:
@@ -38,15 +38,34 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
interface ColorOption {
|
||||
name: string;
|
||||
hex: string;
|
||||
inStock: boolean;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
/** Public Cloudflare Turnstile site key. Omit to skip Turnstile (e.g. dev). */
|
||||
turnstileSiteKey?: string;
|
||||
/**
|
||||
* Available filament colors for printed items, from store-products.ts. Only
|
||||
* in-stock colors are offered in the color dropdown. Omit to hide the color
|
||||
* selector entirely (e.g. if no colors are configured).
|
||||
*/
|
||||
colors?: ColorOption[];
|
||||
}
|
||||
|
||||
export default function OrderForm({ turnstileSiteKey }: Props) {
|
||||
export default function OrderForm({ turnstileSiteKey, colors = [] }: Props) {
|
||||
const [status, setStatus] = useState<Status>('idle');
|
||||
const [errors, setErrors] = useState<FieldErrors>({});
|
||||
const [errorMsg, setErrorMsg] = useState<string>('');
|
||||
// Tracks the order type so the color selector can show/hide. Mirrors the
|
||||
// <select name="orderType"> so the two stay in sync.
|
||||
const [orderType, setOrderType] = useState<OrderType>('cards');
|
||||
|
||||
// Colors currently offered = in-stock only. Empty when none configured.
|
||||
const availableColors = colors.filter((c) => c.inStock);
|
||||
const showColors = availableColors.length > 0 && (orderType === 'deckBoxes' || orderType === 'both');
|
||||
|
||||
const turnstileTokenRef = useRef<string>('');
|
||||
const turnstileWidgetIdRef = useRef<string | null>(null);
|
||||
@@ -97,6 +116,7 @@ export default function OrderForm({ turnstileSiteKey }: Props) {
|
||||
name: string;
|
||||
email: string;
|
||||
orderType: OrderType;
|
||||
color: string;
|
||||
quantity: string;
|
||||
details: string;
|
||||
notes: string;
|
||||
@@ -125,6 +145,7 @@ export default function OrderForm({ turnstileSiteKey }: Props) {
|
||||
name: String(data.get('name') ?? '').trim(),
|
||||
email: String(data.get('email') ?? '').trim(),
|
||||
orderType: (String(data.get('orderType') ?? 'cards') as OrderType),
|
||||
color: String(data.get('color') ?? '').trim(),
|
||||
quantity: String(data.get('quantity') ?? '').trim(),
|
||||
details: String(data.get('details') ?? '').trim(),
|
||||
notes: String(data.get('notes') ?? '').trim(),
|
||||
@@ -224,13 +245,37 @@ export default function OrderForm({ turnstileSiteKey }: Props) {
|
||||
|
||||
<div className="flex flex-col">
|
||||
<label htmlFor="orderType" className={labelBase} style={fieldColor}>Order type</label>
|
||||
<select id="orderType" name="orderType" defaultValue="cards" className={inputBase} style={{ borderColor: 'var(--color-border)', ...fieldColor }}>
|
||||
<select
|
||||
id="orderType"
|
||||
name="orderType"
|
||||
value={orderType}
|
||||
onChange={(e) => setOrderType(e.target.value as OrderType)}
|
||||
className={inputBase}
|
||||
style={{ borderColor: 'var(--color-border)', ...fieldColor }}
|
||||
>
|
||||
<option value="cards">Proxy MTG cards</option>
|
||||
<option value="deckBoxes">3D-printed deck box / counters</option>
|
||||
<option value="both">Both</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Color selector — only for printed items, only when colors are
|
||||
configured and in stock. The list comes from store-products.ts. */}
|
||||
{showColors && (
|
||||
<div className="flex flex-col">
|
||||
<label htmlFor="color" className={labelBase} style={fieldColor}>Print color</label>
|
||||
<select id="color" name="color" defaultValue="" className={inputBase} style={{ borderColor: 'var(--color-border)', ...fieldColor }}>
|
||||
<option value="" disabled>Select a color…</option>
|
||||
{availableColors.map((c) => (
|
||||
<option key={c.name} value={c.name}>{c.name}</option>
|
||||
))}
|
||||
</select>
|
||||
<p className="mt-1 text-xs" style={{ color: 'var(--color-text-subtle)' }}>
|
||||
Colors shown are what’s loaded right now. See the deck-boxes page for swatches.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col">
|
||||
<label htmlFor="quantity" className={labelBase} style={fieldColor}>Approximate quantity</label>
|
||||
<input id="quantity" name="quantity" type="text" placeholder="e.g. 75 cards, or 1 deck box + 4 counters" className={inputBase} style={{ borderColor: borderFor('quantity'), ...fieldColor }} aria-invalid={Boolean(errors.quantity)} aria-describedby={errors.quantity ? 'quantity-error' : undefined} />
|
||||
|
||||
Reference in New Issue
Block a user