diff --git a/.gitignore b/.gitignore index 73a2524..30bf1ec 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ vite.config.js.timestamp-* vite.config.ts.timestamp-* package-lock.json +yarn.lock \ No newline at end of file diff --git a/src/lib/CurrencyInput.svelte b/src/lib/CurrencyInput.svelte index 69437cf..a7626a1 100644 --- a/src/lib/CurrencyInput.svelte +++ b/src/lib/CurrencyInput.svelte @@ -2,7 +2,8 @@ export let value: number = 0; // The raw number export let label: string = ""; // Field label export let onInput: (() => void) | null = null; // Optional extra handler - + export let disabled: boolean = false; + export let className: string = ""; let formatted = ""; // Format whenever value changes @@ -26,7 +27,8 @@ type="text" bind:value={formatted} placeholder="Rp 0" - class="w-full border p-2 rounded" + class="w-full border p-2 rounded ${className}" on:input={handleInput} + disabled={disabled} /> \ No newline at end of file diff --git a/src/routes/backoffice/issue/+page.svelte b/src/routes/backoffice/issue/+page.svelte index a6c4f75..a584407 100644 --- a/src/routes/backoffice/issue/+page.svelte +++ b/src/routes/backoffice/issue/+page.svelte @@ -270,6 +270,8 @@ let dataUser: User[] = []; let projectIssueMap: Set = new Set(); let purchaseOrderMap: Set = new Set(); + let sortColumn: string | null = "created_at"; // or any default column + let sortOrder: "asc" | "desc" = "desc"; let poItems: POItem[] = []; let newPO: PurchaseOrder = { villa_id: "", @@ -349,11 +351,20 @@ const { data } = await supabase.from("vb_po_item").select("item_name"); if (data) poItems = data; } + function getDBColumn(key: string) { + switch (key) { + case "villa_name": return "villa_name"; + case "reported_by": return "reported_by"; + // add mappings if needed + default: return key; + } + } // Fetch issues with optional filters async function fetchIssues() { let query = supabase .from("vb_issues_data") - .select("*").order("issue_number", { ascending: true }); + .select("*") + .order(sortColumn || "created_at", { ascending: sortOrder === "asc" }); const { data: issues, error } = await query; @@ -599,7 +610,15 @@ alert("Purchase Order submitted!"); showPurchaseOrderModal = false; } - + function toggleSort(column: string) { + if (sortColumn === column) { + sortOrder = sortOrder === "asc" ? "desc" : "asc"; + } else { + sortColumn = column; + sortOrder = "asc"; + } + fetchIssues(); // re-fetch or re-sort your rows + } // Function to open purchase order modal function openPurchaseOrderModal(issue) { if (purchaseOrderMap.has(issue.id)) { @@ -787,7 +806,7 @@ -
+
@@ -796,14 +815,22 @@ {:else} {/if} {/each} diff --git a/src/routes/backoffice/purchaseorder/+page.svelte b/src/routes/backoffice/purchaseorder/+page.svelte index 7c22ce1..0ce9828 100644 --- a/src/routes/backoffice/purchaseorder/+page.svelte +++ b/src/routes/backoffice/purchaseorder/+page.svelte @@ -161,6 +161,8 @@ updated_by: "", updated_at: new Date().toISOString(), }; + let sortColumn: string | null = "created_at"; // or any default + let sortOrder: "asc" | "desc" = "desc"; let showEditModal = false; let editForm = { po_number: "", @@ -191,7 +193,13 @@ approval: "", approved_by: "", approved_date: "", - reject_comment: "" + reject_comment: "", + po_remark: "", + approved_quantity: 0, + approved_vendor: "", + approved_price: 0, + po_item: "", + total_approved_order_amount: 0 }; let villaOptions = []; let poItemOptions = []; @@ -283,6 +291,21 @@ currency: "IDR", minimumFractionDigits: 0, }); + // function Sort + function toggleSort(column: string) { + if (sortColumn === column) { + sortOrder = sortOrder === "asc" ? "desc" : "asc"; + } else { + sortColumn = column; + sortOrder = "asc"; + } + fetchPurchaseOrder( + selectedVillaId, + searchTerm, + sortColumn, + sortOrder, + ); + } // Function to format numbers as ordinal (1st, 2nd, 3rd, etc.) function ordinal(num: number) { @@ -323,7 +346,13 @@ approval: row.approval ? "approve" : "reject", approved_by: currentUserId, approved_date: new Date().toISOString().split("T")[0], - reject_comment: row.reject_comment || "" + reject_comment: row.reject_comment || "", + po_remark: row.po_remark || "", + approved_quantity: row.approved_quantity || 0, + approved_vendor: row.approved_vendor || "", + approved_price: row.approved_price || 0, + po_item: row.po_item || "", + total_approved_order_amount: row.total_approved_order_amount || 0 }; showApprovalModal = true; @@ -478,7 +507,8 @@ approved_by: approvalForm.approval === "approve" ? currentUserId : null, approved_date: approvalForm.approved_date, reject_comment: approvalForm.reject_comment || null, - po_status: "approved" + po_status: "approved", + po_remark: approvalForm.po_remark || null }) .eq("id", selectedPO.id); @@ -692,7 +722,7 @@ let query = supabase .from("vb_purchaseorder_data") .select("*") - .order(sort || "purchase_order_number", { ascending: order === "desc" }) + .order(sortColumn || "created_at", { ascending: sortOrder === "asc" }) .range(offset, offset + limit - 1); if (filter) { @@ -1070,7 +1100,7 @@ -
+
toggleSort(col.key)} > {col.title} + {#if sortColumn === col.key} + {sortOrder === 'asc' ? ' 🔼' : ' 🔽'} + {/if} toggleSort(col.key)} > {col.title} + {#if sortColumn === col.key} + {sortOrder === 'asc' ? ' 🔼' : ' 🔽'} + {/if}
@@ -1079,14 +1109,22 @@ {:else} {/if} {/each} @@ -1650,11 +1688,10 @@ {#each [1,2,3,4,5,6] as num} - @@ -1667,7 +1704,7 @@ - +
@@ -1693,27 +1730,89 @@ class="w-full border p-2 bg-gray-100" /> - + + {#if approvalForm.po_item} + + + {/if} + + + {#if approvalForm.approved_quantity != null} + + + {/if} + + + {#if approvalForm.approved_price != null} + + + {/if} + + + {#if approvalForm.total_approved_order_amount != null} + + + {/if} + + + {#if approvalForm.approved_vendor} + + + {/if} + + + + {#if approvalForm.approval === 'reject'} - - + > {/if} - - + + + - + + @@ -1726,6 +1825,7 @@
{/if} + {#if showAcknowledgedModal}
diff --git a/src/routes/backoffice/timesheets/+page.svelte b/src/routes/backoffice/timesheets/+page.svelte index ddcb7d8..82cff4b 100644 --- a/src/routes/backoffice/timesheets/+page.svelte +++ b/src/routes/backoffice/timesheets/+page.svelte @@ -1,8 +1,6 @@ + +
+
+ Villa Logo + +

Timesheet Entry

+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
{form.total_work_hour}
+
+ +
+ + +
+ + + +
diff --git a/src/routes/timesheet/+page.svelte b/src/routes/timesheet/+page.svelte index f5aa5bd..44b8898 100644 --- a/src/routes/timesheet/+page.svelte +++ b/src/routes/timesheet/+page.svelte @@ -20,6 +20,7 @@ datetime_out: string; total_work_hour: number; remarks: string; + approved_date: string | null; approval: boolean | null; // Allow null for new entries }; @@ -46,9 +47,9 @@ datetime_out: "", total_work_hour: 0, remarks: "", + approved_date: null, approval: null, // Default null }; - const typeOfWorkOptions: TimesheetForm["type_of_work"][] = [ "Running", "Periodic", @@ -115,7 +116,16 @@ alert("Please select a villa."); return; } - + if (form.approval) { + const today = new Date(); + const yyyy = today.getFullYear(); + const mm = String(today.getMonth() + 1).padStart(2, "0"); + const dd = String(today.getDate()).padStart(2, "0"); + form.approved_date = `${yyyy}/${mm}/${dd}`; + } else { + form.approved_date = null; + } + form.approval = form.total_work_hour <= 1; const { error } = await supabase.from("vb_timesheet").insert([form]); if (error) { @@ -263,7 +273,6 @@ placeholder="Optional remarks" >
-
toggleSort(col.key)} > {col.title} + {#if sortColumn === col.key} + {sortOrder === 'asc' ? ' 🔼' : ' 🔽'} + {/if} toggleSort(col.key)} > {col.title} + {#if sortColumn === col.key} + {sortOrder === 'asc' ? ' 🔼' : ' 🔽'} + {/if}