diff --git a/src/lib/utils/authUtil.ts b/src/lib/utils/authUtil.ts
new file mode 100644
index 0000000..99db787
--- /dev/null
+++ b/src/lib/utils/authUtil.ts
@@ -0,0 +1,10 @@
+import { supabase } from "$lib/supabaseClient";
+
+export async function getSessionAuthId() {
+ const { data: { session }, error } = await supabase.auth.getSession();
+ if (error) {
+ console.error("Error fetching session:", error);
+ return null;
+ }
+ return session?.user?.id || null;
+}
diff --git a/src/routes/backoffice/issue/+page.svelte b/src/routes/backoffice/issue/+page.svelte
index c203e0f..cc63b52 100644
--- a/src/routes/backoffice/issue/+page.svelte
+++ b/src/routes/backoffice/issue/+page.svelte
@@ -211,7 +211,6 @@
{ key: "issue_number", title: "Issue Number" },
{ key: "move_issue", title: "Move Issue" },
{ key: "description_of_the_issue", title: "Description of The Issue" },
- { key: "reported_date", title: "Reported Date" },
{ key: "issue_related_image", title: "Issue Related Image" },
{ key: "issue_source", title: "Issue Source" },
{ key: "reported_name", title: "Reported By" },
@@ -732,7 +731,7 @@
row[col.key as keyof Issue] as
| string
| number,
- ).toLocaleDateString("en-US")
+ ).toLocaleString("en-US")
: ""}
{:else if col.key === "need_approval"}
@@ -751,6 +750,23 @@
❌
{/if}
+ {:else if col.key === "created_at"}
+
+
+ {new Date(
+ row[col.key as keyof Issue] as string,
+ ).toLocaleString("en-US")}
+ |
+ {:else if col.key === "updated_at"}
+
+ {row[col.key as keyof Issue]
+ ? new Date(
+ row[
+ col.key as keyof Issue
+ ] as string,
+ ).toLocaleString("en-US")
+ : ""}
+ |
{:else}
{row[col.key as keyof Issue]} | !excludedKeys.includes(col.key),
@@ -207,7 +219,7 @@
}
//validation project make
- function validateProjectCheckBox(project: insetProject): boolean {
+ function validateProjectCheckBox(project: insertProject): boolean {
if (!project.project_due_date) {
console.error("Project due date is required");
alert("Project due date is required");
@@ -259,6 +271,17 @@
}
async function addToPo(project: Project) {
+ // session user
+ const session = await supabase.auth.getSession();
+ const user = session?.data?.session?.user;
+ if (!user) {
+ console.error("User not authenticated");
+ alert("User not authenticated");
+ return;
+ }
+
+ const inputBy = user.id; // Use user id as input_by
+
if (!project.add_to_po) {
console.error("Project must be added to PO");
alert("Project must be added to PO");
@@ -274,6 +297,8 @@
input_by: project?.input_by,
project_due_date: project?.project_due_date,
picture_link: project?.picture_link,
+ updated_at: new Date().toISOString(),
+ updated_by: inputBy,
};
const { data, error } = await supabase
@@ -310,6 +335,16 @@
}
async function saveProject(event: Event) {
+ //get session user
+ const session = await supabase.auth.getSession();
+ const user = session?.data?.session?.user;
+ if (!user) {
+ console.error("User not authenticated");
+ return;
+ }
+
+ const inputBy = user.id; // Use email or id as input_by
+
const formData = new FormData(event.target as HTMLFormElement);
// Upload image if selected
@@ -326,12 +361,14 @@
imagePreviewUrl = data?.path;
}
- const projectUpdate: insetProject = {
+ const projectUpdate: insertProject = {
issue_id: formData.get("issue_id") as string,
- input_by: formData.get("input_by") as string,
+ input_by: inputBy,
project_due_date: formData.get("project_due_date") as string,
picture_link:
imagePreviewUrl || (formData.get("picture_link") as string),
+ updated_at: new Date().toISOString(),
+ updated_by: user.id,
};
// Validate project before saving
@@ -553,6 +590,42 @@
No Picture
{/if}
+ {:else if col.key === "project_due_date"}
+
+ {#if row.project_due_date}
+ {new Date(
+ row.project_due_date,
+ ).toLocaleString("en-US")}
+ {:else}
+ No Due Date
+ {/if}
+ |
+ {:else if col.key === "updated_at"}
+
+ {#if row.updated_at}
+ {new Date(
+ row.updated_at,
+ ).toLocaleString("en-US")}
+ {:else}
+ No Update
+ {/if}
+ |
+ {:else if col.key === "input_by"}
+
+ {#if row.input_by}
+ {row.input_by}
+ {:else}
+ Not Yet Input
+ {/if}
+ |
+ {:else if col.key === "updated_name"}
+
+ {#if row.updated_name}
+ {row.updated_name}
+ {:else}
+ No Updater
+ {/if}
+ |
{:else}
{row[col.key as keyof Projects]} | !excludedKeys.includes(col.key),
@@ -285,6 +304,18 @@
}
async function saveProject() {
+ // session check
+ const session = await supabase.auth.getSession();
+
+ if (!session.data.session) {
+ alert("You must be logged in to perform this action.");
+ return;
+ }
+
+ const user = session.data.session.user;
+
+ const inputBy = user.id;
+
if (!validateInput()) {
return;
}
@@ -297,6 +328,9 @@
po_price: newPurchaseOrders.po_price || 0,
po_total_price:
newPurchaseOrders.po_quantity * newPurchaseOrders.po_price || 0,
+ input_by: inputBy,
+ updated_by: inputBy,
+ updated_at: new Date().toISOString(),
};
if (isEditing && currentEditingId) {
@@ -400,13 +434,24 @@
}
async function updateProsesToApproval(id: string, status: boolean) {
+ const sessionId = await getSessionAuthId();
+ if (!sessionId) {
+ alert("You must be logged in to perform this action.");
+ return;
+ }
+
if (!validateInputProsesToAprroval()) {
return;
}
const { data, error } = await supabase
.from("vb_purchase_orders")
- .update({ proses_to_approval: status, po_status: "REQUESTED" })
+ .update({
+ proses_to_approval: status,
+ po_status: "REQUESTED",
+ updated_by: sessionId,
+ updated_at: new Date().toISOString(),
+ })
.eq("id", id);
if (error) {
@@ -425,6 +470,11 @@
id: string,
row: PurchaseOrderDisplay,
) {
+ const sessionId = await getSessionAuthId();
+ if (!sessionId) {
+ alert("You must be logged in to perform this action.");
+ return;
+ }
const selectedOption = (e.target as HTMLSelectElement)?.value ?? "";
const option = getStatusOption(selectedOption);
@@ -454,9 +504,19 @@
}
async function acknowledgedOk(id: string, status: boolean) {
+ const sessionId = await getSessionAuthId();
+ if (!sessionId) {
+ alert("You must be logged in to perform this action.");
+ return;
+ }
+
const { data, error } = await supabase
.from("vb_purchase_orders")
- .update({ acknowledged: status })
+ .update({
+ acknowledged: status,
+ updated_by: sessionId,
+ updated_at: new Date().toISOString(),
+ })
.eq("id", id);
if (error) {
@@ -468,9 +528,19 @@
}
async function receivedOk(id: string, status: boolean) {
+ const sessionId = await getSessionAuthId();
+ if (!sessionId) {
+ alert("You must be logged in to perform this action.");
+ return;
+ }
+
const { data, error } = await supabase
.from("vb_purchase_orders")
- .update({ receivedOk: status })
+ .update({
+ receivedOk: status,
+ updated_by: sessionId,
+ updated_at: new Date().toISOString(),
+ })
.eq("id", id);
if (error) {
@@ -486,6 +556,11 @@
id: string,
row: PurchaseOrderDisplay,
) {
+ const sessionId = await getSessionAuthId();
+ if (!sessionId) {
+ alert("You must be logged in to perform this action.");
+ return;
+ }
const selectedOption = (e.target as HTMLSelectElement)?.value ?? "";
const option = getStatusOption(selectedOption);
@@ -503,7 +578,11 @@
const { data, error } = await supabase
.from("vb_purchase_orders")
- .update({ approval: newPurchaseOrders.approval })
+ .update({
+ approval: newPurchaseOrders.approval,
+ updated_by: sessionId,
+ updated_at: new Date().toISOString(),
+ })
.eq("id", id);
if (error) {
@@ -515,9 +594,18 @@
}
async function completedStatusOk(id: string, status: string) {
+ const sessionId = await getSessionAuthId();
+ if (!sessionId) {
+ alert("You must be logged in to perform this action.");
+ return;
+ }
const { data, error } = await supabase
.from("vb_purchase_orders")
- .update({ completed_status: status })
+ .update({
+ completed_status: status,
+ updated_by: sessionId,
+ updated_at: new Date().toISOString(),
+ })
.eq("id", id);
if (error) {
@@ -753,6 +841,14 @@
>
+ {:else if col.key === "updated_at"}
+ {new Date(
+ row[
+ col.key as keyof PurchaseOrderDisplay
+ ] as string,
+ ).toLocaleString()} |
{:else if col.key === "actions"}
|
{:else}
{row[col.key as keyof TimesheetDisplay]}
@@ -811,138 +816,145 @@
{#if showModal}
-
-
-
-
+
{/if}
diff --git a/src/routes/backoffice/vendor/+page.svelte b/src/routes/backoffice/vendor/+page.svelte
index b162c41..ea41d6c 100644
--- a/src/routes/backoffice/vendor/+page.svelte
+++ b/src/routes/backoffice/vendor/+page.svelte
@@ -28,18 +28,6 @@
website: string;
};
- let allRowsVendor: Vendor[] = [];
- let currentPage = 1;
- let itemsPerPage = 10;
- $: offset = (currentPage - 1) * itemsPerPage;
- $: totalPages = Math.ceil(totalItems / itemsPerPage);
- let totalItems = 0;
- let newVendor: Record = {};
- let showModal = false;
- let isEditing = false;
- let currentEditingId: string | null = null;
- let searchTerm = "";
-
const columns = [
{ key: "name", title: "Name" },
{ key: "vendor_type", title: "Vendor Type" },
@@ -63,6 +51,19 @@
const excludedKeys = ["id", "created_by", "created_at", "updated_at"];
$: formColumns = columns.filter((col) => !excludedKeys.includes(col.key));
+ let allRowsVendor: Vendor[] = [];
+ let currentPage = 1;
+ let offset = 0;
+ let itemsPerPage = 10;
+ let totalItems = 0;
+ let newVendor: Record = {};
+ let showModal = false;
+ let isEditing = false;
+ let currentEditingId: string | null = null;
+ let searchTerm = "";
+ $: offset = (currentPage - 1) * itemsPerPage;
+ $: totalPages = Math.ceil(totalItems / itemsPerPage);
+
async function fetchVendor(search = "", resetPage = false) {
if (resetPage) currentPage = 1;
@@ -84,7 +85,13 @@
function resetPagination() {
currentPage = 1;
+ offset = 0;
+ totalItems = 0;
fetchVendor(searchTerm);
+ showModal = false;
+ isEditing = false;
+ currentEditingId = null;
+ newVendor = {};
}
function nextPage() {
@@ -102,6 +109,7 @@
}
function changePage(page: number) {
+ if (page < 1 || page > totalPages || page === currentPage) return;
currentPage = page;
fetchVendor(searchTerm);
}
@@ -159,7 +167,10 @@
}
async function deleteVendor(id: string) {
- const { error } = await supabase.from("vb_vendor").delete().eq("id", id);
+ const { error } = await supabase
+ .from("vb_vendor")
+ .delete()
+ .eq("id", id);
if (error) {
console.error("Delete error:", error);
} else {
@@ -167,7 +178,10 @@
}
}
- function pageRange(totalPages: number, currentPage: number): (number | string)[] {
+ function pageRange(
+ totalPages: number,
+ currentPage: number,
+ ): (number | string)[] {
const range: (number | string)[] = [];
const maxDisplay = 5;
@@ -207,79 +221,125 @@
fetchVendor(searchTerm, true);
}}
/>
- openModal()}>
+ openModal()}
+ >
➕ Add Vendor
-
-
-
- {#each columns as col}
- | {col.title} |
- {/each}
- Actions |
-
-
-
- {#each allRowsVendor as row}
-
+
+
+
+
{#each columns as col}
- | {row[col.key]} |
+ {col.title} |
{/each}
-
- openModal(row)}>✏️
- deleteVendor(row.id)}>🗑️
- |
+ Actions |
- {/each}
-
-
+
+
+ {#each allRowsVendor as row}
+
+ {#each columns as col}
+ | {row[col.key as keyof typeof row]} |
+ {/each}
+
+ openModal(row)}>✏️
+ deleteVendor(row.id)}>🗑️
+ |
+
+ {/each}
+
+
+
- Showing {(currentPage - 1) * itemsPerPage + 1}–
- {Math.min(currentPage * itemsPerPage, totalItems)} of {totalItems}
+ Page {currentPage} of {totalPages} | Showing
+ {currentPage === totalPages && totalItems > 0
+ ? totalItems - offset
+ : itemsPerPage} items | Showing
+ {offset + 1} to {Math.min(currentPage * itemsPerPage, totalItems)} of {totalItems}
- Prev
+ Prev
{#each pageRange(totalPages, currentPage) as page}
- {#if page === '...'}
+ {#if page === "..."}
...
{:else}
changePage(page)}
- class="px-2 py-1 border rounded {page === currentPage ? 'bg-blue-600 text-white' : ''}">
+ on:click={() => changePage(page as number)}
+ class="px-2 py-1 border rounded {page === currentPage
+ ? 'bg-blue-600 text-white'
+ : ''}"
+ >
{page}
{/if}
{/each}
- Next
+ = totalPages}
+ class="px-2 py-1 border rounded disabled:opacity-50">Next
{#if showModal}
-
-
- {isEditing ? "Edit Vendor" : "Add Vendor"}
- {#each formColumns as col}
-
-
- {#if col.key === 'vendor_unique'}
-
- {:else}
-
- {/if}
+
+
+
+ {isEditing ? "Edit Vendor" : "Add Vendor"}
+
+ {#each formColumns as col}
+
+
+ {#if col.key === "vendor_unique"}
+
+ {:else}
+
+ {/if}
+
+ {/each}
+
+ (showModal = false)}>Cancel
+ Save
- {/each}
-
- showModal = false}>Cancel
- Save
-
{/if}
|