Fix the editing bullshit

This commit is contained in:
2025-11-12 16:06:27 +01:00
parent d06b9a4acb
commit 812d69a911
2 changed files with 73 additions and 57 deletions

View File

@@ -10,15 +10,26 @@
};
export let monthFor: Date = new Date();
let showDatePicker = false;
let selectedDate = "";
let paymentDate: string = "";
let previousValidDate: string = "";
let dateElement: HTMLElement | null = null;
let isEditing = false;
$: {
if (paymentBill.payment && paymentBill.payment.paymentDate) {
if (!isEditing && paymentBill.payment && paymentBill.payment.paymentDate) {
// @ts-ignore Yes split exists... The type is time.Time but it's actually a string
paymentDate = paymentBill.payment.paymentDate.split("T")[0];
selectedDate = paymentDate;
const isoString = paymentBill.payment.paymentDate.split("T")[0];
paymentDate = isoString;
previousValidDate = isoString;
if (dateElement) {
dateElement.textContent = isoString;
}
} else if (!isEditing) {
paymentDate = "";
previousValidDate = "";
if (dateElement) {
dateElement.textContent = "";
}
}
}
@@ -28,17 +39,43 @@
throw new Error(`failed setting paid for ${paymentBill.id} and month ${monthFor} with error ${res.error}`);
}
paymentBill.payment = res.data;
showDatePicker = false;
}
async function doPaidWithDate() {
const dateObj = new Date(selectedDate + "T00:00:00");
function handleDateFocus() {
isEditing = true;
}
async function handleDateBlur(event: FocusEvent) {
isEditing = false;
const target = event.target as HTMLElement;
const newDate = target.textContent?.trim() || "";
if (!newDate) {
target.textContent = previousValidDate;
return;
}
if (!/^\d{4}-\d{2}-\d{2}$/.test(newDate)) {
target.textContent = previousValidDate;
return;
}
const isoDateString = newDate + "T00:00:00.000Z";
const dateObj = new Date(isoDateString);
if (isNaN(dateObj.getTime())) {
target.textContent = previousValidDate;
return;
}
const res = await SetPaidWithDate(paymentBill.id, monthFor, dateObj);
if (!res.success) {
target.textContent = previousValidDate;
throw new Error(`failed setting paid for ${paymentBill.id} with custom date: ${res.error}`);
}
paymentBill.payment = res.data;
showDatePicker = false;
previousValidDate = newDate;
paymentDate = newDate;
}
async function doUnmarkPaid() {
@@ -49,40 +86,46 @@
paymentBill.payment = null;
}
function openDatePicker() {
if (paymentBill.payment) {
showDatePicker = true;
} else {
doPaid();
}
}
</script>
<template>
<div class="bill-card p-3">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-2">
<div class="w-5 h-5 rounded-full flex items-center justify-center text-xs font-bold {paymentBill.payment == null ? 'bg-red-500' : 'bg-green-500'}">
<div class="flex items-center space-x-2 flex-1 min-w-0">
<div class="w-5 h-5 rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0 {paymentBill.payment == null ? 'bg-red-500' : 'bg-green-500'}">
{paymentBill.payment == null ? "!" : "✓"}
</div>
<div class="min-w-0">
<div class="min-w-0 flex-1 text-left">
<h3 class="text-sm font-semibold {paymentBill.payment == null ? 'text-red-400' : 'text-white'} truncate">
{paymentBill.name}
</h3>
<p class="text-xs text-white/60">
{paymentBill.payment == null ? 'Unpaid' : paymentDate}
</p>
{#if paymentBill.payment}
<p
contenteditable="true"
bind:this={dateElement}
class="text-xs text-white/60 outline-none"
on:focus={handleDateFocus}
on:blur={handleDateBlur}
>
{paymentDate}
</p>
{:else}
<p class="text-xs text-white/60">
Unpaid
</p>
{/if}
</div>
</div>
<div class="flex space-x-1">
<!-- svelte-ignore a11y-click-events-have-key-events -->
<button
class="px-2 py-1 text-xs rounded font-medium transition-all duration-200 bg-blue-500/20 hover:bg-blue-500/30 text-blue-400"
on:click={openDatePicker}
>
{paymentBill.payment == null ? 'Pay' : 'Edit'}
</button>
{#if paymentBill.payment}
{#if paymentBill.payment == null}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<button
class="px-2 py-1 text-xs rounded font-medium transition-all duration-200 bg-blue-500/20 hover:bg-blue-500/30 text-blue-400"
on:click={doPaid}
>
Pay
</button>
{:else}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<button
class="px-2 py-1 text-xs rounded font-medium transition-all duration-200 bg-red-500/20 hover:bg-red-500/30 text-red-400"
@@ -93,31 +136,5 @@
{/if}
</div>
</div>
{#if showDatePicker}
<div class="mt-2 p-2 bg-white/5 rounded border border-white/10">
<div class="flex flex-col space-y-2">
<input
type="date"
bind:value={selectedDate}
class="px-2 py-1 text-xs rounded bg-white/10 border border-white/20 text-white"
/>
<div class="flex space-x-1">
<button
class="px-2 py-1 text-xs rounded font-medium bg-blue-500/30 text-blue-400"
on:click={doPaidWithDate}
>
Set
</button>
<button
class="px-2 py-1 text-xs rounded font-medium bg-white/10 text-white/70"
on:click={() => showDatePicker = false}
>
Cancel
</button>
</div>
</div>
</div>
{/if}
</div>
</template>