clean code

This commit is contained in:
2025-07-01 15:58:21 +08:00
parent edeb0870f3
commit a825334e3a
2 changed files with 364 additions and 454 deletions

View File

@@ -21,7 +21,6 @@
{ label: "Guest", value: "Guest" }, { label: "Guest", value: "Guest" },
{ label: "Agent", value: "Agent" }, { label: "Agent", value: "Agent" },
]; ];
const issueTypes = [ const issueTypes = [
{ label: "Facilities - Air Conditioner", value: "Facilities - Air Conditioner" }, { label: "Facilities - Air Conditioner", value: "Facilities - Air Conditioner" },
{ label: "Facilities - Appliances", value: "Facilities - Appliances" }, { label: "Facilities - Appliances", value: "Facilities - Appliances" },
@@ -83,18 +82,6 @@
{ label: "Other - Payment", value: "Other - Payment" }, { label: "Other - Payment", value: "Other - Payment" },
{ label: "Other - Transport", value: "Other - Transport" }, { label: "Other - Transport", value: "Other - Transport" },
]; ];
type PurchaseOrder = {
villa_id: string;
issue_id: string;
po_status: string;
requested_by: string;
requested_date: string;
po_due: string;
po_item: string;
po_quantity: string;
po_type: string;
};
const areaOfVilla = [ const areaOfVilla = [
{ label: "All Bathrooms", value: "All Bathrooms" }, { label: "All Bathrooms", value: "All Bathrooms" },
{ label: "All Guest Houses", value: "All Guest Houses" }, { label: "All Guest Houses", value: "All Guest Houses" },
@@ -149,147 +136,6 @@
{ label: "TV Room", value: "TV Room" }, { label: "TV Room", value: "TV Room" },
{ label: "Water Feature", value: "Water Feature" } { label: "Water Feature", value: "Water Feature" }
]; ];
type Villa = {
id: string;
villa_name: string;
};
type User = {
id: string;
employee_name: string;
};
let currentVillaFilter: string | null = null;
let currentSearchTerm: string | null = null;
let showProjectModal = false;
let selectedIssueId: string | null = null;
let showPurchaseOrderModal = false;
let newPO: PurchaseOrder = {
villa_id: "",
issue_id: "",
po_status: "requested",
requested_by: "",
requested_date: "",
po_due: "",
po_item: "",
po_quantity: "",
po_type: ""
};
let newProject = {
project_name: "",
issue_id: "",
input_by: "",
project_due_date: "",
assigned_to: "",
project_comment: ""
};
let dataVilla: Villa[] = [];
let dataUser: User[] = [];
let projectIssueMap: Set<string> = new Set();
let purchaseOrderMap: Set<string> = new Set();
async function fetchExistingProjectLinks() {
const { data, error } = await supabase
.from("vb_projects")
.select("issue_id");
if (!error && data) {
projectIssueMap = new Set(data.map((p) => p.issue_id));
} else {
console.error("Error loading existing projects:", error);
}
}
async function fetchExistingPurchaseOrders() {
const { data } = await supabase.from("vb_purchase_orders").select("issue_id");
if (data) purchaseOrderMap = new Set(data.map(p => p.issue_id));
}
onMount(async () => {
await fetchExistingProjectLinks();
const { data, error } = await supabase
.from("vb_villas")
.select("id, villa_name, villa_status")
.eq("villa_status", "Active");
if (error) {
console.error("Error fetching villas:", error);
} else if (data) {
dataVilla = data;
}
const { data: userData, error: userError } = await supabase
.from("vb_employee")
.select("id, employee_name, employee_status")
.eq("employee_status", "Active");
if (userError) {
console.error("Error fetching users:", userError);
} else if (userData) {
dataUser = userData;
}
});
type Issue = {
id: string;
villa_id: string;
villa_name: string;
area_of_villa: string;
priority: string;
issue_type: string;
issue_number: string;
move_issue: string;
description_of_the_issue: string;
reported_date: string;
issue_related_image: string;
issue_source: string;
reported_by: string;
input_by: string;
guest_communication: string;
resolution: string;
need_approval: boolean;
created_at: string;
updated_by?: string;
updated_at?: string;
};
type issueInsert = {
villa_id: string;
area_of_villa: string;
priority: string;
issue_type: string;
description_of_the_issue: string;
reported_date: string;
issue_related_image: string;
issue_source: string;
reported_by: string;
input_by: string;
guest_communication: string;
resolution: string;
need_approval: boolean;
};
type POItem = {
item_name: string;
};
let poItems: POItem[] = [];
async function fetchPoItems() {
const { data } = await supabase.from("vb_po_item").select("item_name");
if (data) poItems = data;
}
let allRows: Issue[] = [];
let offset = 0;
let limit = 10;
let totalItems = 0;
export let formErrors = writable<{ [key: string]: string }>({});
type columns = {
key: string;
title: string;
};
const columns: columns[] = [ const columns: columns[] = [
{ key: "description_of_the_issue", title: "Description of The Issue" }, { key: "description_of_the_issue", title: "Description of The Issue" },
{ key: "issue_number", title: "Issue Number" }, { key: "issue_number", title: "Issue Number" },
@@ -314,7 +160,165 @@
{ key: "updated_at", title: "Updated At" }, { key: "updated_at", title: "Updated At" },
{ key: "actions", title: "Actions" }, { key: "actions", title: "Actions" },
]; ];
const excludedKeys = [
"id",
"created_at",
"move_issue",
"issue_number",
"actions",
"villa_name",
"reported_name",
"inputed_name",
"updated_name",
"updated_at",
"updated_by",
];
const excludedKeysDisplay = [
"villa_id",
"reported_by",
"input_by",
"updated_by",
];
const formColumns = columns.filter(
(col) => !excludedKeys.includes(col.key),
);
const formColumnsDisplay = columns.filter(
(col) => !excludedKeysDisplay.includes(col.key),
);
// Define types for the data structures
type PurchaseOrder = {
villa_id: string;
issue_id: string;
po_status: string;
requested_by: string;
requested_date: string;
po_due: string;
po_item: string;
po_quantity: string;
po_type: string;
};
type Villa = {
id: string;
villa_name: string;
};
type User = {
id: string;
employee_name: string;
};
type Issue = {
id: string;
villa_id: string;
villa_name: string;
area_of_villa: string;
priority: string;
issue_type: string;
issue_number: string;
move_issue: string;
description_of_the_issue: string;
reported_date: string;
issue_related_image: string;
issue_source: string;
reported_by: string;
input_by: string;
guest_communication: string;
resolution: string;
need_approval: boolean;
created_at: string;
updated_by?: string;
updated_at?: string;
};
type issueInsert = {
villa_id: string;
area_of_villa: string;
priority: string;
issue_type: string;
description_of_the_issue: string;
reported_date: string;
issue_related_image: string;
issue_source: string;
reported_by: string;
input_by: string;
guest_communication: string;
resolution: string;
need_approval: boolean;
};
type POItem = {
item_name: string;
};
type columns = {
key: string;
title: string;
};
// Reactive variables
let currentVillaFilter: string | null = null;
let currentSearchTerm: string | null = null;
let showProjectModal = false;
let selectedIssueId: string | null = null;
let showPurchaseOrderModal = false;
let dataVilla: Villa[] = [];
let dataUser: User[] = [];
let projectIssueMap: Set<string> = new Set();
let purchaseOrderMap: Set<string> = new Set();
let poItems: POItem[] = [];
let newPO: PurchaseOrder = {
villa_id: "",
issue_id: "",
po_status: "requested",
requested_by: "",
requested_date: "",
po_due: "",
po_item: "",
po_quantity: "",
po_type: ""
};
let newProject = {
project_name: "",
issue_id: "",
input_by: "",
project_due_date: "",
assigned_to: "",
project_comment: ""
};
let allRows: Issue[] = [];
let showModal = false;
let isEditing = false;
let selectedFile: File | null = null;
let imagePreviewUrl: string | null = null;
let currentEditingId: string | null = null;
let newIssue: Record<string, any> = {};
let selectedIssueSummary = "";
let offset = 0;
let limit = 10;
let totalItems = 0;
let currentPage = offset + 1;
let rowsPerPage = limit;
$: totalPages = Math.ceil(totalItems / rowsPerPage);
// Fetch existing project links and purchase orders
async function fetchExistingProjectLinks() {
const { data, error } = await supabase
.from("vb_projects")
.select("issue_id");
if (!error && data) {
projectIssueMap = new Set(data.map((p) => p.issue_id));
} else {
console.error("Error loading existing projects:", error);
}
}
// Fetch existing purchase orders
async function fetchExistingPurchaseOrders() {
const { data } = await supabase.from("vb_purchase_orders").select("issue_id");
if (data) purchaseOrderMap = new Set(data.map(p => p.issue_id));
}
// Fetch PO items
async function fetchPoItems() {
const { data } = await supabase.from("vb_po_item").select("item_name");
if (data) poItems = data;
}
// Fetch issues with optional filters
async function fetchIssues( async function fetchIssues(
search: string | null = null, search: string | null = null,
villaNameFilter: string | null = null, villaNameFilter: string | null = null,
@@ -358,71 +362,7 @@
// Gabungkan data villa ke dalam setiap issue // Gabungkan data villa ke dalam setiap issue
allRows = issues; allRows = issues;
} }
// Function to handle form submission and save issue
let currentPage = offset + 1;
let rowsPerPage = limit;
$: totalPages = Math.ceil(totalItems / rowsPerPage);
function goToPage(page: number) {
if (page >= 1 && page <= totalPages) currentPage = page;
}
onMount(() => {
fetchIssues(null, null, "created_at", "desc", offset, limit);
fetchPoItems();
fetchExistingPurchaseOrders();
});
let showModal = false;
let isEditing = false;
let currentEditingId: string | null = null;
let newIssue: Record<string, any> = {};
const excludedKeys = [
"id",
"created_at",
"move_issue",
"issue_number",
"actions",
"villa_name",
"reported_name",
"inputed_name",
"updated_name",
"updated_at",
"updated_by",
];
const excludedKeysDisplay = [
"villa_id",
"reported_by",
"input_by",
"updated_by",
];
const formColumns = columns.filter(
(col) => !excludedKeys.includes(col.key),
);
const formColumnsDisplay = columns.filter(
(col) => !excludedKeysDisplay.includes(col.key),
);
function openModal(issue?: Record<string, any>) {
if (issue) {
if (projectIssueMap.has(issue.id)) {
alert("This issue is linked to a project and cannot be edited.");
return;
}
isEditing = true;
currentEditingId = issue.id;
newIssue = { ...issue };
} else {
isEditing = false;
currentEditingId = null;
newIssue = {};
}
showModal = true;
}
async function saveIssue(event: Event) { async function saveIssue(event: Event) {
const session = await supabase.auth.getSession(); const session = await supabase.auth.getSession();
const userId = session.data.session?.user.id; const userId = session.data.session?.user.id;
@@ -539,13 +479,12 @@
selectedFile = null; selectedFile = null;
} }
// function get public URL for image supabase // function get public URL for image supabase
async function getPublicUrl(path: string): Promise<string> { async function getPublicUrl(path: string): Promise<string> {
const { data } = supabase.storage.from("villabugis").getPublicUrl(path); const { data } = supabase.storage.from("villabugis").getPublicUrl(path);
return data.publicUrl; return data.publicUrl;
} }
// Function to handle issue deletion
async function deleteIssue(id: string) { async function deleteIssue(id: string) {
if (projectIssueMap.has(id)) { if (projectIssueMap.has(id)) {
alert("This issue is linked to a project and cannot be deleted."); alert("This issue is linked to a project and cannot be deleted.");
@@ -565,165 +504,7 @@
alert("Issue deleted."); alert("Issue deleted.");
} }
} }
// Function to submit project
let selectedFile: File | null = null;
let imagePreviewUrl: string | null = null;
function handleFileChange(event: Event) {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
selectedFile = input.files[0];
imagePreviewUrl = URL.createObjectURL(selectedFile);
}
}
function validateForm(formData: FormData): boolean {
const errors: { [key: string]: string } = {};
const requiredFields = [
"description_of_the_issue",
"issue_source",
"villa_id",
"reported_date",
"reported_by",
"priority",
"issue_type",
"input_by",
"area_of_villa",
];
requiredFields.forEach((field) => {
if (!formData.get(field) || formData.get(field) === "") {
errors[field] = `${field.replace(/_/g, " ")} is required.`;
}
});
formErrors.set(errors);
return Object.keys(errors).length === 0;
}
function errorClass(field: string): string {
return $formErrors[field] ? "border-red-500" : "border";
}
// insert id issue to project
async function moveIssueToProject(issueId: string) {
// get user id from session
const session = await supabase.auth.getSession();
if (!session) {
console.error("User not authenticated");
return;
}
const userId = session.data.session?.user.id;
// update move_issue field in the issue
const { error: updateError } = await supabase
.from("vb_issues")
.update({
move_issue: "PROJECT",
updated_by: userId,
updated_at: new Date().toISOString(),
})
.eq("id", issueId);
if (updateError) {
console.error("Error updating issue move_issue:", updateError);
return;
}
const { error } = await supabase
.from("vb_projects")
.insert({ issue_id: issueId });
if (error) {
console.error("Error moving issue to project:", error);
return;
}
alert(`Issue ${issueId} moved to project successfully.`);
await fetchIssues();
}
// open project modal
let selectedIssueSummary = "";
function openProjectModal(issue: Issue) {
const dueDate = new Date(issue.created_at);
dueDate.setDate(dueDate.getDate() + 2);
selectedIssueSummary = issue.description_of_the_issue ?? "";
newProject = {
project_name: "",
issue_id: issue.id,
input_by: "", // can be prefilled if desired
project_due_date: dueDate.toISOString().split("T")[0], // mm/dd/yyyy
assigned_to: "",
project_comment: ""
};
showProjectModal = true;
}
function openPurchaseOrderModal(issue) {
if (purchaseOrderMap.has(issue.id)) {
alert("This issue already has a purchase order.");
return;
}
const today = new Date();
const dueDate = new Date(today);
dueDate.setDate(dueDate.getDate() + 2);
const formatDate = (d) => d.toISOString().split("T")[0];
newPO = {
issue_id: issue.id,
villa_id: issue.villa_id,
po_status: "requested",
requested_by: "",
requested_date: formatDate(today),
po_due: formatDate(dueDate),
po_item: "",
po_quantity: "",
po_type: ""
};
selectedIssueSummary = issue.description_of_the_issue ?? "";
showPurchaseOrderModal = true;
}
async function submitPurchaseOrder() {
if (!newPO.requested_by || !newPO.po_item || !newPO.po_quantity || !newPO.po_type) {
alert("Please complete all required fields.");
return;
}
const { data: existing } = await supabase
.from("vb_purchase_orders")
.select("id")
.eq("issue_id", newPO.issue_id)
.maybeSingle();
if (existing) {
alert("Purchase order already exists for this issue.");
return;
}
const { error } = await supabase.from("vb_purchase_orders").insert(newPO);
if (error) {
console.error(error);
alert("Failed to create PO.");
return;
}
// reactively update map
purchaseOrderMap = new Set([...purchaseOrderMap, newPO.issue_id]);
alert("Purchase Order submitted!");
showPurchaseOrderModal = false;
}
async function submitProject() { async function submitProject() {
if (!newProject.project_name || !newProject.input_by || !newProject.assigned_to) { if (!newProject.project_name || !newProject.input_by || !newProject.assigned_to) {
alert("Please fill all required fields"); alert("Please fill all required fields");
@@ -776,45 +557,178 @@
alert("Project created successfully."); alert("Project created successfully.");
showProjectModal = false; showProjectModal = false;
} }
// Function to submit purchase order
async function submitPurchaseOrder() {
if (!newPO.requested_by || !newPO.po_item || !newPO.po_quantity || !newPO.po_type) {
// insert id issue to purchase order alert("Please complete all required fields.");
async function moveIssueToPurchaseOrder(issueId: string) {
// get user id from session
const session = await supabase.auth.getSession();
if (!session) {
console.error("User not authenticated");
return; return;
} }
const userId = session.data.session?.user.id; const { data: existing } = await supabase
// update move_issue field in the issue
const { error: updateError } = await supabase
.from("vb_issues")
.update({
move_issue: "PURCHASE_ORDER",
updated_by: userId,
updated_at: new Date().toISOString(),
})
.eq("id", issueId);
if (updateError) {
console.error("Error updating issue move_issue:", updateError);
return;
}
const { error } = await supabase
.from("vb_purchase_orders") .from("vb_purchase_orders")
.insert({ issue_id: issueId }); .select("id")
.eq("issue_id", newPO.issue_id)
.maybeSingle();
if (existing) {
alert("Purchase order already exists for this issue.");
return;
}
const { error } = await supabase.from("vb_purchase_orders").insert(newPO);
if (error) { if (error) {
console.error("Error moving issue to purchase order:", error); console.error(error);
alert("Failed to create PO.");
return; return;
} }
alert(`Issue ${issueId} moved to purchase order successfully.`);
await fetchIssues(); // reactively update map
purchaseOrderMap = new Set([...purchaseOrderMap, newPO.issue_id]);
alert("Purchase Order submitted!");
showPurchaseOrderModal = false;
} }
// Function to open purchase order modal
function openPurchaseOrderModal(issue) {
if (purchaseOrderMap.has(issue.id)) {
alert("This issue already has a purchase order.");
return;
}
const today = new Date();
const dueDate = new Date(today);
dueDate.setDate(dueDate.getDate() + 2);
const formatDate = (d) => d.toISOString().split("T")[0];
newPO = {
issue_id: issue.id,
villa_id: issue.villa_id,
po_status: "requested",
requested_by: "",
requested_date: formatDate(today),
po_due: formatDate(dueDate),
po_item: "",
po_quantity: "",
po_type: ""
};
selectedIssueSummary = issue.description_of_the_issue ?? "";
showPurchaseOrderModal = true;
}
// Function to open project modal
function openProjectModal(issue: Issue) {
const dueDate = new Date(issue.created_at);
dueDate.setDate(dueDate.getDate() + 2);
selectedIssueSummary = issue.description_of_the_issue ?? "";
newProject = {
project_name: "",
issue_id: issue.id,
input_by: "", // can be prefilled if desired
project_due_date: dueDate.toISOString().split("T")[0], // mm/dd/yyyy
assigned_to: "",
project_comment: ""
};
showProjectModal = true;
}
// Pagination functions
function goToPage(page: number) {
if (page >= 1 && page <= totalPages) currentPage = page;
}
// Function to handle page change
function openModal(issue?: Record<string, any>) {
if (issue) {
if (projectIssueMap.has(issue.id)) {
alert("This issue is linked to a project and cannot be edited.");
return;
}
isEditing = true;
currentEditingId = issue.id;
newIssue = { ...issue };
} else {
isEditing = false;
currentEditingId = null;
newIssue = {};
}
showModal = true;
}
// Function to handle file input change
function handleFileChange(event: Event) {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
selectedFile = input.files[0];
imagePreviewUrl = URL.createObjectURL(selectedFile);
}
}
// Function to validate form data
function validateForm(formData: FormData): boolean {
const errors: { [key: string]: string } = {};
const requiredFields = [
"description_of_the_issue",
"issue_source",
"villa_id",
"reported_date",
"reported_by",
"priority",
"issue_type",
"input_by",
"area_of_villa",
];
requiredFields.forEach((field) => {
if (!formData.get(field) || formData.get(field) === "") {
errors[field] = `${field.replace(/_/g, " ")} is required.`;
}
});
formErrors.set(errors);
return Object.keys(errors).length === 0;
}
// Function to get error class for form fields
function errorClass(field: string): string {
return $formErrors[field] ? "border-red-500" : "border";
}
// Fetch villas and users on mount
onMount(async () => {
await fetchExistingProjectLinks();
const { data, error } = await supabase
.from("vb_villas")
.select("id, villa_name, villa_status")
.eq("villa_status", "Active");
if (error) {
console.error("Error fetching villas:", error);
} else if (data) {
dataVilla = data;
}
const { data: userData, error: userError } = await supabase
.from("vb_employee")
.select("id, employee_name, employee_status")
.eq("employee_status", "Active");
if (userError) {
console.error("Error fetching users:", userError);
} else if (userData) {
dataUser = userData;
}
});
// Fetch issues, PO items, and existing purchase orders on mount
onMount(() => {
fetchIssues(null, null, "created_at", "desc", offset, limit);
fetchPoItems();
fetchExistingPurchaseOrders();
});
// Reactive store for form errors
export let formErrors = writable<{ [key: string]: string }>({});
</script> </script>
<div> <div>

View File

@@ -26,7 +26,6 @@
approved_date?: Date; approved_date?: Date;
created_at?: Date; created_at?: Date;
}; };
type TimesheetDisplay = { type TimesheetDisplay = {
id: number; id: number;
name: string; name: string;
@@ -50,7 +49,6 @@
remarks: string; remarks: string;
created_at?: Date; created_at?: Date;
}; };
type TimesheetsInsert = { type TimesheetsInsert = {
entered_by: string; entered_by: string;
work_description: string; work_description: string;
@@ -70,6 +68,15 @@
remarks: string; remarks: string;
approval: boolean | null; // Allow null for new entries approval: boolean | null; // Allow null for new entries
}; };
type Villa = {
id: string;
villa_name: string;
};
type columns = {
key: string;
title: string;
};
const categoryOfWork = [ const categoryOfWork = [
{ label: "Cleaning", value: "Cleaning" }, { label: "Cleaning", value: "Cleaning" },
@@ -80,52 +87,11 @@
{ label: "Administration", value: "Administration" }, { label: "Administration", value: "Administration" },
{ label: "Non Billable", value: "Non Billable" }, { label: "Non Billable", value: "Non Billable" },
]; ];
const typeOfWork = [ const typeOfWork = [
{ label: "Running", value: "Running" }, { label: "Running", value: "Running" },
{ label: "Periodic", value: "Periodic" }, { label: "Periodic", value: "Periodic" },
{ label: "Irregular", value: "Irregular" }, { label: "Irregular", value: "Irregular" },
]; ];
let currentUserId: string | null = null;
let currentVillaFilter: string | null = null;
let currentSearchTerm: string | null = null;
onMount(async () => {
const {
data: { user },
} = await supabase.auth.getUser();
currentUserId = user?.id ?? null;
});
type Villa = {
id: string;
villa_name: string;
};
let dataVilla: Villa[] = [];
onMount(async () => {
const { data, error } = await supabase
.from("vb_villas")
.select("id, villa_name")
.eq("villa_status", "Active");
if (error) {
console.error("Error fetching villas:", error);
} else if (data) {
dataVilla = data;
}
});
let allRows: TimesheetDisplay[] = [];
type columns = {
key: string;
title: string;
};
const columns: columns[] = [ const columns: columns[] = [
{ key: "name", title: "Work Description" }, { key: "name", title: "Work Description" },
{ key: "staff_id", title: "Staff Name" }, { key: "staff_id", title: "Staff Name" },
@@ -142,6 +108,35 @@
{ key: "created_at", title: "Created At" }, { key: "created_at", title: "Created At" },
{ key: "actions", title: "Actions" }, { key: "actions", title: "Actions" },
]; ];
// Store for current user ID and filters
let currentUserId: string | null = null;
let currentVillaFilter: string | null = null;
let currentSearchTerm: string | null = null;
let dataVilla: Villa[] = [];
let allRows: TimesheetDisplay[] = [];
onMount(async () => {
const {
data: { user },
} = await supabase.auth.getUser();
currentUserId = user?.id ?? null;
});
onMount(async () => {
const { data, error } = await supabase
.from("vb_villas")
.select("id, villa_name")
.eq("villa_status", "Active");
if (error) {
console.error("Error fetching villas:", error);
} else if (data) {
dataVilla = data;
}
});
// Function to calculate total work hours
function calculateTotalHours() { function calculateTotalHours() {
if (form.datetime_in && form.datetime_out) { if (form.datetime_in && form.datetime_out) {
const start = new Date(form.datetime_in); const start = new Date(form.datetime_in);
@@ -154,13 +149,14 @@
} }
} }
// Function to fetch timesheets with optional filters and sorting
async function fetchTimeSheets( async function fetchTimeSheets(
villaNameFilter: string | null = null, villaNameFilter: string | null = null,
searchTerm: string | null = null, searchTerm: string | null = null,
sortColumn: string | null = "created_at", sortColumn: string | null = "created_at",
sortOrder: "asc" | "desc" = "desc", sortOrder: "asc" | "desc" = "desc",
offset: number = 0, offset: number = 0,
limit: number = 10, limit: number = 1000,
) { ) {
let query = supabase let query = supabase
.from("vb_timesheet") .from("vb_timesheet")
@@ -269,7 +265,7 @@
// Sort the rows based on the sortColumn and sortOrder // Sort the rows based on the sortColumn and sortOrder
} }
let currentPage = 1; let currentPage = 1;
let rowsPerPage = 5; let rowsPerPage = 20;
$: totalPages = Math.ceil(allRows.length / rowsPerPage); $: totalPages = Math.ceil(allRows.length / rowsPerPage);
$: paginatedRows = allRows.slice( $: paginatedRows = allRows.slice(
(currentPage - 1) * rowsPerPage, (currentPage - 1) * rowsPerPage,