penambahan download report

This commit is contained in:
Aji Setiaji
2025-07-10 16:17:35 +07:00
parent bdcffc401e
commit d9c4da138a
4 changed files with 454 additions and 32 deletions

View File

@@ -3,6 +3,7 @@
import { onMount } from "svelte";
import { writable } from "svelte/store";
import Pagination from "$lib/Pagination.svelte";
import { v4 as uuidv4 } from "uuid";
type Timesheets = {
id: number;
@@ -147,6 +148,8 @@
let isEditing = false;
let currentEditingId: string | null = null;
let newTsdata: Record<string, any> = {};
let selectedMonth: number | null = null;
let selectedYear: number | null = null;
let employees: Employee[] = [];
let villas: Villa[] = [];
let form = {
@@ -434,6 +437,47 @@
);
}
async function exportTimesheets() {
if (!selectedMonth || !selectedYear) {
alert("Please select a month and year to export.");
return;
}
try {
const response = await fetch("https://flow.catalis.app/webhook-test/villabugis-timesheets", {
method: "PATCH",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
month: selectedMonth,
year: selectedYear
})
});
if (!response.ok) {
throw new Error(`Export failed: ${response.statusText}`);
}
const randomUuid = uuidv4().toString();
// Jika response adalah file (application/octet-stream atau Excel)
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = `timesheet-${selectedYear}-${String(selectedMonth).padStart(2, '0')}-${randomUuid}.xlsx`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
} catch (error) {
console.error("Export error:", error);
alert("Failed to export timesheet.");
}
}
// // Function to fetch timesheets with optional filters and sorting
// async function fetchTimeSheets(
// villaIdFilter: string | null = null,
@@ -880,35 +924,73 @@
Showing {(currentPage - 1) * rowsPerPage + 1}
{Math.min(currentPage * rowsPerPage, totalItems)} of {totalItems} items
</div>
<div class="space-x-2">
<button
class="px-3 py-1 rounded border border-gray-300 bg-white hover:bg-gray-100 disabled:opacity-50"
on:click={() => goToPage(currentPage - 1)}
disabled={currentPage === 1}
>
Previous
</button>
{#each pageRange(totalPages, currentPage) as page}
{#if page === "..."}
<span class="px-2">...</span>
{:else}
<button
on:click={() => changePage(page as number)}
class="px-2 py-1 border rounded {page === currentPage
? 'bg-blue-600 text-white border-blue-600'
: 'bg-white border-gray-300 hover:bg-gray-100'}"
>
{page}
</button>
{/if}
{/each}
<button
class="px-3 py-1 rounded border border-gray-300 bg-white hover:bg-gray-100 disabled:opacity-50"
on:click={() => goToPage(currentPage + 1)}
disabled={currentPage === totalPages}
>
Next
</button>
<div class="flex items-center space-x-4">
<!-- Export Controls -->
<div class="">
<!-- Month Selector -->
<label for="month" class="text-sm">Month:</label>
<select
id="month"
class="border border-gray-300 px-2 py-1 rounded text-sm"
bind:value={selectedMonth}
>
<option value="" disabled selected>Select</option>
{#each Array.from({ length: 12 }, (_, i) => i + 1) as m}
<option value={m}>{m}</option>
{/each}
</select>
<!-- Year Selector -->
<label for="year" class="text-sm ml-2">Year:</label>
<select
id="year"
class="border border-gray-300 px-2 py-1 rounded text-sm"
bind:value={selectedYear}
>
<option value="" disabled selected>Select</option>
{#each Array.from({ length: 5 }, (_, i) => new Date().getFullYear() - i) as y}
<option value={y}>{y}</option>
{/each}
</select>
<!-- Export Button -->
<button
class="bg-green-600 text-white px-3 py-1 rounded hover:bg-green-700 text-sm"
on:click={exportTimesheets}
>
⬇️ Export
</button>
</div>
<div class="space-x-2">
<button
class="px-3 py-1 rounded border border-gray-300 bg-white hover:bg-gray-100 disabled:opacity-50"
on:click={() => goToPage(currentPage - 1)}
disabled={currentPage === 1}
>
Previous
</button>
{#each pageRange(totalPages, currentPage) as page}
{#if page === "..."}
<span class="px-2">...</span>
{:else}
<button
on:click={() => changePage(page as number)}
class="px-2 py-1 border rounded {page === currentPage
? 'bg-blue-600 text-white border-blue-600'
: 'bg-white border-gray-300 hover:bg-gray-100'}"
>
{page}
</button>
{/if}
{/each}
<button
class="px-3 py-1 rounded border border-gray-300 bg-white hover:bg-gray-100 disabled:opacity-50"
on:click={() => goToPage(currentPage + 1)}
disabled={currentPage === totalPages}
>
Next
</button>
</div>
</div>
</div>
</div>