"use client"; import { useState, useEffect } from "react"; import { formatDate } from "@/lib/format-date"; import { useRouter, useSearchParams } from "next/navigation"; import { getWholesaleCustomerByUser, submitWholesaleOrder, getWholesaleProducts, getWholesaleCustomerOrders, getWholesaleCustomerPricing, getWholesaleCustomer, type WholesaleProduct, type WholesaleCustomerOrder, type WholesalePricingOverride } from "@/actions/wholesale-register"; import { getWholesaleSettings, enqueueWholesaleNotification } from "@/actions/wholesale"; type CartItem = { product: WholesaleProduct; quantity: number; unitPrice: number; }; export default function WholesalePortalPage() { const router = useRouter(); const [customer, setCustomer] = useState<{ id: string; user_id: string; company_name: string; contact_name: string; email: string; account_status: string; brand_id: string; } | null>(null); const [brandName, setBrandName] = useState("Wholesale Portal"); const [loading, setLoading] = useState(true); const [previewMode, setPreviewMode] = useState(false); const [tab, setTab] = useState<"products" | "cart" | "orders">("products"); const [products, setProducts] = useState([]); const [cart, setCart] = useState([]); const [orders, setOrders] = useState([]); const [pricingOverrides, setPricingOverrides] = useState>({}); const [pickupDate, setPickupDate] = useState(""); const [submitting, setSubmitting] = useState(false); const [msg, setMsg] = useState<{ kind: "success" | "error"; text: string } | null>(null); const [onlinePaymentEnabled, setOnlinePaymentEnabled] = useState(false); const [processingPayment, setProcessingPayment] = useState(null); useEffect(() => { // ── Admin preview mode ────────────────────────────────────────────────── const params = new URLSearchParams(window.location.search); const isPreview = params.get("_admin_preview") === "1"; const previewCustomerId = params.get("preview_customer_id"); if (isPreview && previewCustomerId) { // Load customer directly by ID (admin preview mode — no login required) getWholesaleCustomer(previewCustomerId).then(async cust => { if (!cust) { // In preview mode with an invalid customer ID, show empty state setCustomer(null); setLoading(false); return; } const { supabase } = await import("@/lib/supabase"); const { data: ws } = await supabase .from("wholesale_settings") .select("wholesale_enabled, online_payment_enabled") .eq("brand_id", cust.brand_id) .single(); setOnlinePaymentEnabled(ws?.online_payment_enabled ?? false); setCustomer(cust); setPreviewMode(true); setLoading(false); loadBrandName(cust.brand_id); loadProducts(cust.brand_id); loadOrders(cust.id); loadPricingOverrides(cust.id); }); return; // ← prevent the synchronous session check below from running while preview loads } // ── Normal session-based login ──────────────────────────────────────── const cookies = document.cookie.split(";").reduce((acc, c) => { const [k, v] = c.trim().split("="); acc[k] = decodeURIComponent(v); return acc; }, {} as Record); const session = cookies["wholesale_session"]; if (!session) { router.push("/wholesale/login"); return; } let userId: string; try { const parsed = JSON.parse(session); userId = parsed.user_id; } catch { router.push("/wholesale/login"); return; } getWholesaleCustomerByUser("00000000-0000-0000-0000-000000000000", userId).then(async cust => { if (!cust || cust.account_status !== "active") { router.push("/wholesale/login?error=account_not_active"); return; } const { supabase } = await import("@/lib/supabase"); const { data: ws } = await supabase .from("wholesale_settings") .select("wholesale_enabled, online_payment_enabled") .eq("brand_id", cust.brand_id) .single(); if (ws && ws.wholesale_enabled === false) { router.push("/wholesale/login?error=portal_disabled"); return; } setOnlinePaymentEnabled(ws?.online_payment_enabled ?? false); setCustomer(cust); setLoading(false); loadBrandName(cust.brand_id); loadProducts(cust.brand_id); loadOrders(cust.id); loadPricingOverrides(cust.id); }); }, [router]); async function loadBrandName(brandId: string) { const { supabase } = await import("@/lib/supabase"); const { data: brand } = await supabase .from("brands") .select("name") .eq("id", brandId) .single(); if (brand) setBrandName(brand.name); } async function loadProducts(brandId: string) { const { getWholesaleProducts } = await import("@/actions/wholesale"); const prods = await getWholesaleProducts(brandId); setProducts(prods); } async function loadOrders(customerId: string) { const orderList = await getWholesaleCustomerOrders(customerId); setOrders(orderList); } async function loadPricingOverrides(customerId: string) { const pricing = await getWholesaleCustomerPricing(customerId); const map: Record = {}; for (const p of pricing) { map[p.product_id] = p.custom_unit_price; } setPricingOverrides(map); } async function handlePayNow(order: WholesaleCustomerOrder) { if (!customer) return; setProcessingPayment(order.id); try { const res = await fetch("/api/wholesale/checkout", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ orderId: order.id, customerId: customer.id }), }); const data = await res.json(); if (data.checkoutUrl) { window.location.href = data.checkoutUrl; } else { setMsg({ kind: "error", text: data.error ?? "Failed to start payment." }); } } catch { setMsg({ kind: "error", text: "Payment request failed." }); } finally { setProcessingPayment(null); } } function addToCart(product: WholesaleProduct) { const qty = prompt(`Quantity for ${product.name} (${product.unit_type}):`); if (!qty) return; const q = Number(qty); if (isNaN(q) || q <= 0) return; // Determine unit price: customer override first, then price tiers let unitPrice = 0; const overridePrice = pricingOverrides[product.id]; if (overridePrice !== undefined) { unitPrice = overridePrice; } else if (product.price_tiers && product.price_tiers.length > 0) { const tier = product.price_tiers.find((t: { min_qty: number; max_qty: number; price: number }) => q >= t.min_qty && (t.max_qty === 0 || q <= t.max_qty) ); unitPrice = tier ? tier.price : product.price_tiers[product.price_tiers.length - 1].price; } setCart(prev => { const existing = prev.find(i => i.product.id === product.id); if (existing) { return prev.map(i => i.product.id === product.id ? { ...i, quantity: i.quantity + q } : i); } return [...prev, { product, quantity: q, unitPrice }]; }); setTab("cart"); } async function handlePlaceOrder() { if (!customer || cart.length === 0) return; setSubmitting(true); setMsg(null); const checkoutSessionId = crypto.randomUUID(); const items = cart.map(c => ({ product_id: c.product.id, quantity: c.quantity, unit_price: c.unitPrice, })); const result = await submitWholesaleOrder({ brandId: customer.brand_id, customerId: customer.id, anticipatedPickupDate: pickupDate || undefined, items, checkoutSessionId, }); setSubmitting(false); if (result.success) { setMsg({ kind: "success", text: `Order placed! Invoice: ${result.invoiceNumber} — Status: ${result.status}` }); setCart([]); setPickupDate(""); if (customer) loadOrders(customer.id); // Enqueue order confirmation notification if (result.orderId && customer) { const total = cart.reduce((s, i) => s + i.quantity * i.unitPrice, 0); enqueueWholesaleNotification({ brandId: customer.brand_id, customerId: customer.id, orderId: result.orderId, type: "order_confirmation", emailTo: customer.email, subject: `Order ${result.invoiceNumber} Confirmed`, bodyHtml: `

Thank you for your order, ${customer.company_name}!

Your wholesale order ${result.invoiceNumber} has been received.

Total: $${total.toFixed(2)}

${result.status === "awaiting_deposit" ? `

Deposit Required: Your order is awaiting a deposit payment.

` : ""}

We'll notify you when your order is ready for pickup.

`, bodyText: `Order ${result.invoiceNumber} confirmed. Total: $${total.toFixed(2)}. Status: ${result.status}.`, }); // Also notify the admin const settings = await getWholesaleSettings(customer.brand_id); const adminEmail = settings?.notification_email ?? settings?.from_email ?? settings?.invoice_business_email ?? null; if (adminEmail) { enqueueWholesaleNotification({ brandId: customer.brand_id, customerId: customer.id, orderId: result.orderId, type: "order_confirmation", emailTo: adminEmail, subject: `[Admin] New Wholesale Order — ${result.invoiceNumber}`, bodyHtml: `

New Wholesale Order

A new wholesale order has been placed by ${customer.company_name}.

Invoice: ${result.invoiceNumber}

Total: $${total.toFixed(2)}

Status: ${result.status}

${result.status === "awaiting_deposit" ? `

Action Required: Awaiting deposit payment.

` : ""} `, bodyText: `New wholesale order ${result.invoiceNumber} from ${customer.company_name}. Total: $${total.toFixed(2)}. Status: ${result.status}.`, }); } // Trigger notification send (fire-and-forget) fetch(`/api/wholesale/notifications/send`, { method: "POST" }).catch(() => {}); } } else { let errorText = result.error ?? "Failed to place order."; if (result.creditLimit !== undefined) { errorText += ` (Credit limit: $${result.creditLimit} | Outstanding: $${result.outstandingBalance?.toFixed(2)} | Order total: $${result.orderTotal?.toFixed(2)})`; } setMsg({ kind: "error", text: errorText }); } } if (loading) { return (

Loading...

); } return (
{previewMode && (
Admin Preview — viewing portal as {customer?.company_name}
)} {/* Header */}

{brandName}

Wholesale Portal — {customer?.company_name}

{/* Tab nav */}
{msg && (
{msg.text}
)} {tab === "products" && (

Product Catalog

{products.length === 0 ? (

No products available.

) : (
{products.map(p => (

{p.name}

{p.description ?? ""}

{p.availability} {" "}{p.qty_available} {p.unit_type} available

{p.price_tiers && p.price_tiers.length > 0 && (

{pricingOverrides[p.id] !== undefined ? ( Your price: ${pricingOverrides[p.id]!.toFixed(2)} ) : ( p.price_tiers.map((t: { min_qty: number; max_qty: number; price: number }, i: number) => ( {t.min_qty}{t.max_qty ? `-${t.max_qty}` : "+"}: ${t.price} )) )}

)}
{p.availability === "available" && ( )}
))}
)}
)} {tab === "cart" && (

Your Order ({cart.length} items)

{cart.length === 0 ? (

Cart is empty.

) : ( <>
{cart.map(item => ( ))}
Product Qty Unit Price Total
{item.product.name} {item.quantity} {item.product.unit_type} ${item.unitPrice.toFixed(2)} ${(item.quantity * item.unitPrice).toFixed(2)}
setPickupDate(e.target.value)} className="rounded-xl border border-slate-300 px-3 py-2 text-sm outline-none focus:border-green-600" />

Total: ${cart.reduce((s, i) => s + i.quantity * i.unitPrice, 0).toFixed(2)}

)}
)} {tab === "orders" && (

Order History

{orders.length === 0 ? (

No orders yet.

) : (
{orders.map(o => (

{o.invoice_number ?? o.id.slice(0, 8)}

{formatDate(new Date(o.created_at))} {o.anticipated_pickup_date && ` · Pickup: ${o.anticipated_pickup_date}`}

${Number(o.subtotal).toFixed(2)}

{o.payment_status === "paid" ? "Paid" : `$${Number(o.balance_due).toFixed(2)} due`}

{o.status.replace("_", " ")} {o.items && o.items.length > 0 && ( {o.items.length} item{o.items.length !== 1 ? "s" : ""} )} {o.invoice_number && o.invoice_token && ( Download Invoice )} {onlinePaymentEnabled && Number(o.balance_due) > 0 && o.payment_status !== "paid" && ( )}
))}
)}
)}

Powered by{" "} Route Commerce

); }