"use client"; import { useState } from "react"; import { logAuditEvent } from "@/actions/audit"; type Product = { id: string; name: string; type: string; price: number; }; type AssignedProduct = { id: string; product_id: string; products: { name: string; type: string; price: number } | null; }; type StopProductAssignmentProps = { stopId: string; allProducts: Product[]; assignedProducts: AssignedProduct[]; callerUid: string; }; export default function StopProductAssignment({ stopId, allProducts, assignedProducts, callerUid, }: StopProductAssignmentProps) { const [products, setProducts] = useState(assignedProducts); const [selected, setSelected] = useState(""); const [assigning, setAssigning] = useState(false); const [removing, setRemoving] = useState(null); const [error, setError] = useState(null); const assignedIds = new Set(products.map((p) => p.product_id)); const availableProducts = allProducts.filter((p) => !assignedIds.has(p.id)); async function handleAssign(e: React.FormEvent) { e.preventDefault(); if (!selected) return; setAssigning(true); setError(null); // First run diagnostic to understand the actual state const diagRes = await fetch( `${process.env.NEXT_PUBLIC_SUPABASE_URL}/rest/v1/rpc/debug_stop_product_assignment`, { method: "POST", headers: { apikey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, "Content-Type": "application/json", }, body: JSON.stringify({ p_stop_id: stopId, p_product_id: selected, p_caller_uid: callerUid, }), } ); const diag = await diagRes.json(); // Now attempt the actual assignment const res = await fetch( `${process.env.NEXT_PUBLIC_SUPABASE_URL}/rest/v1/rpc/assign_product_to_stop`, { method: "POST", headers: { apikey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, "Content-Type": "application/json", }, body: JSON.stringify({ p_stop_id: stopId, p_product_id: selected, p_caller_uid: callerUid, }), } ); const data = await res.json(); if (!res.ok || data.success === false) { const diagInfo = diag && typeof diag === 'object' && 'reason' in diag ? `[${(diag as any).reason}] (admin_found=${(diag as any).admin_found}, role=${(diag as any).admin_role}, admin_brand=${(diag as any).admin_brand_id}, stop_brand=${(diag as any).stop_brand_id}, product_brand=${(diag as any).product_brand_id})` : ''; const errMsg = data?.error ?? data?.message ?? `HTTP ${res.status}`; const errDetail = data?.details ?? data?.hint ?? data?.code ?? ''; const fullError = diagInfo ? `Failed to assign: ${errMsg} ${diagInfo}${errDetail ? ' | ' + errDetail : ''}` : `Failed to assign: ${errMsg}${errDetail ? ' — ' + errDetail : ''}`; setError(fullError); setAssigning(false); return; } // Refresh product list from get_stop_products RPC const refreshRes = await fetch( `${process.env.NEXT_PUBLIC_SUPABASE_URL}/rest/v1/rpc/get_stop_products`, { method: "POST", headers: { apikey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, "Content-Type": "application/json", }, body: JSON.stringify({ p_stop_id: stopId }), } ); const refreshData = await refreshRes.json(); setProducts(refreshData.products ?? []); setSelected(""); setAssigning(false); logAuditEvent({ table_name: "product_stops", record_id: data.id, action: "INSERT", old_data: null, new_data: { stop_id: stopId, product_id: selected }, brand_id: null, }); } async function handleRemove(productId: string) { const entry = products.find((p) => p.product_id === productId); if (!entry) return; setRemoving(productId); setError(null); const res = await fetch( `${process.env.NEXT_PUBLIC_SUPABASE_URL}/rest/v1/rpc/unassign_product_from_stop`, { method: "POST", headers: { apikey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, "Content-Type": "application/json", }, body: JSON.stringify({ p_stop_id: stopId, p_product_id: productId, p_caller_uid: callerUid, }), } ); const data = await res.json(); if (!res.ok || data.success === false) { const errMsg = data?.error ?? data?.message ?? `HTTP ${res.status}`; const errDetail = data?.details ?? data?.hint ?? data?.code ?? ''; setError(`Failed to remove: ${errMsg}${errDetail ? ' — ' + errDetail : ''}`); setRemoving(null); return; } setProducts(products.filter((p) => p.product_id !== productId)); setRemoving(null); logAuditEvent({ table_name: "product_stops", record_id: entry.id, action: "DELETE", old_data: { stop_id: stopId, product_id: productId }, new_data: null, brand_id: null, }); } return (
{error && (
{error}
)} {products.length > 0 ? (

Assigned Products ({products.length})

{products.map((ap) => (

{ap.products?.name ?? "Unknown"}

{ap.products?.type} ·{" "} ${Number(ap.products?.price ?? 0).toFixed(2)}

))}
) : (

No products assigned yet.

)} {availableProducts.length > 0 && (
)}
); }