feat(journals): implement Quick Add and unified Append/Prepend shared component

- Created AeCompJournalEntryQuickAdd for high-velocity note creation
- Extracted robust append/prepend logic from List View into AeCompModalJournalEntryAppend
- Unified List and Detail views to use the shared modal for content manipulation
- Added explicit Append/Prepend actions to Journal Entry settings menu
- Updated TODO.md and Journals module documentation
This commit is contained in:
Scott Idem
2026-01-13 22:59:08 -05:00
parent 80bc5e453a
commit 8fd11d7224
9 changed files with 403 additions and 398 deletions

View File

@@ -0,0 +1,106 @@
<script lang="ts">
import { api } from '$lib/api/api';
import { ae_api } from '$lib/stores/ae_stores';
import { journals_slct, journals_loc, journals_trig } from '$lib/ae_journals/ae_journals_stores';
// Props
let {
class: className = "",
placeholder = "Type your quick note... (First line = Title)"
} = $props();
// State
let note_content = $state("");
let is_submitting = $state(false);
// Derived
// Determine target journal: Selected > Default Preference > First Available?
let target_journal_id = $derived($journals_slct.journal_id || $journals_loc.qry__journal_id);
async function handle_submit() {
if (!note_content.trim()) return;
if (!target_journal_id) {
alert("No journal selected!");
return;
}
is_submitting = true;
const lines = note_content.trim().split('\n');
let name = lines[0].substring(0, 100);
if (lines[0].length > 100) name += "...";
// If content is just one line, name is content, content is content.
// If multiple lines, name is line 0, content is full text.
const payload = {
journal_id: target_journal_id,
name: name,
content: note_content,
type_code: 'note', // Default to note
// created_on: handled by backend usually, or we can send ISO
enabled: true,
hidden: false
};
// Use the store value directly via $ prefix
const api_cfg = $ae_api;
const res = await api.create_ae_obj_v3({
api_cfg: api_cfg,
obj_type: 'journal_entry',
fields: payload
});
if (res) {
note_content = "";
// Trigger refresh
$journals_trig.journal_entry_li = true;
} else {
alert("Failed to create note.");
}
is_submitting = false;
}
function handle_keydown(e: KeyboardEvent) {
if (e.ctrlKey && e.key === 'Enter') {
handle_submit();
}
}
</script>
<div class="card p-4 space-y-4 variant-filled-surface {className}">
<header class="flex justify-between items-center">
<h3 class="h3">Quick Add</h3>
{#if !target_journal_id}
<span class="badge variant-filled-error">No Journal Selected</span>
{/if}
</header>
<textarea
class="textarea"
rows="3"
bind:value={note_content}
{placeholder}
onkeydown={handle_keydown}
disabled={is_submitting}
></textarea>
<div class="flex justify-end space-x-2">
<button
class="btn variant-ghost-surface"
onclick={() => note_content = ""}
disabled={is_submitting || note_content.length === 0}
>
Clear
</button>
<button
class="btn variant-filled-primary"
onclick={handle_submit}
disabled={is_submitting || !target_journal_id || note_content.length === 0}
>
{#if is_submitting}Saving...{:else}Add Note{/if}
</button>
</div>
</div>