feat(journals): redesign list + entry views with glow, dark mode, compact mobile-first layout

- ae_comp__journal_obj_li: compact tap-target rows, glow wrapper, plain gray dark mode (no Skeleton paired utils)
- +page.svelte (journals index): fix 'Managed by Account Name Not Set' bug, responsive spacing, glow on quick-add
- ae_comp__journal_obj_id_view: glow wrapper, explicit bg-white/dark:bg-gray-900, remove broken dynamic color class
- ae_comp__journal_entry_obj_li: glow wrapper, left-accent border on cards, fix dark mode hover
- ae_comp__journal_entry_obj_id_view: glow wrapper, consistent gray dark mode, edit-mode ring indicator
- ae_comp__journal_entry_header: replace Skeleton surface vars with plain grays (dark mode fix)
- e_app_theme: fix theme selector panel readability in dark mode
This commit is contained in:
Scott Idem
2026-03-13 19:48:23 -04:00
parent ea87befc0d
commit 9b8bc7cb73
7 changed files with 185 additions and 175 deletions

View File

@@ -22,142 +22,118 @@
let { lq__journal_obj_li }: Props = $props();
</script>
<!-- Responsive Grid Container -->
<section
class="journal_list grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 w-full max-w-7xl px-4"
>
{#if $lq__journal_obj_li && $lq__journal_obj_li.length}
{#each $lq__journal_obj_li as journal, index (journal.journal_id)}
<div
class="
journal_card
group relative
flex flex-col justify-between
bg-surface-50 dark:bg-surface-900
border border-surface-500/20 rounded-xl
p-5 shadow-sm hover:shadow-xl hover:border-primary-500/50
transition-all duration-200 ease-in-out
"
class:hidden={(journal?.hide || !journal?.enable) &&
!$ae_loc.trusted_access}
class:opacity-60={journal.hide}
class:border-warning-500={!journal?.enable}
>
<!-- Top Section: Title & Badge -->
<div class="space-y-3">
<header class="flex justify-between items-start gap-2">
<div class="flex items-center gap-3">
<div
class="p-2 bg-primary-500/10 rounded-lg text-primary-500 group-hover:bg-primary-500 group-hover:text-white transition-colors"
>
<BookType size="1.5em" />
</div>
<h3
class="text-xl font-bold text-surface-900 dark:text-surface-100 line-clamp-1"
>
{journal.name}
</h3>
</div>
<!--
Compact mobile-first list — the entire row is the tap target.
Glow effect mirrors the Quick Add section above it.
Uses plain Tailwind gray scale with explicit dark: variants — no Skeleton paired utilities —
so behavior is predictable regardless of which Skeleton theme is active.
-->
<div class="w-full max-w-2xl relative group/list">
<!-- Glow ring behind the list, same technique as Quick Add -->
<div
class="absolute -inset-1 bg-linear-to-r from-primary-500 to-secondary-500
rounded-2xl blur opacity-10 dark:opacity-20
group-hover/list:opacity-25 dark:group-hover/list:opacity-35
transition duration-700 pointer-events-none"
></div>
{#if journal.type_code}
<span
class="badge preset-tonal-warning text-[10px] uppercase tracking-wider font-bold"
>
{journal.type_code}
</span>
{/if}
</header>
<!-- Description (Power User / Edit Mode Only) -->
{#if journal.description && $ae_loc.edit_mode}
<div
class="prose prose-sm dark:prose-invert max-h-24 overflow-y-auto bg-surface-100/50 dark:bg-surface-800/50 p-3 rounded-lg text-xs font-mono"
>
{@html journal.description_md_html}
</div>
{/if}
<!-- Quick Stats (Clean View) -->
<div
class="flex items-center gap-4 text-xs text-surface-600 dark:text-surface-400"
>
<div
class="flex items-center gap-1"
title="Entry Count"
>
<Hash size="1.2em" />
<span class="font-bold"
>{journal.journal_entry_count ?? 0}</span
>
</div>
<div
class="flex items-center gap-1"
title="Last Updated"
>
<Clock size="1.2em" />
<span
>{ae_util.iso_datetime_formatter(
journal.updated_on || journal.created_on,
'date_short'
)}</span
>
</div>
</div>
</div>
<!-- Bottom Section: Actions -->
<div
class="mt-6 pt-4 border-t border-surface-500/10 flex flex-col gap-3"
<section class="journal_list relative w-full space-y-1.5 p-2 sm:p-3
bg-white dark:bg-gray-900
border border-gray-200 dark:border-gray-700
rounded-2xl shadow-xl">
{#if $lq__journal_obj_li && $lq__journal_obj_li.length}
{#each $lq__journal_obj_li as journal (journal.journal_id)}
<a
href="/journals/{journal?.journal_id}"
class="journal_card group relative
flex items-center gap-3 px-4 py-3
bg-gray-50 dark:bg-gray-800
border border-gray-200 dark:border-gray-700
border-l-4 border-l-primary-500/60
rounded-xl shadow-sm
hover:shadow-md hover:border-l-primary-500
hover:bg-gray-100 dark:hover:bg-gray-700
active:scale-[0.99]
transition-all duration-150 ease-in-out"
class:hidden={(journal?.hide || !journal?.enable) && !$ae_loc.trusted_access}
class:opacity-60={journal.hide}
class:!border-l-warning-500={!journal?.enable}
>
<a
href="/journals/{journal?.journal_id}"
class="btn preset-filled-primary w-full font-bold shadow-md hover:scale-[1.02] active:scale-95 transition-all"
>
<BookOpenText size="1.2em" class="mr-2" />
<span>Open Journal</span>
</a>
<!-- Icon: fixed size, never squashed -->
<div class="shrink-0 p-2 bg-primary-500/10 rounded-lg text-primary-500
group-hover:bg-primary-500 group-hover:text-white transition-colors">
<BookType size="1.3em" />
</div>
<!-- Admin Metadata (Edit Mode Only) -->
{#if $ae_loc.edit_mode && $ae_loc.administrator_access}
<div
class="flex items-center justify-center gap-2 text-[10px] opacity-50 font-mono"
>
<Calendar size="1em" />
<span
>Created: {ae_util.iso_datetime_formatter(
journal.created_on,
'datetime_iso_12_no_seconds'
)}</span
>
<!-- Name + badge: min-w-0 flex-1 lets text shrink and wrap -->
<div class="min-w-0 flex-1">
<div class="text-sm sm:text-base font-bold
text-gray-900 dark:text-gray-100
leading-snug break-words">
{journal.name}
</div>
{/if}
</div>
<div class="flex flex-wrap items-center gap-2 mt-0.5">
{#if journal.type_code}
<span class="badge preset-tonal-warning text-[10px] uppercase tracking-wider font-bold">
{journal.type_code}
</span>
{/if}
<!-- Description snippet: edit mode only -->
{#if journal.description && $ae_loc.edit_mode}
<span class="text-[11px] text-gray-500 dark:text-gray-400 font-mono truncate max-w-[16rem]">
{ae_util.strip_html ? ae_util.strip_html(journal.description).slice(0, 60) : journal.description.slice(0, 60)}&hellip;
</span>
{/if}
</div>
</div>
<!-- Status Indicators (Edit Mode Only) -->
{#if $ae_loc.edit_mode}
<div class="absolute -top-2 -right-2 flex gap-1">
{#if journal.hide}
<span
class="badge-icon preset-tonal-surface shadow-sm"
title="Hidden">🚫</span
>
{/if}
{#if !journal.enable}
<span
class="badge-icon preset-tonal-warning shadow-sm"
title="Disabled">⚠️</span
>
<!-- Stats: right-aligned, compact -->
<div class="shrink-0 flex flex-col items-end gap-0.5
text-xs text-gray-500 dark:text-gray-400">
<div class="flex items-center gap-1" title="Entry Count">
<Hash size="0.85em" />
<span class="font-bold tabular-nums">{journal.journal_entry_count ?? 0}&times;</span>
</div>
<div class="flex items-center gap-1" title="Last Updated">
<Clock size="0.85em" />
<span class="tabular-nums">{ae_util.iso_datetime_formatter(
journal.updated_on || journal.created_on,
'date_short'
)}</span>
</div>
{#if $ae_loc.edit_mode && $ae_loc.administrator_access}
<div class="flex items-center gap-1 opacity-40" title="Created">
<Calendar size="0.85em" />
<span class="font-mono text-[10px] tabular-nums">{ae_util.iso_datetime_formatter(
journal.created_on,
'date_short'
)}</span>
</div>
{/if}
</div>
{/if}
<!-- Chevron hint: desktop only -->
<BookOpenText size="0.95em"
class="shrink-0 opacity-0 group-hover:opacity-30 transition-opacity hidden sm:block" />
<!-- Status overlays: edit mode only -->
{#if $ae_loc.edit_mode}
<div class="absolute -top-1.5 -right-1.5 flex gap-1">
{#if journal.hide}
<span class="badge-icon preset-tonal-surface shadow-sm" title="Hidden">🚫</span>
{/if}
{#if !journal.enable}
<span class="badge-icon preset-tonal-warning shadow-sm" title="Disabled">⚠️</span>
{/if}
</div>
{/if}
</a>
{/each}
{:else}
<div class="p-20 text-center text-gray-400 dark:text-gray-500 flex flex-col items-center gap-4">
<BookType size="4em" />
<p class="text-xl">No journals found in this view.</p>
</div>
{/each}
{:else}
<div
class="col-span-full p-20 text-center opacity-50 flex flex-col items-center gap-4"
>
<BookType size="4em" />
<p class="text-xl">No journals found in this view.</p>
</div>
{/if}
</section>
{/if}
</section>
</div>