Compare commits

..

No commits in common. "98765a3d2d5f539960bb05ebbd78d875636bc959" and "4cbe3fe0f9adfbdfeb19911bb3da3ad9b171aa8e" have entirely different histories.

4 changed files with 38 additions and 90 deletions

View File

@ -20,8 +20,6 @@ export interface Card {
name: string; name: string;
last_digits: string; last_digits: string;
currency_id: number; currency_id: number;
currency: Currency;
display_name: string;
} }
export interface Category { export interface Category {
@ -52,13 +50,7 @@ export interface Transfer {
from_card_id: number; from_card_id: number;
to_card_id: number; to_card_id: number;
value: number; value: number;
from_value: number;
to_value: number;
date: string; date: string;
show_value: string;
have_diff_currs: boolean;
from_card: Card;
to_card: Card;
} }
export interface Payment { export interface Payment {
@ -150,8 +142,8 @@ export type EntityType<T extends EntityName> =
// //
export async function getAll<T>(groupName: string, session?: string, queryParams?: string): Promise<T[] | ErrorMessage> { export async function getAll<T>(groupName: string, session?: string): Promise<T[] | ErrorMessage> {
const url = queryParams ? `${BASE_API_URL}/${groupName}/all?${queryParams}` : `${BASE_API_URL}/${groupName}/all` const url = `${BASE_API_URL}/${groupName}/all`
const defaultHeaders = { const defaultHeaders = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}; };

View File

@ -6,11 +6,10 @@ function isErrorMessage(value: any): value is ErrorMessage {
return value && typeof value.message === 'string'; return value && typeof value.message === 'string';
} }
export const GET: RequestHandler = async ({ cookies, params, url }): Promise<Response> => { export const GET: RequestHandler = async ({ cookies, params }): Promise<Response> => {
const session = cookies.get('session'); const session = cookies.get('session');
const { entity } = params; const { entity } = params;
const queryParams = url.searchParams.toString();
// Check if the entity is valid // Check if the entity is valid
if (!session) { if (!session) {
return new Response(JSON.stringify("no cookies"), { status: 401 }); return new Response(JSON.stringify("no cookies"), { status: 401 });
@ -22,7 +21,7 @@ export const GET: RequestHandler = async ({ cookies, params, url }): Promise<Res
// TypeScript type inference for entity // TypeScript type inference for entity
const entityName = entity as EntityName const entityName = entity as EntityName
const result = await getAll<EntityType<typeof entityName>>(entityName, session, queryParams); const result = await getAll<EntityType<typeof entityName>>(entityName, session);
if (isErrorMessage(result)) { if (isErrorMessage(result)) {
console.log("ERROR"); console.log("ERROR");

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { onMount, tick } from "svelte"; import { onMount } from "svelte";
import { type Card, type Currency } from "$lib/entities"; import { type Card, type Currency } from "$lib/entities";
import { NumberToFPA } from "$lib/util/fpa"; import { NumberToFPA } from "$lib/util/fpa";
@ -64,18 +64,14 @@
name: "", name: "",
}; };
} }
if (balanceRef) {
balanceRef.value = "";
}
} }
} }
async function editCard(card: Card) { function editCard(card: Card) {
editingCard = { ...card }; editingCard = { ...card };
if (balanceRef) { if (balanceRef) {
balanceRef.value = NumberToFPA(card.balance); balanceRef.value = NumberToFPA(card.balance);
} }
await tick();
if (creditLineRef) { if (creditLineRef) {
creditLineRef.value = NumberToFPA(card.credit_line); creditLineRef.value = NumberToFPA(card.credit_line);
} }

View File

@ -11,25 +11,18 @@
let error: string | null = $state(null); let error: string | null = $state(null);
let editingTransfer: Transfer | null = $state(null); let editingTransfer: Transfer | null = $state(null);
let newTransfer: Partial<Transfer> = $state({ let newTransfer: Partial<Transfer> = $state({
from_card_id: 0,
to_card_id: 0,
card_id: 0, card_id: 0,
value: 0, value: 0,
to_value: 0,
from_value: 0,
date: "2006-01-02T15:04:05Z", date: "2006-01-02T15:04:05Z",
}); });
onMount(async () => { onMount(async () => {
await fetchCategories(); await fetchCategories();
await fetchCards(true); await fetchCards();
}); });
async function fetchCards(preloadCurrencies = false) { async function fetchCards() {
const queryParams = new URLSearchParams({ const result = await fetch("/api/card/all");
preload_currencies: preloadCurrencies.toString(),
});
const result = await fetch(`/api/card/all?${queryParams}`);
if (!result.ok) { if (!result.ok) {
const obj = await result.json(); const obj = await result.json();
error = obj.message; error = obj.message;
@ -79,8 +72,6 @@
from_card_id: 0, from_card_id: 0,
to_card_id: 0, to_card_id: 0,
value: 0, value: 0,
to_value: 0,
from_value: 0,
date: "", date: "",
}; };
} }
@ -92,9 +83,6 @@
const parts = transfer.date.split("T"); const parts = transfer.date.split("T");
mutateDate = parts[0]; mutateDate = parts[0];
selectedTime = parts[1].split("Z")[0]; selectedTime = parts[1].split("Z")[0];
if (valueRef) {
valueRef.value = NumberToFPA(transfer.value);
}
} }
async function deleteTransfer(id: number) { async function deleteTransfer(id: number) {
@ -112,28 +100,19 @@
} }
// Helper function to get the name of the parent category // Helper function to get the name of the parent category
function doesCurrentTransferHasSameCurrencies(): boolean { function getCardName(cardId: number) {
if (currentTransfer.from_card_id == 0 || currentTransfer.to_card_id == 0) { if (cardId === 0) return "None";
return true; const card = cards.find((card) => card.id === cardId);
} return card ? card.name : "Unknown";
return (
cards.find((card) => card.id == currentTransfer.from_card_id)
?.currency_id ==
cards.find((card) => card.id == currentTransfer.to_card_id)?.currency_id
);
} }
let valueRef: HTMLInputElement | null = $state(null); function handleValueInput(
function createHandleValueInput(field: "value" | "from_value" | "to_value") { event: Event & { currentTarget: EventTarget & HTMLInputElement },
return function ( ): void {
event: Event & { currentTarget: EventTarget & HTMLInputElement }, const target = event.target as HTMLInputElement;
): void { const rawValue = target.value.replace(/[^0-9]/g, "");
const target = event.target as HTMLInputElement; currentTransfer.value = parseInt(rawValue || "0");
const rawValue = target.value.replace(/[^0-9]/g, ""); target.value = NumberToFPA(currentTransfer.value);
const parsedValue = parseInt(rawValue || "0");
currentTransfer[field] = parsedValue;
target.value = NumberToFPA(parsedValue);
};
} }
const constructedTime = $derived(`${mutateDate}T${selectedTime}Z`); const constructedTime = $derived(`${mutateDate}T${selectedTime}Z`);
@ -182,39 +161,15 @@
</select> </select>
</label> </label>
{#if doesCurrentTransferHasSameCurrencies()} <label class="block">
<label class="block"> <span class="text-gray-700">Value:</span>
<span class="text-gray-700">Value:</span> <input
<input type="text"
type="text" oninput={handleValueInput}
oninput={createHandleValueInput("value")} required
bind:this={valueRef} class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md focus:ring focus:ring-indigo-200 focus:border-indigo-500"
required />
class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md focus:ring focus:ring-indigo-200 focus:border-indigo-500" </label>
/>
</label>
{:else}
<label class="block">
<span class="text-gray-700">From Value:</span>
<input
type="text"
oninput={createHandleValueInput("from_value")}
bind:this={valueRef}
required
class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md focus:ring focus:ring-indigo-200 focus:border-indigo-500"
/>
</label>
<label class="block">
<span class="text-gray-700">To Value:</span>
<input
type="text"
oninput={createHandleValueInput("to_value")}
bind:this={valueRef}
required
class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md focus:ring focus:ring-indigo-200 focus:border-indigo-500"
/>
</label>
{/if}
<div class="flex items-center space-x-4"> <div class="flex items-center space-x-4">
<label> <label>
@ -263,12 +218,18 @@
class="bg-white p-4 rounded-lg shadow-md flex justify-between items-center" class="bg-white p-4 rounded-lg shadow-md flex justify-between items-center"
> >
<div> <div>
<strong class="block text-lg">{transfer.show_value}</strong> <strong class="block text-lg">{NumberToFPA(transfer.value)}</strong>
<div class="text-sm text-gray-600"> <div class="text-sm text-gray-600">
<span class="font-bold">From:</span> <span class="font-bold">From:</span>
{transfer.from_card.display_name} {getCardName(transfer.from_card_id)}
<span class="text-sm"
>{`•${cards.find((card) => card.id == transfer.from_card_id)?.last_digits}`}</span
>
<span class="font-bold">To:</span> <span class="font-bold">To:</span>
{transfer.to_card.display_name} {getCardName(transfer.to_card_id)}
<span class="text-sm"
>{`•${cards.find((card) => card.id == transfer.to_card_id)?.last_digits}`}</span
>
<span class="font-bold">Date:</span> <span class="font-bold">Date:</span>
{transfer.date} {transfer.date}
</div> </div>