Initial commit: Craft2Prints with Stages 1-3
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import { notFound } from 'next/navigation';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import AdminNav from '@/components/AdminNav';
|
||||
import PromotionScopePicker from '@/components/PromotionScopePicker';
|
||||
import { updatePromotion } from '../../actions';
|
||||
|
||||
export default async function EditPromotionPage({ params }: { params: { id: string } }) {
|
||||
const [promotion, products] = await Promise.all([
|
||||
prisma.promotion.findUnique({ where: { id: params.id }, include: { products: { select: { id: true } } } }),
|
||||
prisma.product.findMany({ orderBy: { name: 'asc' } }),
|
||||
]);
|
||||
if (!promotion) notFound();
|
||||
|
||||
const selectedIds = new Set(promotion.products.map((p) => p.id));
|
||||
const toDateInput = (d: Date | null) => (d ? d.toISOString().slice(0, 10) : '');
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-2xl px-6 py-12">
|
||||
<AdminNav />
|
||||
<h1 className="font-display text-3xl">Edit promotion</h1>
|
||||
<p className="mt-2 text-sm text-muted">
|
||||
Shown as a banner at the top of every page while its date window is active, and actually
|
||||
discounts the price of whatever it covers — every item, or specific ones you pick.
|
||||
</p>
|
||||
|
||||
<form action={updatePromotion} className="mt-10 space-y-6">
|
||||
<input type="hidden" name="id" value={promotion.id} />
|
||||
|
||||
<div>
|
||||
<label htmlFor="message" className="tag-label mb-2 block">
|
||||
Banner message
|
||||
</label>
|
||||
<textarea
|
||||
id="message"
|
||||
name="message"
|
||||
required
|
||||
rows={2}
|
||||
defaultValue={promotion.message}
|
||||
className="w-full border border-line bg-paper px-3 py-2 text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="discountPercent" className="tag-label mb-2 block">
|
||||
Discount (%)
|
||||
</label>
|
||||
<input
|
||||
id="discountPercent"
|
||||
name="discountPercent"
|
||||
type="number"
|
||||
min={1}
|
||||
max={100}
|
||||
required
|
||||
defaultValue={promotion.discountPercent}
|
||||
className="w-full border border-line bg-paper px-3 py-2 text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<PromotionScopePicker
|
||||
products={products}
|
||||
defaultScope={promotion.scope as 'ALL' | 'SPECIFIC'}
|
||||
defaultSelectedIds={[...selectedIds]}
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label htmlFor="startsAt" className="tag-label mb-2 block">
|
||||
Starts (optional)
|
||||
</label>
|
||||
<input
|
||||
id="startsAt"
|
||||
name="startsAt"
|
||||
type="date"
|
||||
defaultValue={toDateInput(promotion.startsAt)}
|
||||
className="w-full border border-line bg-paper px-3 py-2 text-sm"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-muted">Leave blank to start immediately.</p>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="endsAt" className="tag-label mb-2 block">
|
||||
Ends (optional)
|
||||
</label>
|
||||
<input
|
||||
id="endsAt"
|
||||
name="endsAt"
|
||||
type="date"
|
||||
defaultValue={toDateInput(promotion.endsAt)}
|
||||
className="w-full border border-line bg-paper px-3 py-2 text-sm"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-muted">Leave blank for no end date.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" className="bg-clay px-6 py-3 text-sm font-medium text-paper hover:bg-clay-dark">
|
||||
Save changes
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user