221 lines
6.7 KiB
Svelte
221 lines
6.7 KiB
Svelte
<script>
|
|
import { EditSymbol } from '$lib/editSymbol.svelte';
|
|
import { settingsSymbol } from '$lib/settingsSymbol.svelte';
|
|
import { invalidate, invalidateAll } from '$app/navigation';
|
|
let { data } = $props();
|
|
let trans = $derived(data.transactions);
|
|
let budgets = $derived(data.budgets);
|
|
let budgetTransactions = $derived(data.budgetTransactions);
|
|
let notes = $state('');
|
|
let currentTransaction = $state({ budget_id: null, amount: 0, notes: '' });
|
|
let account = $derived(data.account);
|
|
let hide = $derived(account?.hide || false);
|
|
let inTotal = $derived(account?.in_total || false);
|
|
let expanded = $state([]);
|
|
|
|
function editNotes(transaction) {
|
|
my_modal_3.showModal();
|
|
currentTransaction = transaction;
|
|
notes = transaction.notes;
|
|
}
|
|
async function saveNotes() {
|
|
let res = fetch(`/transcation/${currentTransaction.id}`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ notes: $state.snapshot(notes) })
|
|
});
|
|
my_modal_3.close();
|
|
let result = await res;
|
|
if (result.ok) {
|
|
// Update the transaction in the data
|
|
currentTransaction.notes = notes;
|
|
// Optionally, you can also update the UI or show a success message
|
|
} else {
|
|
// Handle error case
|
|
console.error('Failed to save notes');
|
|
}
|
|
}
|
|
async function saveSettings() {
|
|
let res = await fetch(`/api/account/${account.id}`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
hide: $state.snapshot(hide),
|
|
in_total: $state.snapshot(inTotal)
|
|
})
|
|
});
|
|
if (res.ok) {
|
|
settings_modal.close();
|
|
// Optionally, you can refresh the account data or show a success message
|
|
} else {
|
|
console.error('Failed to save settings');
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div class="flex mb-4">
|
|
<div class="w-128 flex-none justify-bottom">
|
|
<h1 class="text-xl font-bold">{account?.name}</h1>
|
|
</div>
|
|
<div class="w-64 grow">{account?.balance}</div>
|
|
<div class="w-14 flex-none text-right">
|
|
<button class="btn btn-square btn-ghost" onclick={() => settings_modal.showModal()}
|
|
>{@render settingsSymbol()}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<h1>Transcations</h1>
|
|
<table class="table w-full">
|
|
<thead>
|
|
<tr>
|
|
<th>Date</th>
|
|
<th>Payee</th>
|
|
<th>Description</th>
|
|
<th>Amount</th>
|
|
<th>Notes</th>
|
|
<th>Budgets</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{#each trans as transaction}
|
|
{@const applicableBudgets = budgetTransactions.filter(
|
|
(bt) => bt.transaction_id === transaction.id
|
|
)}
|
|
{@const budgetTotal = applicableBudgets.reduce(
|
|
(accumulator, currentValue) => accumulator + Number(currentValue.amount),
|
|
0
|
|
)}
|
|
<tr class="hover:bg-base-300">
|
|
<td>{transaction.date.toDateString()}</td>
|
|
<td>{transaction.payee ?? ''}</td>
|
|
<td>{transaction.description}</td>
|
|
<td
|
|
><ul class="list bg-base-100 rounded-box shadow-md">
|
|
<li class="list-row">Amount: {transaction.amount}</li>
|
|
<li class="list-row">Budget: {budgetTotal.toFixed(2)}</li>
|
|
<li class="list-row">Remains: {(transaction.amount - budgetTotal).toFixed(2)}</li>
|
|
</ul></td
|
|
>
|
|
<td>{transaction.notes}</td>
|
|
<td>
|
|
<ul class="list bg-base-100 rounded-box shadow-md">
|
|
{#each applicableBudgets as budgetTransaction}
|
|
<li class="list-row">
|
|
<div class="flex">
|
|
<div class="flex-auto w-24">
|
|
{budgets.find((b) => b.id === budgetTransaction.budget_id)?.name}
|
|
</div>
|
|
<div class="flex-auto w-16">${budgetTransaction.amount}</div>
|
|
<div class="flex-auto w-48">{budgetTransaction.notes}</div>
|
|
</div>
|
|
</li>
|
|
{/each}
|
|
</ul></td
|
|
>
|
|
<td
|
|
><button class="btn btn-square btn-ghost" onclick={() => editNotes(transaction)}
|
|
>{@render EditSymbol()}</button
|
|
></td
|
|
>
|
|
</tr>
|
|
{/each}
|
|
</tbody>
|
|
</table>
|
|
|
|
<dialog id="my_modal_3" class="modal">
|
|
<div class="modal-box">
|
|
<form method="dialog">
|
|
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
|
|
</form>
|
|
<fieldset class="fieldset">
|
|
<p class="label">{currentTransaction?.description}</p>
|
|
<p class="label">${currentTransaction?.amount}</p>
|
|
<p class="label">{currentTransaction?.date?.toDateString()}</p>
|
|
<legend class="fieldset-legend">Notes</legend>
|
|
<textarea bind:value={notes} class="textarea w-100"></textarea>
|
|
|
|
<button class="btn btn-neutral" onclick={() => saveNotes()}>Save</button>
|
|
|
|
<legend class="fieldset-legend">Add to budget</legend>
|
|
<select bind:value={currentTransaction.budget_id} class="select">
|
|
<option disabled selected>Pick a budget</option>
|
|
{#each budgets as budget}
|
|
<option value={budget.id}>{budget.name} - {budget.sum}</option>
|
|
{/each}
|
|
</select>
|
|
<legend class="fieldset-legend">Amount</legend>
|
|
<input
|
|
bind:value={currentTransaction.amount}
|
|
type="number"
|
|
class="input validator"
|
|
required
|
|
placeholder="Amount"
|
|
title="Amount"
|
|
/>
|
|
<legend class="fieldset-legend">Notes</legend>
|
|
<textarea bind:value={currentTransaction.notes} class="textarea w-100"></textarea>
|
|
<p class="validator-hint">Must a sensible number</p>
|
|
<button
|
|
class="btn btn-primary"
|
|
onclick={() => {
|
|
if (currentTransaction.budget_id) {
|
|
fetch(`/api/budget/${currentTransaction.budget_id}/transaction`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
transactionId: currentTransaction.id,
|
|
amount: currentTransaction.amount,
|
|
notes: currentTransaction.notes
|
|
})
|
|
}).then((res) => {
|
|
if (res.ok) {
|
|
// Optionally, you can refresh the UI or show a success message
|
|
console.log('Transaction added to budget successfully');
|
|
} else {
|
|
console.error('Failed to add transaction to budget');
|
|
}
|
|
});
|
|
} else {
|
|
console.error('No budget selected');
|
|
}
|
|
}}>Add to Budget</button
|
|
>
|
|
</fieldset>
|
|
</div>
|
|
<form method="dialog" class="modal-backdrop">
|
|
<button>close</button>
|
|
</form>
|
|
</dialog>
|
|
|
|
<dialog id="settings_modal" class="modal">
|
|
<div class="modal-box">
|
|
<form method="dialog">
|
|
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
|
|
</form>
|
|
<h3>{account?.name}</h3>
|
|
<fieldset class="fieldset bg-base-100 border-base-300 rounded-box w-64 border p-4">
|
|
<legend class="fieldset-legend">Options</legend>
|
|
<label class="label">
|
|
<input type="checkbox" bind:checked={hide} class="toggle" />
|
|
Hide
|
|
</label>
|
|
<label class="label">
|
|
<input type="checkbox" bind:checked={inTotal} class="toggle" />
|
|
Use in total
|
|
</label>
|
|
</fieldset>
|
|
<button onclick={() => saveSettings()} class="btn btn-primary mt-4">Save</button>
|
|
</div>
|
|
<form method="dialog" class="modal-backdrop">
|
|
<button>close</button>
|
|
</form>
|
|
</dialog>
|