mirror of
https://github.com/Patiun/com.gregkilmer.www.git
synced 2026-11-08 04:08:24 +00:00
141 lines
6.4 KiB
Plaintext
141 lines
6.4 KiB
Plaintext
---
|
|
/**
|
|
* /store/order — Order request page
|
|
* ---------------------------------------------------------------------------
|
|
* Hard-gated by store-availability.json:
|
|
* - ordersOpen === false => renders a "closed" notice + email link, NO form.
|
|
* - ordersOpen === true => renders the OrderForm island + slot meters +
|
|
* the requirements list.
|
|
*
|
|
* The server endpoint /api/order re-checks the same file and returns 403 when
|
|
* closed, so the gate can't be bypassed by POSTing directly.
|
|
*/
|
|
import StoreLayout from '@layouts/StoreLayout.astro';
|
|
import Reveal from '@components/motion/Reveal.astro';
|
|
import SectionHeader from '@components/layout/SectionHeader.astro';
|
|
import Icon from '@components/Icon.astro';
|
|
import ObfuscatedEmail from '@components/ObfuscatedEmail.astro';
|
|
import OrderForm from '@components/store/OrderForm.tsx';
|
|
import SlotMeter from '@components/store/SlotMeter.astro';
|
|
import RequirementList from '@components/store/RequirementList.astro';
|
|
import { requirements } from '@data/store-products';
|
|
import { storeAvailability } from '@data/store-availability';
|
|
import { turnstileSiteKey } from '@lib/env';
|
|
|
|
const av = storeAvailability;
|
|
const open = av.ordersOpen;
|
|
const siteKey = turnstileSiteKey();
|
|
---
|
|
|
|
<StoreLayout
|
|
title="Order Request"
|
|
description="Submit a proxy-card or 3D-print order request. No payment is taken through the site."
|
|
>
|
|
<div class="container-prose flex flex-col gap-14 py-28 sm:py-32">
|
|
<section class="flex flex-col gap-5">
|
|
<Reveal>
|
|
<a
|
|
href="/store"
|
|
class="inline-flex items-center gap-1.5 font-mono text-xs uppercase tracking-[0.18em]"
|
|
style="color: var(--color-accent);"
|
|
>
|
|
<Icon name="arrow-left" class="h-4 w-4" />
|
|
Back to store
|
|
</a>
|
|
</Reveal>
|
|
<Reveal delay={60}>
|
|
<SectionHeader kicker="Order" icon="clipboard-list" title="Order request" />
|
|
</Reveal>
|
|
<Reveal delay={100}>
|
|
<p class="max-w-2xl text-lg leading-relaxed" style="color: var(--color-text-muted);">
|
|
This form sends me an order request by email. No payment is taken through the site.
|
|
{av.turnaround}
|
|
</p>
|
|
</Reveal>
|
|
</section>
|
|
|
|
{/* Availability meters — shown first so visitors immediately see whether
|
|
there's capacity before reading the rest of the page. */}
|
|
<section class="flex flex-col gap-5">
|
|
<Reveal><SectionHeader kicker="Availability" icon="gauge" title="Current order slots" /></Reveal>
|
|
<Reveal delay={60}>
|
|
<div class="grid gap-4 sm:grid-cols-2">
|
|
<SlotMeter label="Card orders" icon="cards-playing" open={av.slots.cards.open} total={av.slots.cards.total} />
|
|
<SlotMeter label="3D-print slots" icon="printer-3d-nozzle" open={av.slots.deckBoxes.open} total={av.slots.deckBoxes.total} />
|
|
</div>
|
|
</Reveal>
|
|
|
|
{/* Open/closed status banner (under the meters). */}
|
|
<Reveal delay={100}>
|
|
<div
|
|
class="flex flex-col gap-3 rounded-xl border p-5 sm:flex-row sm:items-center sm:justify-between"
|
|
style={open
|
|
? 'border-color: color-mix(in srgb, var(--color-accent) 35%, transparent); background: color-mix(in srgb, var(--color-accent) 8%, transparent);'
|
|
: 'border-color: color-mix(in srgb, #e55 40%, transparent); background: color-mix(in srgb, #e55 10%, transparent);'}
|
|
>
|
|
<div class="flex items-center gap-3">
|
|
<Icon name={open ? 'check-circle' : 'close-circle'} class="h-6 w-6 shrink-0" style={open ? 'color: var(--color-accent);' : 'color: #e55;'} />
|
|
<span class="text-sm sm:text-base" style="color: var(--color-text);">
|
|
{open ? 'Orders are open. Slots are limited.' : 'Orders are currently closed.'}
|
|
</span>
|
|
</div>
|
|
<span class="font-mono text-xs" style="color: var(--color-text-subtle);">
|
|
Updated {av.lastUpdated}
|
|
</span>
|
|
</div>
|
|
</Reveal>
|
|
</section>
|
|
|
|
{/* Either the form (open) or the closed notice (no form). */}
|
|
{open ? (
|
|
<section class="flex flex-col gap-8 lg:grid lg:grid-cols-[1.6fr_1fr] lg:items-start">
|
|
<Reveal>
|
|
<div class="card flex flex-col gap-2">
|
|
<h3 class="font-sans text-lg font-bold" style="color: var(--color-text);">Your request</h3>
|
|
<p class="text-sm" style="color: var(--color-text-muted);">
|
|
Fill in the details below. Remember: the card list is final once received, and
|
|
double-sided cards count as 2 slots.
|
|
</p>
|
|
<div class="mt-3">
|
|
<OrderForm client:idle turnstileSiteKey={siteKey} />
|
|
</div>
|
|
</div>
|
|
</Reveal>
|
|
|
|
<Reveal delay={80}>
|
|
<div class="flex flex-col gap-4 lg:sticky lg:top-24">
|
|
<RequirementList items={requirements} heading="Policies & requirements" />
|
|
</div>
|
|
</Reveal>
|
|
</section>
|
|
) : (
|
|
<section class="flex flex-col gap-6">
|
|
<Reveal>
|
|
<div
|
|
class="flex flex-col items-center gap-4 rounded-2xl border p-8 text-center"
|
|
style="border-color: color-mix(in srgb, #e55 40%, transparent); background: color-mix(in srgb, #e55 8%, transparent);"
|
|
>
|
|
<span class="inline-flex h-12 w-12 items-center justify-center rounded-full" style="background: color-mix(in srgb, #e55 20%, transparent); color: #e55;" aria-hidden="true">
|
|
<Icon name="lock" class="h-6 w-6" />
|
|
</span>
|
|
<h3 class="font-sans text-xl font-bold" style="color: var(--color-text);">Orders are not being taken right now</h3>
|
|
<p class="max-w-md text-sm" style="color: var(--color-text-muted);">
|
|
I open a limited number of slots at a time. Check back here — the meters above
|
|
show live availability, and the order form appears as soon as orders reopen. You can
|
|
also email me directly with questions.
|
|
</p>
|
|
<div class="mt-1 flex flex-wrap items-center justify-center gap-2">
|
|
<Icon name="email" class="h-5 w-5" style="color: var(--color-accent);" />
|
|
<ObfuscatedEmail address="orders@gregkilmer.com" class="font-medium" style="color: var(--color-accent);" />
|
|
</div>
|
|
</div>
|
|
</Reveal>
|
|
|
|
<Reveal delay={60}>
|
|
<RequirementList items={requirements} heading="Policies & requirements (for when orders open)" />
|
|
</Reveal>
|
|
</section>
|
|
)}
|
|
</div>
|
|
</StoreLayout>
|