diff --git a/estore/src/app/api/checkout/route.ts b/estore/src/app/api/checkout/route.ts index d78054f..0789e71 100644 --- a/estore/src/app/api/checkout/route.ts +++ b/estore/src/app/api/checkout/route.ts @@ -78,6 +78,15 @@ export async function POST(req: NextRequest) { if (deliveryNotes && typeof deliveryNotes === 'string' && deliveryNotes.length > 1000) { return NextResponse.json({ error: 'Delivery notes too long' }, { status: 400 }) } + if (deliveryCents !== undefined && (!Number.isInteger(deliveryCents) || deliveryCents < 0)) { + return NextResponse.json({ error: 'Invalid delivery charge' }, { status: 400 }) + } + if (customerFirstName && (typeof customerFirstName !== 'string' || customerFirstName.length > 100 || /[\r\n\x00-\x1f]/.test(customerFirstName))) { + return NextResponse.json({ error: 'Invalid first name' }, { status: 400 }) + } + if (customerLastName && (typeof customerLastName !== 'string' || customerLastName.length > 100 || /[\r\n\x00-\x1f]/.test(customerLastName))) { + return NextResponse.json({ error: 'Invalid last name' }, { status: 400 }) + } const customerName = [customerFirstName, customerLastName].filter(Boolean).join(' ') || undefined diff --git a/estore/src/app/api/delivery-quote/route.ts b/estore/src/app/api/delivery-quote/route.ts index abf64e0..24fa4c0 100644 --- a/estore/src/app/api/delivery-quote/route.ts +++ b/estore/src/app/api/delivery-quote/route.ts @@ -23,6 +23,10 @@ export async function POST(request: Request) { // Apply per-item rate override if provided (overrides just base and perMile for the inferred tier) if (rateOverride) { + if (typeof rateOverride.base !== 'number' || rateOverride.base < 0 || + typeof rateOverride.perMile !== 'number' || rateOverride.perMile < 0) { + return NextResponse.json({ error: 'Invalid rate override' }, { status: 400 }) + } rates[tier] = { ...rates[tier], base: rateOverride.base, diff --git a/estore/src/app/api/hours/route.ts b/estore/src/app/api/hours/route.ts new file mode 100644 index 0000000..69b2b01 --- /dev/null +++ b/estore/src/app/api/hours/route.ts @@ -0,0 +1,8 @@ +import { NextResponse } from 'next/server' +import { getHoursConfig } from '@/lib/hours' + +export const dynamic = 'force-dynamic' + +export async function GET() { + return NextResponse.json(getHoursConfig()) +} diff --git a/estore/src/app/globals.css b/estore/src/app/globals.css index 7469cf2..8824054 100644 --- a/estore/src/app/globals.css +++ b/estore/src/app/globals.css @@ -135,11 +135,11 @@ position: relative; z-index: 1; transition: transform 0.2s ease; - -webkit-mask-image: url('/color/images/balloon-mask.svg'); + -webkit-mask-image: url('/color-picker/images/balloon-mask.svg'); -webkit-mask-size: contain; -webkit-mask-repeat: no-repeat; -webkit-mask-position: center; - mask-image: url('/color/images/balloon-mask.svg'); + mask-image: url('/color-picker/images/balloon-mask.svg'); mask-size: contain; mask-repeat: no-repeat; mask-position: center; diff --git a/estore/src/app/terms/page.tsx b/estore/src/app/terms/page.tsx index d2d6ab8..ed895cd 100644 --- a/estore/src/app/terms/page.tsx +++ b/estore/src/app/terms/page.tsx @@ -76,7 +76,7 @@ export default function TermsPage() {
- Balloon orders for delivery require a minimum 2-hour delivery window. Smaller delivery + Balloon orders for delivery require a minimum 1-hour delivery window. Smaller delivery windows cannot be guaranteed for on-time arrival, as we account for potential delays.
diff --git a/estore/src/components/AdminColorFilter.tsx b/estore/src/components/AdminColorFilter.tsx index fa690c2..a09ab66 100644 --- a/estore/src/components/AdminColorFilter.tsx +++ b/estore/src/components/AdminColorFilter.tsx @@ -142,7 +142,7 @@ export default function AdminColorFilter({ disabledColors, onSave, onClose }: Pr
- ~{drive} min drive · Please reserve at least 2 hours at your venue · select a start time + ~{drive} min drive · Please reserve at least 1 hour at your venue · select a start time
-