generated from dave/wails-template
Fix the editing bullshit
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user