Read-only mirror of the client's existing system as it stood before our work began. Taken from matthijsexpand@149.210.159.152 (TransIP VPS, Lelystad NL) with the client's written permission. Contents: - home-weddingcaketopper/ Next.js app, proxy.py, supabase schema - var-www/ static webroots for all three domains - etc-nginx/ vhost configs (previously unversioned, server-only) Excluded: node_modules (704M, regenerable), .next (17M, regenerable), and env file contents (present on local disk, gitignored — see README). Not our IP. Not covered by the proposal's assignment clause.
13 lines
2 KiB
TypeScript
13 lines
2 KiB
TypeScript
'use client';
|
||
import { useState } from 'react';
|
||
import { STYLES } from '@/lib/types';
|
||
export default function OrderPage(){
|
||
const [loading,setLoading]=useState(false); const [msg,setMsg]=useState('');
|
||
async function submit(e:React.FormEvent<HTMLFormElement>){e.preventDefault();setLoading(true);setMsg(''); const fd=new FormData(e.currentTarget);
|
||
const files=fd.getAll('photos') as File[]; if(files.length<3||files.length>6){setMsg('Upload minimaal 3 en maximaal 6 foto’s.'); setLoading(false); return;}
|
||
const res=await fetch('/api/orders/create',{method:'POST',body:fd}); const data=await res.json(); if(!res.ok){setMsg(data.error||'Er ging iets mis.');setLoading(false);return;}
|
||
const pay=await fetch('/api/payments/session',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({orderId:data.orderId})}); const p=await pay.json(); if(!pay.ok){setMsg(p.error||'Betaling kon niet starten.');setLoading(false);return;}
|
||
window.location.href=p.redirectUrl || `/order/checkout?orderId=${data.orderId}`;
|
||
}
|
||
return <main className="container"><div className="topbar"><a className="logo" href="/">WEDDING<span> cake topper</span></a></div><div className="card"><h1>Start jouw ontwerp</h1><form onSubmit={submit} className="grid"><label>Product<select name="product" defaultValue="bruidspaar-taarttopper"><option value="bruidspaar-taarttopper">Bruidspaar taarttopper</option></select></label><label>Foto’s uploaden<input name="photos" type="file" accept="image/*" multiple required /></label><label>Stijl<select name="style" required>{STYLES.map(s=><option key={s} value={s}>{s}</option>)}</select></label><label>Naam<input name="name" required placeholder="Voor- en achternaam" /></label><label>Email<input name="email" type="email" required /></label><label>Trouwdatum<input name="wedding_date" type="date" /></label><label>Opmerkingen<textarea name="notes" rows={4} placeholder="Bijv. kleding, pose, grappig detail..." /></label><button className="btn" disabled={loading}>{loading?'Even geduld...':'Ga naar betaling'}</button>{msg&&<p>{msg}</p>}</form></div></main>
|
||
}
|