aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/routes
diff options
context:
space:
mode:
authorivar <i@oiee.no>2025-12-26 13:18:15 +0100
committerivar <i@oiee.no>2025-12-26 13:18:15 +0100
commitfe0fe074ec8e8959bbdeff0ccc7f68d20b30e963 (patch)
tree032fcc7ee0b72899405a5046e7761d71fb029c9c /app/src/routes
parent874e1572298531dde9bc1d3ccdb704af0a045605 (diff)
downloadsparebank1-actualbudget-fe0fe074ec8e8959bbdeff0ccc7f68d20b30e963.tar.xz
sparebank1-actualbudget-fe0fe074ec8e8959bbdeff0ccc7f68d20b30e963.zip
WIP form
Diffstat (limited to 'app/src/routes')
-rw-r--r--app/src/routes/+page.server.ts5
-rw-r--r--app/src/routes/+page.svelte88
-rw-r--r--app/src/routes/actual.remote.ts22
-rw-r--r--app/src/routes/sb1-authorize/+server.ts7
-rw-r--r--app/src/routes/sb1.remote.ts5
5 files changed, 63 insertions, 64 deletions
diff --git a/app/src/routes/+page.server.ts b/app/src/routes/+page.server.ts
index 0d6016b..5d3e857 100644
--- a/app/src/routes/+page.server.ts
+++ b/app/src/routes/+page.server.ts
@@ -1,11 +1,12 @@
import type { PageServerLoad } from './$types';
-import { get_budgets } from '$lib/server/actual';
+import { get_accounts, get_budgets } from '$lib/server/actual';
import sb1 from "$lib/server/sb1"
export const load = (async () => {
return {
actual: {
- meta: await get_budgets()
+ budgets: await get_budgets(),
+ accounts: await get_accounts(),
},
sb1: {
accounts: (await sb1.data.get_accounts())?.accounts
diff --git a/app/src/routes/+page.svelte b/app/src/routes/+page.svelte
index 26db3e4..7b0a495 100644
--- a/app/src/routes/+page.svelte
+++ b/app/src/routes/+page.svelte
@@ -1,54 +1,80 @@
<script lang="ts">
import Button from "$lib/ui/button.svelte";
- import { clear_auth_session, get_transactions, init_auth_session } from "./sb1.remote";
+ import { clear_auth_session, init_auth_session } from "./sb1.remote";
import type { PageProps } from "./$types";
+ import { Temporal } from "temporal-polyfill";
+ import { instantAsHtmlInputValueString } from "$lib/helpers";
- let navigating = $state(false);
let { data }: PageProps = $props();
+ let navigating = $state(false);
+ let form = $state({
+ budgetId: "",
+ mappings: [] as Array<{ sb1: string; actual: string }>,
+ delta: instantAsHtmlInputValueString(Temporal.Now.instant().subtract("PT24H")),
+ dry: true,
+ });
+ async function run() {}
async function authorize() {
navigating = true;
const url = await init_auth_session();
location.href = url;
- navigating = false;
}
async function logout() {
+ navigating = true;
await clear_auth_session();
+ location.reload();
+ }
+
+ function mappingChanged(sb1: string, actual: string) {
+ let mappings = form.mappings;
+ if (mappings.find((c) => c.sb1 === sb1)) mappings = mappings.filter((c) => c.sb1 !== sb1);
+ mappings.push({ sb1, actual });
+ form.mappings = mappings;
}
+
+ $inspect(form);
</script>
<main>
{#if data.sb1.accounts?.length}
- <ul>
- {#each data.sb1.accounts as account}
- <li>{account.name}</li>
- {#if (await get_transactions(account.key))?.length}
- <ul>
- {#each await get_transactions(account.key) as transaction}
- <li>{JSON.stringify(transaction)}</li>
- {/each}
- </ul>
- {:else}
- <small>Ingen transaksjoner</small>
- {/if}
- {/each}
- </ul>
- <Button onclick={logout}>Logg ut</Button>
+ <form onsubmit={run}>
+ <h3>Importer</h3>
+ <fieldset>
+ <h4>Budsjett</h4>
+ {#each data.actual.budgets as budget}
+ {@const id = `budget-${budget.id}`}
+ <input name="budget" {id} value={budget.id} type="radio" bind:group={form.budgetId} />
+ <label for={id}>{budget.name}({budget.id})</label><br />
+ {/each}
+ <h4>Kontoer</h4>
+ {#each data.sb1.accounts as account}
+ {@const actualId = `mapping-${account.key}-actual`}
+ <div>
+ <code>{account.name}</code>
+ <span>&#8594;</span>
+ <label for={actualId}>Actual</label>
+ <select name={actualId} id={actualId} onchange={(e) => mappingChanged(account.key, e.currentTarget.value)}>
+ <option value="-" selected>-</option>
+ {#each data.actual.accounts as actual}
+ <option value={actual.id}>
+ {actual.name}
+ </option>
+ {/each}
+ </select>
+ </div>
+ {/each}
+ <h4>Ellers</h4>
+ <label for="delta">Importer transaksjoner siden</label>
+ <input type="date" id="delta" bind:value={form.delta} /><br />
+ <input type="checkbox" id="dry" bind:checked={form.dry} /><label for="dry">Tørrkjøring</label><br /><br />
+ <input type="submit" />
+ </fieldset>
+ </form>
+ <h3>Annet</h3>
+ <Button onclick={logout} loading={navigating}>Logg ut</Button>
{:else}
<Button onclick={authorize} loading={navigating}>Autentisér hos Sparebanken 1</Button>
{/if}
-
- {#if data.actual.meta}
- <pre>{JSON.stringify(data.actual.meta, null, 2)}</pre>
- {/if}
</main>
-
-<style>
- main {
- display: flex;
- justify-content: center;
- width: 100%;
- height: 90vh;
- }
-</style>
diff --git a/app/src/routes/actual.remote.ts b/app/src/routes/actual.remote.ts
deleted file mode 100644
index 9560d4d..0000000
--- a/app/src/routes/actual.remote.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { command, query } from "$app/server";
-import { ACTUAL_HOST, ACTUAL_PASS } from "$env/static/private";
-import * as actual from "@actual-app/api"
-import { existsSync, mkdirSync } from "node:fs";
-import path from "node:path";
-
-async function init_actual() {
- const dataDir = path.resolve(import.meta.dirname, "actualDataDir");
-
- if (!existsSync(dataDir)) mkdirSync(dataDir);
-
- return actual.init({
- password: ACTUAL_PASS,
- serverURL: ACTUAL_HOST,
- dataDir: dataDir
- })
-}
-
-export const get_actual_meta = query(async () => {
- await init_actual()
- return await actual.getBudgets()
-})
diff --git a/app/src/routes/sb1-authorize/+server.ts b/app/src/routes/sb1-authorize/+server.ts
index e08db3e..b3a0cf7 100644
--- a/app/src/routes/sb1-authorize/+server.ts
+++ b/app/src/routes/sb1-authorize/+server.ts
@@ -31,15 +31,14 @@ export const GET: RequestHandler = async ({ url }) => {
body: fd
})
- const text = await response.text()
+ const json = await response.json()
if (response.ok) {
const epoch = Temporal.Now.instant().epochMilliseconds
- await db.update(syncSession).set({ tokens: text, accessTokenCreated: epoch, refreshTokenCreated: epoch }).where(eq(syncSession.id, id))
+ await db.update(syncSession).set({ tokens: json, accessTokenCreated: epoch.toString(), refreshTokenCreated: epoch.toString() }).where(eq(syncSession.id, id))
redirect(302, "/")
} else {
- console.error(text)
- return new Response(text)
+ return new Response(json)
}
return new Response()
diff --git a/app/src/routes/sb1.remote.ts b/app/src/routes/sb1.remote.ts
index 9a2167e..1ee0155 100644
--- a/app/src/routes/sb1.remote.ts
+++ b/app/src/routes/sb1.remote.ts
@@ -8,10 +8,6 @@ const init_auth_session = command(async () => {
return await sb1.auth.init_auth_session()
})
-const is_ready = query(() => {
- return sb1.auth.is_ready()
-})
-
const get_accounts = query(() => {
return sb1.data.get_accounts()
})
@@ -35,7 +31,6 @@ const refresh_tokem = command(async () => {
export {
refresh_tokem,
init_auth_session,
- is_ready,
get_accounts,
get_transactions,
clear_auth_session,