Moves ~25 components, utils (search, filename, groupDocuments, documentStatusLabel, validateFile), bulkSelection store, and TranscriptionSection sub-component. Fixes broken relative imports. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
149 lines
4.7 KiB
Svelte
149 lines
4.7 KiB
Svelte
<script lang="ts">
|
|
import { onMount } from 'svelte';
|
|
import TagInput, { type Tag } from '$lib/components/TagInput.svelte';
|
|
import FieldLabelBadge from './FieldLabelBadge.svelte';
|
|
import { m } from '$lib/paraglide/messages.js';
|
|
|
|
let {
|
|
tags = $bindable<Tag[]>([]),
|
|
currentTitle = $bindable(''),
|
|
documentLocation = $bindable(''),
|
|
archiveBox = $bindable(''),
|
|
archiveFolder = $bindable(''),
|
|
initialTitle = '',
|
|
initialArchiveBox = '',
|
|
initialArchiveFolder = '',
|
|
initialSummary = '',
|
|
titleRequired = false,
|
|
suggestedTitle = '',
|
|
hideTitle = false,
|
|
editMode = false
|
|
}: {
|
|
tags?: Tag[];
|
|
currentTitle?: string;
|
|
documentLocation?: string;
|
|
archiveBox?: string;
|
|
archiveFolder?: string;
|
|
initialTitle?: string;
|
|
initialArchiveBox?: string;
|
|
initialArchiveFolder?: string;
|
|
initialSummary?: string;
|
|
titleRequired?: boolean;
|
|
suggestedTitle?: string;
|
|
hideTitle?: boolean;
|
|
editMode?: boolean;
|
|
} = $props();
|
|
|
|
// Seed bindables from initial-* props once at mount and only when the parent
|
|
// hasn't already supplied a non-empty value through the binding. onMount runs
|
|
// exactly once per instance, so this never stomps a parent-driven update on a
|
|
// later prop change. Required by the single-doc edit flow which seeds from
|
|
// the document; bulk-edit consumers leave the initial-* unset and bind their
|
|
// own state.
|
|
let titleDirty = $state(false);
|
|
onMount(() => {
|
|
if (!currentTitle && initialTitle) currentTitle = initialTitle;
|
|
if (!archiveBox && initialArchiveBox) archiveBox = initialArchiveBox;
|
|
if (!archiveFolder && initialArchiveFolder) archiveFolder = initialArchiveFolder;
|
|
});
|
|
const titleValue = $derived(titleDirty ? currentTitle : suggestedTitle || currentTitle);
|
|
</script>
|
|
|
|
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
|
|
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
|
|
{m.doc_section_description()}
|
|
</h2>
|
|
|
|
<div class="space-y-5">
|
|
{#if !hideTitle}
|
|
<!-- Titel (required) -->
|
|
<div>
|
|
<label for="title" class="mb-1 block text-sm font-medium text-ink-2"
|
|
>{m.form_label_title()}{#if titleRequired}
|
|
*{/if}</label
|
|
>
|
|
<input
|
|
id="title"
|
|
type="text"
|
|
name="title"
|
|
value={titleValue}
|
|
oninput={(e) => {
|
|
currentTitle = (e.target as HTMLInputElement).value;
|
|
titleDirty = true;
|
|
}}
|
|
required={titleRequired}
|
|
class="block w-full rounded border border-line p-2 text-sm shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
|
|
/>
|
|
</div>
|
|
{/if}
|
|
|
|
<!-- Optional divider -->
|
|
<div class="my-3 flex items-center gap-2">
|
|
<div class="flex-1 border-t border-line"></div>
|
|
<span class="text-xs font-bold tracking-widest text-ink-3 uppercase"
|
|
>{m.label_optional()}</span
|
|
>
|
|
<div class="flex-1 border-t border-line"></div>
|
|
</div>
|
|
|
|
<!-- Schlagworte (optional) -->
|
|
<div>
|
|
<p class="mb-1 block text-sm font-medium text-ink-2">
|
|
{m.form_label_tags()}
|
|
{#if editMode}<FieldLabelBadge variant="additive" />{/if}
|
|
</p>
|
|
<TagInput bind:tags={tags} />
|
|
<input type="hidden" name="tags" value={tags.map((t) => t.name).join(',')} />
|
|
</div>
|
|
|
|
{#if !editMode}
|
|
<!-- Inhalt (optional) — not bulk-editable. -->
|
|
<div>
|
|
<label for="summary" class="mb-1 block text-sm font-medium text-ink-2"
|
|
>{m.form_label_content()}</label
|
|
>
|
|
<textarea
|
|
id="summary"
|
|
name="summary"
|
|
rows="5"
|
|
placeholder={m.form_placeholder_content()}
|
|
class="block w-full rounded border border-line p-2 font-serif text-sm shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
|
|
>{initialSummary}</textarea
|
|
>
|
|
</div>
|
|
{/if}
|
|
|
|
<!-- Karton -->
|
|
<div data-testid="description-archive-box">
|
|
<label for="archiveBox" class="mb-1 block text-sm font-medium text-ink-2">
|
|
{m.form_label_archive_box()}
|
|
{#if editMode}<FieldLabelBadge variant="replace" />{/if}
|
|
</label>
|
|
<input
|
|
id="archiveBox"
|
|
type="text"
|
|
name="archiveBox"
|
|
bind:value={archiveBox}
|
|
class="block w-full rounded border border-line p-2 text-sm shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
|
|
/>
|
|
<p class="mt-1 text-xs text-ink-3">{m.form_helper_archive_box()}</p>
|
|
</div>
|
|
|
|
<!-- Mappe -->
|
|
<div data-testid="description-archive-folder">
|
|
<label for="archiveFolder" class="mb-1 block text-sm font-medium text-ink-2">
|
|
{m.form_label_archive_folder()}
|
|
{#if editMode}<FieldLabelBadge variant="replace" />{/if}
|
|
</label>
|
|
<input
|
|
id="archiveFolder"
|
|
type="text"
|
|
name="archiveFolder"
|
|
bind:value={archiveFolder}
|
|
class="block w-full rounded border border-line p-2 text-sm shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
|
|
/>
|
|
<p class="mt-1 text-xs text-ink-3">{m.form_helper_archive_folder()}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|