perbaikan data
This commit is contained in:
176
src/routes/backoffice/vendor/+page.svelte
vendored
176
src/routes/backoffice/vendor/+page.svelte
vendored
@@ -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<string, any> = {};
|
||||
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<string, any> = {};
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
<button class="bg-blue-600 text-white px-4 py-2 rounded" on:click={() => openModal()}>
|
||||
<button
|
||||
class="bg-blue-600 text-white px-4 py-2 rounded"
|
||||
on:click={() => openModal()}
|
||||
>
|
||||
➕ Add Vendor
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Table -->
|
||||
<table class="min-w-[1000px] divide-y divide-gray-200 text-sm w-max">
|
||||
<thead class="bg-gray-100">
|
||||
<tr>
|
||||
{#each columns as col}
|
||||
<th class="p-2 text-left border">{col.title}</th>
|
||||
{/each}
|
||||
<th class="p-2 border">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each allRowsVendor as row}
|
||||
<tr class="hover:bg-gray-50">
|
||||
<div class="overflow-x-auto rounded-lg shadow mb-4">
|
||||
<table class="min-w-[1000px] divide-y divide-gray-200 text-sm w-max">
|
||||
<thead class="bg-gray-100">
|
||||
<tr>
|
||||
{#each columns as col}
|
||||
<td class="p-2 border">{row[col.key]}</td>
|
||||
<th class="p-2 text-left border">{col.title}</th>
|
||||
{/each}
|
||||
<td class="p-2 border">
|
||||
<button class="text-blue-600" on:click={() => openModal(row)}>✏️</button>
|
||||
<button class="text-red-600 ml-2" on:click={() => deleteVendor(row.id)}>🗑️</button>
|
||||
</td>
|
||||
<th class="p-2 border">Actions</th>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each allRowsVendor as row}
|
||||
<tr class="hover:bg-gray-50">
|
||||
{#each columns as col}
|
||||
<td class="p-2 border"
|
||||
>{row[col.key as keyof typeof row]}</td
|
||||
>
|
||||
{/each}
|
||||
<td class="p-2 border">
|
||||
<button
|
||||
class="text-blue-600"
|
||||
on:click={() => openModal(row)}>✏️</button
|
||||
>
|
||||
<button
|
||||
class="text-red-600 ml-2"
|
||||
on:click={() => deleteVendor(row.id)}>🗑️</button
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<div class="flex justify-between items-center mt-4 text-sm">
|
||||
<div>
|
||||
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}
|
||||
</div>
|
||||
|
||||
<div class="flex space-x-1">
|
||||
<button on:click={previousPage} disabled={currentPage === 1} class="px-2 py-1 border rounded disabled:opacity-50">Prev</button>
|
||||
<button
|
||||
on:click={previousPage}
|
||||
disabled={currentPage <= 1}
|
||||
class="px-2 py-1 border rounded disabled:opacity-50">Prev</button
|
||||
>
|
||||
{#each pageRange(totalPages, currentPage) as page}
|
||||
{#if page === '...'}
|
||||
{#if page === "..."}
|
||||
<span class="px-2">...</span>
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => 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}
|
||||
</button>
|
||||
{/if}
|
||||
{/each}
|
||||
<button on:click={nextPage} disabled={currentPage === totalPages} class="px-2 py-1 border rounded disabled:opacity-50">Next</button>
|
||||
<button
|
||||
on:click={nextPage}
|
||||
disabled={currentPage >= totalPages}
|
||||
class="px-2 py-1 border rounded disabled:opacity-50">Next</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
{#if showModal}
|
||||
<div class="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50">
|
||||
<div class="bg-white p-6 rounded w-[500px] max-h-[90vh] overflow-y-auto">
|
||||
<h2 class="text-lg font-semibold mb-4">{isEditing ? "Edit Vendor" : "Add Vendor"}</h2>
|
||||
{#each formColumns as col}
|
||||
<div class="mb-3">
|
||||
<label class="text-sm">{col.title}</label>
|
||||
{#if col.key === 'vendor_unique'}
|
||||
<input class="w-full p-2 border rounded bg-gray-100" bind:value={newVendor[col.key]} readonly />
|
||||
{:else}
|
||||
<input class="w-full p-2 border rounded" bind:value={newVendor[col.key]} />
|
||||
{/if}
|
||||
<div
|
||||
class="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50"
|
||||
>
|
||||
<div
|
||||
class="bg-white p-6 rounded w-[500px] max-h-[90vh] overflow-y-auto"
|
||||
>
|
||||
<h2 class="text-lg font-semibold mb-4">
|
||||
{isEditing ? "Edit Vendor" : "Add Vendor"}
|
||||
</h2>
|
||||
{#each formColumns as col}
|
||||
<div class="mb-3">
|
||||
<label class="text-sm">{col.title}</label>
|
||||
{#if col.key === "vendor_unique"}
|
||||
<input
|
||||
class="w-full p-2 border rounded bg-gray-100"
|
||||
bind:value={newVendor[col.key]}
|
||||
readonly
|
||||
/>
|
||||
{:else}
|
||||
<input
|
||||
class="w-full p-2 border rounded"
|
||||
bind:value={newVendor[col.key]}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
<div class="flex justify-end mt-4 space-x-2">
|
||||
<button
|
||||
class="px-4 py-2 bg-gray-200 rounded"
|
||||
on:click={() => (showModal = false)}>Cancel</button
|
||||
>
|
||||
<button
|
||||
class="px-4 py-2 bg-blue-600 text-white rounded"
|
||||
on:click={isEditing ? updateVendor : addVendor}>Save</button
|
||||
>
|
||||
</div>
|
||||
{/each}
|
||||
<div class="flex justify-end mt-4 space-x-2">
|
||||
<button class="px-4 py-2 bg-gray-200 rounded" on:click={() => showModal = false}>Cancel</button>
|
||||
<button class="px-4 py-2 bg-blue-600 text-white rounded" on:click={isEditing ? updateVendor : addVendor}>Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user