Initial commit: Craft2Prints with Stages 1-3

This commit is contained in:
Andymick
2026-07-15 18:09:59 +01:00
commit 41937ffc15
158 changed files with 16054 additions and 0 deletions
+88
View File
@@ -0,0 +1,88 @@
'use client';
import { useState } from 'react';
const PRESETS = ['XS', 'S', 'M', 'L', 'XL', 'XXL'];
export default function SizePicker({ name, defaultSizes = [] }: { name: string; defaultSizes?: string[] }) {
const [sizes, setSizes] = useState<string[]>(defaultSizes);
const [custom, setCustom] = useState('');
const addSize = (s: string) => {
const trimmed = s.trim();
if (!trimmed || sizes.includes(trimmed)) return;
setSizes((prev) => [...prev, trimmed]);
};
const removeSize = (s: string) => {
setSizes((prev) => prev.filter((x) => x !== s));
};
return (
<div>
<input type="hidden" name={name} value={sizes.join(',')} />
{sizes.length > 0 && (
<div className="mb-3 flex flex-wrap gap-2">
{sizes.map((s) => (
<span
key={s}
className="flex items-center gap-1.5 border border-ink bg-ink px-3 py-1 text-xs text-paper"
>
{s}
<button
type="button"
onClick={() => removeSize(s)}
aria-label={`Remove ${s}`}
className="hover:text-splash-pink"
>
×
</button>
</span>
))}
</div>
)}
<div className="flex flex-wrap gap-2">
{PRESETS.map((s) => (
<button
key={s}
type="button"
onClick={() => addSize(s)}
disabled={sizes.includes(s)}
className="border border-line px-3 py-1.5 text-xs hover:border-clay hover:text-clay disabled:opacity-30"
>
+ {s}
</button>
))}
</div>
<div className="mt-3 flex items-center gap-2">
<input
value={custom}
onChange={(e) => setCustom(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
addSize(custom);
setCustom('');
}
}}
placeholder="Custom size (e.g. One Size, 9, 10)"
className="border border-line bg-paper px-2 py-1.5 text-xs"
/>
<button
type="button"
onClick={() => {
addSize(custom);
setCustom('');
}}
className="border border-ink px-3 py-1.5 text-xs hover:border-clay hover:bg-clay hover:text-paper"
>
+ Add
</button>
</div>
<p className="mt-1 text-xs text-muted">Leave empty for products that don&apos;t need sizing.</p>
</div>
);
}