style(journals): standardize configuration interfaces across module

- Refactored Module, Journal, and Entry configs to use consistent tabbed layouts.
- Adopted unified 'Aether Orange' aesthetic with Skeleton UI and Lucide icons.
- Replaced overcrowded inline settings menu with 'ModalJournalEntryConfig'.
- Cleaned up Header component logic and improved visual consistency.
This commit is contained in:
Scott Idem
2026-01-14 17:17:56 -05:00
parent 04e4350fbf
commit 8ae23cdcd9
5 changed files with 732 additions and 1646 deletions

View File

@@ -1,81 +1,42 @@
<script lang="ts">
interface Props {
log_lvl?: number;
show?: boolean;
tab?: string;
}
let {
log_lvl = $bindable(0),
show = $bindable(true),
tab = $bindable('form') // form, local_json, session_json
}: Props = $props();
/**
* modal_journals_config.svelte
* Standardized Global/Module configuration for Journals.
*/
import {
ArrowDown01,
ArrowDown10,
ArrowDownUp,
BetweenVerticalEnd,
BetweenVerticalStart,
Bot,
BookHeart,
BookImage,
Bookmark,
BookOpenText,
BriefcaseBusiness,
CalendarClock,
Check,
Copy,
Expand,
Eye,
EyeOff,
Flag,
FlagOff,
FilePlus,
Fingerprint,
Globe,
Library,
MessageSquareWarning,
Minus,
Notebook,
Pencil,
Plus,
RefreshCcw,
RemoveFormatting,
SquareLibrary,
Shapes,
Share2,
Settings,
X,
Database,
CodeXml,
ShieldCheck,
ShieldMinus,
Siren,
Skull,
Tags,
Target,
ToggleLeft,
ToggleRight,
Trash2,
TypeOutline,
X
BookOpenText,
MousePointerClick
} from '@lucide/svelte';
import { Modal } from 'flowbite-svelte';
import {
ae_snip,
ae_loc,
ae_sess,
ae_api,
ae_trig,
slct,
slct_trigger
ae_api
} from '$lib/stores/ae_stores';
import {
journals_loc,
journals_sess,
journals_slct,
journals_prom,
journals_trig
journals_sess
} from '$lib/ae_journals/ae_journals_stores';
import E_app_codemirror_v5 from '$lib/app_components/e_app_codemirror_v5.svelte';
interface Props {
log_lvl?: number;
show?: boolean;
}
let {
log_lvl = $bindable(0),
show = $bindable(false)
}: Props = $props();
let tab: 'form' | 'local_json' | 'session_json' = $state('form');
</script>
<Modal
@@ -83,102 +44,52 @@
autoclose={false}
placement="top-center"
size="xl"
class="
top-center
relative
flex flex-col
mx-auto w-full
bg-white dark:bg-gray-800
text-gray-800 dark:text-gray-200
border border-orange-300 dark:border-orange-700 rounded-lg
shadow-xl
"
headerClass="
flex flex-row gap-2 items-center justify-between
w-full
bg-orange-100 dark:bg-orange-900
"
footerClass="
flex flex-row gap-2 items-center justify-center
w-full
bg-orange-100 dark:bg-orange-900
"
class="relative flex flex-col mx-auto w-full bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 border border-orange-300 dark:border-orange-700 rounded-lg shadow-xl"
headerClass="flex flex-row gap-2 items-center justify-between w-full bg-orange-100 dark:bg-orange-900 p-4 rounded-t-lg"
footerClass="flex flex-row gap-2 items-center justify-center w-full bg-orange-100 dark:bg-orange-900 p-4 rounded-b-lg"
>
{#snippet header()}
<h3>
<span class="text-base font-semibold">
<span class="text-primary-500">
<BookOpenText class="inline-block mr-1" />
</span>
&AElig; Journals Settings:
</span>
{$journals_loc?.name ?? '-- not set --'}
<h3 class="flex items-center gap-2 text-lg font-bold">
<Settings class="text-primary-500" />
<span>&AElig; Journals Module Settings</span>
</h3>
{/snippet}
<div class="modal h-full md:pb-24">
<div class="modal-box space-y-2">
<!-- Menu to toggle between viewing JSON and the form view -->
<div class="flex flex-row gap-1 items-center justify-center">
<button
type="button"
class:preset-outlined-surface-200-800={tab === 'form'}
class="
btn btn-sm
preset-outlined-surface-50-950
transition-all
"
onclick={() => (tab = 'form')}
>
<span class="fas fa-cog mr-1"></span>
Config
</button>
<button
type="button"
class:preset-outlined-surface-200-800={tab === 'local_json'}
class="
btn btn-sm
preset-outlined-surface-50-950
transition-all
"
onclick={() => (tab = 'local_json')}
>
<span class="fas fa-code mr-1"></span>
Local JSON
</button>
<button
type="button"
class:preset-outlined-surface-200-800={tab === 'session_json'}
class="
btn btn-sm
preset-outlined-surface-50-950
transition-all
"
onclick={() => (tab = 'session_json')}
>
<span class="fas fa-code mr-1"></span>
Session JSON
</button>
</div>
<!-- Section for the configuration form -->
<div
class:hidden={tab !== 'form'}
class="flex flex-col gap-6 items-start justify-start p-2"
<div class="space-y-6 py-2 h-[60vh] overflow-y-auto px-4">
<!-- Navigation Tabs -->
<div class="flex justify-center gap-1 mb-4 p-1 bg-surface-500/10 rounded-lg max-w-fit mx-auto">
<button
class="btn btn-sm transition-all {tab === 'form' ? 'variant-filled-primary' : 'variant-soft-surface'}"
onclick={() => (tab = 'form')}
>
<div class="w-full space-y-4">
<h2 class="h2 text-xl font-bold flex items-center gap-2 border-b border-surface-500/30 pb-2">
<CalendarClock class="text-primary-500" />
Date and Time Settings
</h2>
<Settings size="1.1em" class="mr-1" /> Config
</button>
<button
class="btn btn-sm transition-all {tab === 'local_json' ? 'variant-filled-primary' : 'variant-soft-surface'}"
onclick={() => (tab = 'local_json')}
>
<Database size="1.1em" class="mr-1" /> Local JSON
</button>
<button
class="btn btn-sm transition-all {tab === 'session_json' ? 'variant-filled-primary' : 'variant-soft-surface'}"
onclick={() => (tab = 'session_json')}
>
<CodeXml size="1.1em" class="mr-1" /> Session JSON
</button>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
{#if tab === 'form'}
<div class="space-y-8 animate-in fade-in duration-300">
<!-- Date/Time Section -->
<section class="space-y-4">
<h2 class="text-xl font-bold flex items-center gap-2 border-b border-surface-500/30 pb-2">
<CalendarClock size="1.2em" class="text-primary-500" />
Date and Time Display
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 p-2">
<label class="label">
<span>DateTime Format</span>
<select
bind:value={$journals_loc.datetime_format}
class="select"
>
<span class="text-sm font-bold opacity-70">DateTime Format</span>
<select bind:value={$journals_loc.datetime_format} class="select select-sm variant-form-material">
<option value="datetime_12_short">MMM D, YY hh:mm A</option>
<option value="datetime_12_long">MMMM D, YYYY hh:mm A</option>
<option value="datetime_short">MMM D, YY HH:mm</option>
@@ -187,67 +98,86 @@
<option value="datetime_iso">ISO (YYYY-MM-DD HH:mm:ss)</option>
</select>
</label>
<label class="label">
<span>Time Format</span>
<select
bind:value={$journals_loc.time_format}
class="select"
>
<option value="time_12_short">12-hour short (e.g., 3:30 PM)</option>
<option value="time_12_long">12-hour long (e.g., 3:30:45 PM)</option>
<option value="time_short">24-hour short (e.g., 15:30)</option>
<option value="time_long">24-hour long (e.g., 15:30:45)</option>
<span class="text-sm font-bold opacity-70">Time-Only Format</span>
<select bind:value={$journals_loc.time_format} class="select select-sm variant-form-material">
<option value="time_12_short">12-hour short (3:30 PM)</option>
<option value="time_12_long">12-hour long (3:30:45 PM)</option>
<option value="time_short">24-hour short (15:30)</option>
<option value="time_long">24-hour long (15:30:45)</option>
</select>
</label>
</div>
</div>
</div>
</section>
<!-- Section for viewing (and direct editing???) the raw localStorage JSON configuration -->
<div class:hidden={tab !== 'local_json'} class="">
<!-- UI Section -->
<section class="space-y-4">
<h2 class="text-xl font-bold flex items-center gap-2 border-b border-surface-500/30 pb-2">
<MousePointerClick size="1.2em" class="text-primary-500" />
User Interface Preferences
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 p-2">
<label class="flex items-center space-x-3 cursor-pointer p-2 rounded-lg bg-surface-500/5 border border-surface-500/10">
<input type="checkbox" bind:checked={$journals_loc.entry.auto_save} class="checkbox" />
<div class="space-y-0.5">
<span class="font-bold">Enable Auto-Save</span>
<p class="text-xs opacity-60">Automatically sync changes while editing</p>
</div>
</label>
<label class="flex items-center space-x-3 cursor-pointer p-2 rounded-lg bg-surface-500/5 border border-surface-500/10">
<input type="checkbox" bind:checked={$journals_loc.show_id_random} class="checkbox" />
<div class="space-y-0.5">
<span class="font-bold">Show Technical IDs</span>
<p class="text-xs opacity-60">Display UUIDs in metadata footers</p>
</div>
</label>
</div>
</section>
<!-- Security Section -->
<section class="space-y-4">
<h2 class="text-xl font-bold flex items-center gap-2 border-b border-surface-500/30 pb-2">
<ShieldCheck size="1.2em" class="text-primary-500" />
Security & Encryption
</h2>
<div class="p-4 bg-orange-500/5 rounded-lg border border-orange-500/20 space-y-4">
<div class="text-sm opacity-80 italic">
Global security overrides for the journal module.
</div>
<label class="flex items-center space-x-3 cursor-pointer">
<input type="checkbox" bind:checked={$journals_sess.enable_session_passcode_cache} class="checkbox checkbox-primary" />
<span class="text-sm font-bold">Cache Passcodes in Session</span>
</label>
</div>
</section>
</div>
{:else if tab === 'local_json'}
<div class="h-full min-h-[400px]">
<E_app_codemirror_v5
editable={false}
readonly={true}
content={JSON.stringify($journals_loc, null, 2)}
show_line_numbers={false}
placeholder=""
class="
p-1
preset-outlined-surface-100-900
rounded-lg
"
theme_mode={$ae_loc.theme_mode}
class="rounded-lg border border-surface-500/30"
/>
<!-- <pre class="text-wrap">
{JSON.stringify($journals_loc, null, 2)}
</pre> -->
</div>
<!-- Section for viewing (and direct editing???) the raw sessionStorage JSON configuration -->
<div class:hidden={tab !== 'session_json'} class="">
{:else if tab === 'session_json'}
<div class="h-full min-h-[400px]">
<E_app_codemirror_v5
editable={false}
readonly={true}
content={JSON.stringify($journals_sess, null, 2)}
show_line_numbers={false}
placeholder=""
class="
p-1
preset-outlined-surface-100-900
rounded-lg
"
theme_mode={$ae_loc.theme_mode}
class="rounded-lg border border-surface-500/30"
/>
<!-- <pre class="text-wrap">
{JSON.stringify($journals_sess, null, 2)}
</pre> -->
</div>
</div>
{/if}
</div>
{#snippet footer()}
<button class="btn btn-sm btn-outline btn-primary" onclick={() => (show = false)}>
<X class="inline-block mr-1" />
Close
<button class="btn variant-filled-primary font-bold shadow-lg min-w-[120px]" onclick={() => (show = false)}>
<Check size="1.2em" class="mr-2" />
Done
</button>
{/snippet}
</Modal>
</Modal>