perbaikan update villa
This commit is contained in:
@@ -20,3 +20,13 @@ export function timestampToDate(timestamp: number): string {
|
|||||||
|
|
||||||
return `${year}-${month}-${day}`;
|
return `${year}-${month}-${day}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatCurrency(value: number | string): string {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
value = parseFloat(value);
|
||||||
|
}
|
||||||
|
return new Intl.NumberFormat('id-ID', {
|
||||||
|
style: 'currency',
|
||||||
|
currency: 'IDR',
|
||||||
|
}).format(value);
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { supabase } from "$lib/supabaseClient";
|
import { supabase } from "$lib/supabaseClient";
|
||||||
|
import { formatCurrency } from "$lib/utils/conversion";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
@@ -23,13 +24,14 @@
|
|||||||
season_6_rate: number;
|
season_6_rate: number;
|
||||||
season_7_rate: number;
|
season_7_rate: number;
|
||||||
villa_email_address: string;
|
villa_email_address: string;
|
||||||
villa_recovery_email_adress: string;
|
villa_recovery_email_address: string;
|
||||||
owner_portal_username: string;
|
owner_portal_username: string;
|
||||||
owner_portal_password: string;
|
owner_portal_password: string;
|
||||||
created_by: string;
|
created_by: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let searchTerm: string = "";
|
||||||
let allRows: Villa[] = [];
|
let allRows: Villa[] = [];
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
let limit = 10;
|
let limit = 10;
|
||||||
@@ -70,7 +72,7 @@
|
|||||||
{ key: "season_7_rate", title: "Season 7 Rate" },
|
{ key: "season_7_rate", title: "Season 7 Rate" },
|
||||||
{ key: "villa_email_address", title: "Villa Email Address" },
|
{ key: "villa_email_address", title: "Villa Email Address" },
|
||||||
{
|
{
|
||||||
key: "villa_recovery_email_adress",
|
key: "villa_recovery_email_address",
|
||||||
title: "Villa Recovery Email Address",
|
title: "Villa Recovery Email Address",
|
||||||
},
|
},
|
||||||
{ key: "owner_portal_username", title: "Owner Portal Username" },
|
{ key: "owner_portal_username", title: "Owner Portal Username" },
|
||||||
@@ -159,15 +161,36 @@
|
|||||||
$: formColumns = columns.filter((col) => !excludedKeys.includes(col.key));
|
$: formColumns = columns.filter((col) => !excludedKeys.includes(col.key));
|
||||||
|
|
||||||
function openModal(villa?: Villa) {
|
function openModal(villa?: Villa) {
|
||||||
|
console.log("Opening modal for villa:", villa);
|
||||||
|
|
||||||
showModal = true;
|
showModal = true;
|
||||||
isEditing = !!villa;
|
isEditing = !!villa;
|
||||||
currentEditingId = villa?.id ?? null;
|
currentEditingId = villa?.id ?? null;
|
||||||
newVilla = {};
|
newVilla = currentEditingId ? { ...villa } : {};
|
||||||
|
|
||||||
|
console.log("New villa data:", newVilla);
|
||||||
|
|
||||||
for (const col of formColumns) {
|
for (const col of formColumns) {
|
||||||
newVilla[col.key] = villa
|
if (villa) {
|
||||||
? (villa[col.key as keyof Villa] ?? "")
|
// kalau kolom boolean, langsung pakai boolean
|
||||||
: "";
|
if (col.key === "closeable_living_room") {
|
||||||
|
newVilla[col.key] = villa.closeable_living_room ? "true" : "false";
|
||||||
|
} else if (col.key === "monthly_rental_pre_approved_status") {
|
||||||
|
newVilla[col.key] = villa.monthly_rental_pre_approved_status ? "true" : "false";
|
||||||
|
} else if (col.key === "long_term_rental_pre_approval") {
|
||||||
|
newVilla[col.key] = villa.long_term_rental_pre_approval ? "true" : "false";
|
||||||
|
} else if (col.key === "pet_allowed_pre_approval_status") {
|
||||||
|
newVilla[col.key] = villa.pet_allowed_pre_approval_status ? "true" : "false";
|
||||||
|
} else {
|
||||||
|
newVilla[col.key] = villa[col.key as keyof Villa] ?? "";
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
newVilla[col.key] = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(" new villa after processing:", newVilla);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//validation function
|
//validation function
|
||||||
@@ -195,7 +218,7 @@
|
|||||||
// "monthly_rental_pre_approved_status",
|
// "monthly_rental_pre_approved_status",
|
||||||
// "long_term_rental_pre_approval",
|
// "long_term_rental_pre_approval",
|
||||||
// "pet_allowed_pre_approval_status",
|
// "pet_allowed_pre_approval_status",
|
||||||
// "villa_recovery_email_adress",
|
// "villa_recovery_email_address",
|
||||||
// "villa_email_address",
|
// "villa_email_address",
|
||||||
];
|
];
|
||||||
requiredFields.forEach((field) => {
|
requiredFields.forEach((field) => {
|
||||||
@@ -222,8 +245,19 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newVilla.season_1_rate === "") newVilla.season_1_rate = 0;
|
||||||
|
if (newVilla.season_2_rate === "") newVilla.season_2_rate = 0;
|
||||||
|
if (newVilla.season_3_rate === "") newVilla.season_3_rate = 0;
|
||||||
|
if (newVilla.season_4_rate === "") newVilla.season_4_rate = 0;
|
||||||
|
if (newVilla.season_5_rate === "") newVilla.season_5_rate = 0;
|
||||||
|
if (newVilla.season_6_rate === "") newVilla.season_6_rate = 0;
|
||||||
|
if (newVilla.season_7_rate === "") newVilla.season_7_rate = 0;
|
||||||
|
|
||||||
if (isEditing && currentEditingId) {
|
if (isEditing && currentEditingId) {
|
||||||
const { error } = await supabase
|
console.log("Updating villa with ID:", currentEditingId);
|
||||||
|
console.log("New villa data:", newVilla);
|
||||||
|
|
||||||
|
const { data, error } = await supabase
|
||||||
.from("vb_villas")
|
.from("vb_villas")
|
||||||
.update(newVilla)
|
.update(newVilla)
|
||||||
.eq("id", currentEditingId);
|
.eq("id", currentEditingId);
|
||||||
@@ -231,6 +265,8 @@
|
|||||||
alert("Error updating villa: " + error.message);
|
alert("Error updating villa: " + error.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("Villa updated:", data);
|
||||||
} else {
|
} else {
|
||||||
const { error } = await supabase
|
const { error } = await supabase
|
||||||
.from("vb_villas")
|
.from("vb_villas")
|
||||||
@@ -241,8 +277,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await fetchVillas();
|
await fetchVillas(
|
||||||
|
searchTerm,
|
||||||
|
"created_at",
|
||||||
|
"desc",
|
||||||
|
rowsPerPage,
|
||||||
|
(currentPage - 1) * rowsPerPage,
|
||||||
|
);
|
||||||
showModal = false;
|
showModal = false;
|
||||||
|
|
||||||
|
alert(
|
||||||
|
isEditing ? "Villa updated successfully!" : "Villa added successfully!",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteVilla(id: string) {
|
async function deleteVilla(id: string) {
|
||||||
@@ -254,7 +300,13 @@
|
|||||||
if (error) {
|
if (error) {
|
||||||
alert("Error deleting villa: " + error.message);
|
alert("Error deleting villa: " + error.message);
|
||||||
} else {
|
} else {
|
||||||
await fetchVillas();
|
await fetchVillas(
|
||||||
|
searchTerm,
|
||||||
|
"created_at",
|
||||||
|
"desc",
|
||||||
|
rowsPerPage,
|
||||||
|
(currentPage - 1) * rowsPerPage,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,7 +325,13 @@
|
|||||||
if (error) {
|
if (error) {
|
||||||
console.error("Error updating villa status:", error);
|
console.error("Error updating villa status:", error);
|
||||||
} else {
|
} else {
|
||||||
await fetchVillas();
|
await fetchVillas(
|
||||||
|
searchTerm,
|
||||||
|
"created_at",
|
||||||
|
"desc",
|
||||||
|
rowsPerPage,
|
||||||
|
(currentPage - 1) * rowsPerPage,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +344,13 @@
|
|||||||
if (error) {
|
if (error) {
|
||||||
console.error("Error updating villa condition:", error);
|
console.error("Error updating villa condition:", error);
|
||||||
} else {
|
} else {
|
||||||
await fetchVillas();
|
await fetchVillas(
|
||||||
|
searchTerm,
|
||||||
|
"created_at",
|
||||||
|
"desc",
|
||||||
|
rowsPerPage,
|
||||||
|
(currentPage - 1) * rowsPerPage,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -307,10 +371,16 @@
|
|||||||
placeholder="🔍 Search by name..."
|
placeholder="🔍 Search by name..."
|
||||||
class="border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:outline-none px-4 py-2 rounded-xl text-sm w-64 transition"
|
class="border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:outline-none px-4 py-2 rounded-xl text-sm w-64 transition"
|
||||||
on:input={(e) => {
|
on:input={(e) => {
|
||||||
const searchTerm = (
|
searchTerm = (
|
||||||
e.target as HTMLInputElement
|
e.target as HTMLInputElement
|
||||||
).value.toLowerCase();
|
).value.toLowerCase();
|
||||||
fetchVillas(searchTerm, "created_at", "desc", limit, 0);
|
fetchVillas(
|
||||||
|
searchTerm,
|
||||||
|
"created_at",
|
||||||
|
"desc",
|
||||||
|
rowsPerPage,
|
||||||
|
0,
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<!-- filter -->
|
<!-- filter -->
|
||||||
@@ -339,7 +409,7 @@
|
|||||||
<button
|
<button
|
||||||
class="bg-gray-200 text-gray-700 px-4 py-2 rounded-xl hover:bg-gray-300 text-sm transition"
|
class="bg-gray-200 text-gray-700 px-4 py-2 rounded-xl hover:bg-gray-300 text-sm transition"
|
||||||
on:click={() =>
|
on:click={() =>
|
||||||
fetchVillas(null, "created_at", "desc", limit, 0)}
|
fetchVillas(null, "created_at", "desc", rowsPerPage, 0)}
|
||||||
>
|
>
|
||||||
🔄 Reset
|
🔄 Reset
|
||||||
</button>
|
</button>
|
||||||
@@ -499,31 +569,31 @@
|
|||||||
</td>
|
</td>
|
||||||
{:else if col.key === "season_1_rate"}
|
{:else if col.key === "season_1_rate"}
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
{row[col.key] || "N/A"}
|
{formatCurrency(row[col.key]) || "N/A"}
|
||||||
</td>
|
</td>
|
||||||
{:else if col.key === "season_2_rate"}
|
{:else if col.key === "season_2_rate"}
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
{row[col.key] || "N/A"}
|
{formatCurrency(row[col.key]) || "N/A"}
|
||||||
</td>
|
</td>
|
||||||
{:else if col.key === "season_3_rate"}
|
{:else if col.key === "season_3_rate"}
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
{row[col.key] || "N/A"}
|
{formatCurrency(row[col.key]) || "N/A"}
|
||||||
</td>
|
</td>
|
||||||
{:else if col.key === "season_4_rate"}
|
{:else if col.key === "season_4_rate"}
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
{row[col.key] || "N/A"}
|
{formatCurrency(row[col.key]) || "N/A"}
|
||||||
</td>
|
</td>
|
||||||
{:else if col.key === "season_5_rate"}
|
{:else if col.key === "season_5_rate"}
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
{row[col.key] || "N/A"}
|
{formatCurrency(row[col.key]) || "N/A"}
|
||||||
</td>
|
</td>
|
||||||
{:else if col.key === "season_6_rate"}
|
{:else if col.key === "season_6_rate"}
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
{row[col.key] || "N/A"}
|
{formatCurrency(row[col.key]) || "N/A"}
|
||||||
</td>
|
</td>
|
||||||
{:else if col.key === "season_7_rate"}
|
{:else if col.key === "season_7_rate"}
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
{row[col.key] || "N/A"}
|
{formatCurrency(row[col.key]) || "N/A"}
|
||||||
</td>
|
</td>
|
||||||
{:else if col.key === "actions"}
|
{:else if col.key === "actions"}
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
@@ -612,11 +682,9 @@
|
|||||||
)}"
|
)}"
|
||||||
bind:value={newVilla[col.key]}
|
bind:value={newVilla[col.key]}
|
||||||
>
|
>
|
||||||
<option value="" disabled selected
|
<option value="" disabled>SELECT STATUS</option>
|
||||||
>SELECT STATUS</option
|
<option value="Active">ACTIVE</option>
|
||||||
>
|
<option value="Inactive">INACTIVE</option>
|
||||||
<option value="available">ACTIVE</option>
|
|
||||||
<option value="rented">INACTIVE</option>
|
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -637,13 +705,12 @@
|
|||||||
)}"
|
)}"
|
||||||
bind:value={newVilla[col.key]}
|
bind:value={newVilla[col.key]}
|
||||||
>
|
>
|
||||||
<option value="" disabled selected
|
<option value="" disabled>SELECT CONDITION</option>
|
||||||
>SELECT CONDITION</option
|
<option value="Occupied">Occupied</option>
|
||||||
>
|
<option value="Vacant clean">Vacant clean</option>
|
||||||
<option value="new">New</option>
|
<option value="Vacant dirty">Vacant Dirty</option>
|
||||||
<option value="good">Good</option>
|
<option value="Ready for Inspection"
|
||||||
<option value="needs_maintenance"
|
>Ready for Inspection</option
|
||||||
>Needs Maintenance</option
|
|
||||||
>
|
>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@@ -664,9 +731,7 @@
|
|||||||
)}"
|
)}"
|
||||||
bind:value={newVilla[col.key]}
|
bind:value={newVilla[col.key]}
|
||||||
>
|
>
|
||||||
<option value="" disabled selected
|
<option value="" disabled>SELECT OPTION</option>
|
||||||
>SELECT OPTION</option
|
|
||||||
>
|
|
||||||
<option value="true">Yes</option>
|
<option value="true">Yes</option>
|
||||||
<option value="false">No</option>
|
<option value="false">No</option>
|
||||||
</select>
|
</select>
|
||||||
@@ -688,9 +753,7 @@
|
|||||||
)}"
|
)}"
|
||||||
bind:value={newVilla[col.key]}
|
bind:value={newVilla[col.key]}
|
||||||
>
|
>
|
||||||
<option value="" disabled selected
|
<option value="" disabled>SELECT OPTION</option>
|
||||||
>SELECT OPTION</option
|
|
||||||
>
|
|
||||||
<option value="true">Yes</option>
|
<option value="true">Yes</option>
|
||||||
<option value="false">No</option>
|
<option value="false">No</option>
|
||||||
</select>
|
</select>
|
||||||
@@ -712,9 +775,7 @@
|
|||||||
)}"
|
)}"
|
||||||
bind:value={newVilla[col.key]}
|
bind:value={newVilla[col.key]}
|
||||||
>
|
>
|
||||||
<option value="" disabled selected
|
<option value="" disabled>SELECT OPTION</option>
|
||||||
>SELECT OPTION</option
|
|
||||||
>
|
|
||||||
<option value="true">Yes</option>
|
<option value="true">Yes</option>
|
||||||
<option value="false">No</option>
|
<option value="false">No</option>
|
||||||
</select>
|
</select>
|
||||||
@@ -736,9 +797,7 @@
|
|||||||
)}"
|
)}"
|
||||||
bind:value={newVilla[col.key]}
|
bind:value={newVilla[col.key]}
|
||||||
>
|
>
|
||||||
<option value="" disabled selected
|
<option value="" disabled>SELECT OPTION</option>
|
||||||
>SELECT OPTION</option
|
|
||||||
>
|
|
||||||
<option value="true">Yes</option>
|
<option value="true">Yes</option>
|
||||||
<option value="false">No</option>
|
<option value="false">No</option>
|
||||||
</select>
|
</select>
|
||||||
@@ -748,7 +807,7 @@
|
|||||||
{$formErrors.pet_allowed_pre_approval_status}
|
{$formErrors.pet_allowed_pre_approval_status}
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
{:else if col.key === "session_1_rate" || col.key === "session_2_rate" || col.key === "session_3_rate" || col.key === "session_4_rate" || col.key === "session_5_rate" || col.key === "session_6_rate" || col.key === "session_7_rate"}
|
{:else if col.key === "season_1_rate" || col.key === "season_2_rate" || col.key === "season_3_rate" || col.key === "season_4_rate" || col.key === "season_5_rate" || col.key === "season_6_rate" || col.key === "season_7_rate"}
|
||||||
<div class="space-y-1">
|
<div class="space-y-1">
|
||||||
<label class="block text-sm font-medium text-gray-700"
|
<label class="block text-sm font-medium text-gray-700"
|
||||||
>{col.title}</label
|
>{col.title}</label
|
||||||
|
|||||||
Reference in New Issue
Block a user