Files
OSIT-AE-App-Svelte/src/routes/journals/+page.svelte

218 lines
8.6 KiB
Svelte

<script lang="ts">
/**
* src/routes/journals/+page.svelte
* Modernized Journals Index View
* Focus: Simplicity for regular users, power tools for edit mode.
*/
import { onMount } from 'svelte';
import { goto } from '$app/navigation';
// *** Icons
import {
BookPlus, SquareLibrary, Wrench,
FileUp, Loader2, Sparkles
} from 'lucide-svelte';
// *** Libraries & Stores
import { liveQuery } from 'dexie';
import { Modal } from 'flowbite-svelte';
import { db_journals } from '$lib/ae_journals/db_journals';
import { journals_func } from '$lib/ae_journals/ae_journals_functions';
import { ae_loc, ae_api, slct } from '$lib/stores/ae_stores';
import {
journals_loc,
journals_sess,
journals_slct,
journals_trig
} from '$lib/ae_journals/ae_journals_stores';
// *** Components
import AeCompModalJournalConfig from './ae_comp__modal_journal_config.svelte';
import Journal_obj_li from './ae_comp__journal_obj_li.svelte';
import AeCompJournalEntryQuickAdd from './ae_comp__journal_entry_quick_add.svelte';
import AeCompModalJournalImport from './ae_comp__modal_journal_import.svelte';
interface Props {
data: any;
}
let { data }: Props = $props();
// *** State
let show_import_modal = $state(false);
let log_lvl = 0;
// *** LiveQueries
let lq__journal_obj_li = $derived(
liveQuery(async () => {
return await db_journals.journal
.where('person_id')
.equals($ae_loc.person_id)
.reverse()
.sortBy('tmp_sort_3');
})
);
async function create_journal() {
if (!confirm('Create a new journal?')) return;
const name = $journals_sess.journal.new_journal_name;
const type = $journals_sess.journal.new_journal_type_code;
if (name && type) {
try {
const results = await journals_func.create_ae_obj__journal({
api_cfg: $ae_api,
account_id: $slct.account_id,
data_kv: {
person_id_random: $ae_loc.person_id,
name,
type_code: type,
cfg_json: { category_li: [{ code: '', name: 'Default' }] }
}
});
if (results?.journal_id_random) {
$journals_sess.show__modal_new__journal_obj = false;
goto(`/journals/${results.journal_id_random}`);
}
} catch (error) {
alert('Failed to create journal.');
}
} else {
alert('Please provide a name and type.');
}
}
</script>
<div class="page_container flex flex-col gap-8 items-center w-full min-h-screen p-4 md:p-8">
<!-- Header Section -->
<header class="text-center space-y-2 max-w-3xl">
<h1 class="text-4xl md:text-5xl font-black tracking-tight text-surface-900 dark:text-surface-100">
<!-- <div class="p-3 bg-surface-500/10 rounded-2xl"> -->
<SquareLibrary size="1em" class="text-primary-500 inline-block" />
<!-- </div> -->
Journals
</h1>
<p class="text-surface-600 dark:text-surface-400 font-medium">
Managed by <span class="text-primary-500">{$ae_loc.account_name ?? 'Æ loading...'}</span>
{#if $ae_loc.person.given_name}
&bull; <span class="opacity-75">{$ae_loc.person.given_name}</span>
{/if}
</p>
</header>
<!-- Quick Add Integrated Section -->
<section class="w-full max-w-2xl">
<div class="relative group">
<div class="absolute -inset-1 bg-gradient-to-r from-primary-500 to-secondary-500 rounded-2xl blur opacity-25 group-hover:opacity-50 transition duration-1000 group-hover:duration-200"></div>
<AeCompJournalEntryQuickAdd
journals_li={$lq__journal_obj_li}
class="relative shadow-2xl rounded-xl overflow-hidden border border-surface-500/10 bg-surface-50 dark:bg-surface-900"
/>
</div>
<div class="mt-2 flex items-center justify-center gap-2 text-xs opacity-50 font-bold uppercase tracking-widest">
<Sparkles size="1em" />
<span>Fast Input Mode Active</span>
</div>
</section>
<!-- Administrative Action Bar (Edit Mode Only) -->
{#if $ae_loc.edit_mode}
<nav class="flex flex-row flex-wrap gap-3 items-center justify-center w-full py-4 border-y border-surface-500/10">
<button type="button"
class="btn variant-filled-secondary shadow-lg hover:scale-105 transition-transform"
onclick={() => $journals_sess.show__modal_new__journal_obj = true}
>
<BookPlus size="1.2em" class="mr-2" />
<span>New Journal</span>
</button>
<button type="button"
class="btn variant-filled-surface border border-surface-500/30 shadow-lg hover:scale-105 transition-transform"
onclick={() => show_import_modal = true}
>
<FileUp size="1.2em" class="mr-2" />
<span>Import</span>
</button>
<button type="button"
class="btn variant-soft-surface shadow-lg hover:scale-105 transition-transform"
onclick={() => $journals_sess.show__modal__journals_config = true}
>
<Wrench size="1.2em" class="mr-2" />
<span>Config</span>
</button>
</nav>
{/if}
<!-- Main List Section -->
<main class="w-full flex justify-center">
{#if $lq__journal_obj_li === undefined}
<div class="flex flex-col items-center justify-center p-20 gap-4 opacity-50">
<Loader2 size="3em" class="animate-spin" />
<p class="text-xl font-bold">Accessing Brain...</p>
</div>
{:else if $lq__journal_obj_li.length > 0}
<Journal_obj_li {lq__journal_obj_li} />
{:else}
<div class="max-w-md text-center p-12 bg-surface-500/5 rounded-3xl border-2 border-dashed border-surface-500/20">
<SquareLibrary size="4em" class="mx-auto mb-4 opacity-20" />
<h3 class="text-2xl font-bold mb-2">No Journals Found</h3>
<p class="opacity-60 mb-6">You haven't created any journals yet. Start by creating one to begin your documentation journey.</p>
<button type="button"
class="btn variant-filled-primary"
onclick={() => $journals_sess.show__modal_new__journal_obj = true}
>
Create Your First Journal
</button>
</div>
{/if}
</main>
</div>
<!-- Modals -->
{#if $journals_sess.show__modal_new__journal_obj}
<Modal
title="Create New Journal"
bind:open={$journals_sess.show__modal_new__journal_obj}
autoclose={false}
size="md"
class="bg-white dark:bg-surface-900 shadow-2xl rounded-2xl"
>
<div class="p-2 space-y-4">
<div class="space-y-1">
<label class="label text-sm font-bold opacity-75">Journal Name</label>
<input
type="text"
placeholder="e.g. My Daily Logs"
bind:value={$journals_sess.journal.new_journal_name}
class="input variant-filled-surface rounded-lg"
/>
</div>
<div class="space-y-1">
<label class="label text-sm font-bold opacity-75">Type Code</label>
<input
type="text"
placeholder="e.g. diary, log, notebook"
bind:value={$journals_sess.journal.new_journal_type_code}
class="input variant-filled-surface rounded-lg"
/>
</div>
<div class="flex justify-end gap-2 pt-4">
<button type="button" class="btn variant-soft-surface" onclick={() => $journals_sess.show__modal_new__journal_obj = false}>Cancel</button>
<button type="button" class="btn variant-filled-primary font-bold" onclick={create_journal}>Create Journal</button>
</div>
</div>
</Modal>
{/if}
{#if $journals_sess.show__modal__journals_config}
<AeCompModalJournalConfig show={$journals_sess.show__modal__journals_config} />
{/if}
<AeCompModalJournalImport
bind:open={show_import_modal}
on_close={() => (show_import_modal = false)}
on_import_complete={() => {}}
/>