Skip to content

Commit 5424d0c

Browse files
authored
feat: add payment method and GCash receipt handling to order processing
2 parents 9726d9e + d9f3426 commit 5424d0c

4 files changed

Lines changed: 145 additions & 5 deletions

File tree

frontend/app/admin/page.tsx

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ type OrderItem = {
1111
email: string;
1212
phone: string;
1313
address: string;
14+
paymentMethod: string;
15+
gcashReference: string;
16+
gcashReceiptUrl: string;
1417
item: string;
1518
size: string;
1619
quantity: number;
@@ -74,6 +77,9 @@ export default function AdminPage() {
7477
email: string;
7578
phone: string;
7679
address: string;
80+
payment_method: string;
81+
gcash_reference: string;
82+
gcash_receipt_url: string;
7783
item_name: string;
7884
size: string;
7985
quantity: number;
@@ -91,6 +97,9 @@ export default function AdminPage() {
9197
email: order.email,
9298
phone: order.phone,
9399
address: order.address,
100+
paymentMethod: order.payment_method,
101+
gcashReference: order.gcash_reference,
102+
gcashReceiptUrl: order.gcash_receipt_url,
94103
item: order.item_name,
95104
size: order.size,
96105
quantity: order.quantity,
@@ -134,6 +143,9 @@ export default function AdminPage() {
134143
order.phone,
135144
order.item,
136145
order.size,
146+
order.paymentMethod,
147+
order.gcashReference,
148+
order.gcashReceiptUrl,
137149
order.status,
138150
].some((field) => field.toLowerCase().includes(normalized));
139151
const matchesStatus =
@@ -229,6 +241,9 @@ export default function AdminPage() {
229241
"Email",
230242
"Phone",
231243
"Address",
244+
"Payment Method",
245+
"GCash Reference",
246+
"GCash Receipt",
232247
"Item",
233248
"Size",
234249
"Qty",
@@ -244,6 +259,9 @@ export default function AdminPage() {
244259
order.email,
245260
order.phone,
246261
order.address,
262+
order.paymentMethod,
263+
order.gcashReference,
264+
order.gcashReceiptUrl,
247265
order.item,
248266
order.size,
249267
String(order.quantity),
@@ -491,12 +509,13 @@ export default function AdminPage() {
491509
</div>
492510

493511
<div className="mt-5 overflow-x-auto rounded-2xl border border-white/10">
494-
<table className="w-full min-w-[1100px] text-left text-sm text-white/80">
512+
<table className="w-full min-w-[1300px] text-left text-sm text-white/80">
495513
<thead className="bg-white/5 text-xs uppercase tracking-[0.2em] text-white/60">
496514
<tr>
497515
<th className="px-4 py-3">Order</th>
498516
<th className="px-4 py-3">Customer</th>
499517
<th className="px-4 py-3">Address</th>
518+
<th className="px-4 py-3">Payment</th>
500519
<th className="px-4 py-3">Item</th>
501520
<th className="px-4 py-3">Qty</th>
502521
<th className="px-4 py-3">Price</th>
@@ -528,6 +547,28 @@ export default function AdminPage() {
528547
{order.address}
529548
</span>
530549
</td>
550+
<td className="px-4 py-3">
551+
<div className="text-xs uppercase tracking-[0.2em] text-white/50">
552+
{order.paymentMethod}
553+
</div>
554+
<div className="text-sm font-semibold text-white">
555+
{order.gcashReference}
556+
</div>
557+
{order.gcashReceiptUrl ? (
558+
<a
559+
href={order.gcashReceiptUrl}
560+
target="_blank"
561+
rel="noreferrer"
562+
className="text-xs uppercase tracking-[0.2em] text-emerald-200 hover:text-emerald-100"
563+
>
564+
View Receipt
565+
</a>
566+
) : (
567+
<div className="text-xs text-white/40">
568+
Missing receipt
569+
</div>
570+
)}
571+
</td>
531572
<td className="px-4 py-3">
532573
<div className="font-semibold text-white">
533574
{order.item}

frontend/app/api/admin/orders/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export async function GET(request: NextRequest) {
3737
const { data, error } = await supabaseAdmin
3838
.from("orders")
3939
.select(
40-
"id,full_name,email,phone,address,item_name,size,quantity,unit_price,line_total,status,created_at"
40+
"id,full_name,email,phone,address,payment_method,gcash_reference,gcash_receipt_url,item_name,size,quantity,unit_price,line_total,status,created_at"
4141
)
4242
.order("created_at", { ascending: false });
4343

frontend/app/page.tsx

Lines changed: 99 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ type CartItem = {
2222
quantity: number;
2323
};
2424

25+
const GCASH_BUCKET = "gcash-receipts";
26+
const MAX_RECEIPT_SIZE = 5 * 1024 * 1024;
27+
2528
export default function Home() {
2629
const [merchItems, setMerchItems] = useState<MerchItem[]>([]);
2730
const [merchLoading, setMerchLoading] = useState(true);
@@ -196,19 +199,71 @@ export default function Home() {
196199
const email = String(formData.get("email") ?? "").trim();
197200
const phone = String(formData.get("contactNumber") ?? "").trim();
198201
const address = String(formData.get("address") ?? "").trim();
202+
const paymentMethod = String(formData.get("paymentMethod") ?? "gcash");
203+
const gcashReference = String(
204+
formData.get("gcashReference") ?? ""
205+
).trim();
206+
const receiptFile = formData.get("gcashReceipt");
199207

200208
if (!fullName || !email || !phone || !address) {
201209
setSubmitError("Please complete all contact fields.");
202210
return;
203211
}
204212

213+
if (paymentMethod !== "gcash") {
214+
setSubmitError("Select GCash as your payment method.");
215+
return;
216+
}
217+
218+
if (!gcashReference) {
219+
setSubmitError("Enter your GCash reference number.");
220+
return;
221+
}
222+
223+
if (!(receiptFile instanceof File) || receiptFile.size === 0) {
224+
setSubmitError("Upload your GCash receipt screenshot.");
225+
return;
226+
}
227+
228+
if (!receiptFile.type.startsWith("image/")) {
229+
setSubmitError("Receipt screenshot must be an image file.");
230+
return;
231+
}
232+
233+
if (receiptFile.size > MAX_RECEIPT_SIZE) {
234+
setSubmitError("Receipt image must be 5MB or smaller.");
235+
return;
236+
}
237+
205238
setSubmitting(true);
206239

240+
const fileExtension =
241+
receiptFile.name.split(".").pop()?.toLowerCase() || "jpg";
242+
const uploadPath = `gcash/${crypto.randomUUID()}.${fileExtension}`;
243+
const { error: uploadError } = await supabase.storage
244+
.from(GCASH_BUCKET)
245+
.upload(uploadPath, receiptFile, {
246+
contentType: receiptFile.type,
247+
});
248+
249+
if (uploadError) {
250+
setSubmitError("Unable to upload receipt. Please try again.");
251+
setSubmitting(false);
252+
return;
253+
}
254+
255+
const receiptUrl = supabase.storage
256+
.from(GCASH_BUCKET)
257+
.getPublicUrl(uploadPath).data.publicUrl;
258+
207259
const orderRows = cartItems.map((item) => ({
208260
full_name: fullName,
209261
email,
210262
phone,
211263
address,
264+
payment_method: "gcash",
265+
gcash_reference: gcashReference,
266+
gcash_receipt_url: receiptUrl,
212267
item_id: item.itemId,
213268
item_name: item.name,
214269
size: item.size,
@@ -229,7 +284,7 @@ export default function Home() {
229284
setCartItems([]);
230285
setQuantities((prev) => prev.map(() => 0));
231286
form.reset();
232-
setSubmitSuccess("Order received! We'll email you with next steps.");
287+
setSubmitSuccess("Order received! We'll verify your GCash receipt.");
233288
setSubmitting(false);
234289
};
235290
return (
@@ -538,8 +593,8 @@ export default function Home() {
538593
Place Your Order
539594
</h2>
540595
<p className="mt-3 text-sm leading-6 text-white/70">
541-
Fill up the form below to reserve your merch. We will follow up
542-
with payment details and size confirmation.
596+
Fill up the form below and attach your GCash receipt to confirm
597+
your merch order.
543598
</p>
544599
<div className="mt-6 grid gap-4 text-xs uppercase tracking-[0.25em] text-white/60">
545600
<div className="flex items-center gap-3">
@@ -594,6 +649,47 @@ export default function Home() {
594649
/>
595650
</label>
596651

652+
<div className="rounded-2xl border border-white/10 bg-white/5 p-4">
653+
<p className="text-xs uppercase tracking-[0.2em] text-white/60">
654+
Payment Method
655+
</p>
656+
<label className="mt-3 flex items-center gap-3 text-sm text-white/80">
657+
<input
658+
type="radio"
659+
name="paymentMethod"
660+
value="gcash"
661+
defaultChecked
662+
className="h-4 w-4 border-white/30 bg-white/10 text-emerald-300 focus:ring-emerald-300/40"
663+
/>
664+
GCash
665+
</label>
666+
<p className="mt-2 text-xs text-white/60">
667+
Upload your GCash receipt before confirming the order.
668+
</p>
669+
</div>
670+
671+
<label className="text-sm text-white/80">
672+
GCash Reference No.
673+
<input
674+
type="text"
675+
name="gcashReference"
676+
placeholder="0000000000"
677+
required
678+
className="mt-2 w-full rounded-xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-white placeholder-white/40 focus:border-emerald-300/70 focus:outline-none focus:ring-2 focus:ring-emerald-300/30"
679+
/>
680+
</label>
681+
682+
<label className="text-sm text-white/80">
683+
GCash Receipt Screenshot
684+
<input
685+
type="file"
686+
name="gcashReceipt"
687+
accept="image/*"
688+
required
689+
className="mt-2 w-full rounded-xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-white file:mr-3 file:rounded-full file:border-0 file:bg-white/10 file:px-3 file:py-2 file:text-xs file:uppercase file:tracking-[0.2em] file:text-white/80"
690+
/>
691+
</label>
692+
597693
{submitError ? (
598694
<p className="text-xs uppercase tracking-[0.2em] text-amber-300">
599695
{submitError}

frontend/supabase/schema.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ create table if not exists public.orders (
2121
email text not null,
2222
phone text not null,
2323
address text not null,
24+
payment_method text not null default 'gcash',
25+
gcash_reference text not null,
26+
gcash_receipt_url text not null,
2427
item_id uuid references public.merch_items(id),
2528
item_name text not null,
2629
size text not null,

0 commit comments

Comments
 (0)