perbaikan data

This commit is contained in:
aji@catalis.app
2025-06-22 12:26:43 +07:00
parent 2e4ff82e98
commit 2ad0f5093d
10 changed files with 752 additions and 353 deletions

View File

@@ -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}