From 0db68da00c4da5c2c357abb9ec2cf2e9011db2ea Mon Sep 17 00:00:00 2001 From: Marcel Date: Thu, 26 Mar 2026 12:32:01 +0100 Subject: [PATCH] refactor(persons): extract PersonCard, PersonMergePanel, CoCorrespondentsList, PersonDocumentList Split the 610-line person detail page into four focused co-located components: - PersonCard: view/edit card with inline form (owns editMode) - PersonMergePanel: merge target typeahead + two-step confirm (state reset via {#key}) - CoCorrespondentsList: frequency-ranked correspondent chips linking to conversations - PersonDocumentList: reusable sorted/paginated document list (used for sent + received) Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/routes/persons/[id]/+page.svelte | 555 +----------------- .../persons/[id]/CoCorrespondentsList.svelte | 30 + .../src/routes/persons/[id]/PersonCard.svelte | 246 ++++++++ .../persons/[id]/PersonDocumentList.svelte | 132 +++++ .../persons/[id]/PersonMergePanel.svelte | 83 +++ 5 files changed, 508 insertions(+), 538 deletions(-) create mode 100644 frontend/src/routes/persons/[id]/CoCorrespondentsList.svelte create mode 100644 frontend/src/routes/persons/[id]/PersonCard.svelte create mode 100644 frontend/src/routes/persons/[id]/PersonDocumentList.svelte create mode 100644 frontend/src/routes/persons/[id]/PersonMergePanel.svelte diff --git a/frontend/src/routes/persons/[id]/+page.svelte b/frontend/src/routes/persons/[id]/+page.svelte index 5566055c..a37e87da 100644 --- a/frontend/src/routes/persons/[id]/+page.svelte +++ b/frontend/src/routes/persons/[id]/+page.svelte @@ -1,10 +1,10 @@
@@ -110,500 +64,25 @@ $effect(() => {
- -
-
+ -
- {#if editMode && data.canWrite} - -
-
-

- {m.person_edit_heading()} -

- - {#if form?.updateError} -

- {form.updateError} -

- {/if} - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- -
- - -
-
-
- {:else} - -
-
-
- {person.firstName[0]}{person.lastName[0]} -
-
- -
-
-

- {person.firstName} - {person.lastName} -

-
- {#if data.canWrite} - - {/if} -
-
- -
-
- {m.person_label_full_name()} - {person.firstName} {person.lastName} -
- - {#if person.alias} -
- {m.form_label_alias()} - "{person.alias}" -
- {/if} - - {#if person.birthYear || person.deathYear} -
- - {#if person.birthYear && person.deathYear}{m.person_label_birth_year()} / {m.person_label_death_year()}{:else if person.birthYear}{m.person_label_birth_year()}{:else}{m.person_label_death_year()}{/if} - - - {#if person.birthYear}* {person.birthYear}{/if}{#if person.birthYear && person.deathYear} -  {/if}{#if person.deathYear}† {person.deathYear}{/if} - -
- {/if} - - {#if person.notes} -
- {m.person_label_notes()} -

- {person.notes} -

-
- {/if} -
-
-
- {/if} -
-
- - {#if data.canWrite} {#key person.id} -
-
-

{m.person_merge_heading()}

-

- {m.person_merge_description()} -

- - {#if form?.mergeError} -

- {form.mergeError} -

- {/if} - -
- - -
-
- { mergeTargetId = value; showMergeConfirm = false; }} - /> -
- - {#if !showMergeConfirm} - - {:else} -
- - -
- {/if} -
- - {#if showMergeConfirm} -

- {m.person_merge_warning()} {person.firstName} {person.lastName} - {m.person_merge_will_be_deleted()} -

- {/if} -
-
-
+ {/key} {/if} - - {#if coCorrespondents.length > 0} -
-

- {m.person_co_correspondents_heading()} -

-
- {#each coCorrespondents as c (c.id)} - - {c.name} - ({c.count}) - - {/each} -
-
- {/if} + - -
-
-

{m.person_docs_heading()}

- - {sentDocuments.length} - - {#if sentYearRange} - {sentYearRange} - {/if} - {#if sentDocuments.length > 1} - - {/if} -
+ - {#if sentDocuments.length === 0} -
-

{m.person_no_docs()}

-
- {:else} - - {#if sentDocuments.length > DOCS_PREVIEW_LIMIT && !showAllSent} - - {/if} - {/if} -
- - -
-
-

{m.person_received_docs_heading()}

- - {receivedDocuments.length} - - {#if receivedYearRange} - {receivedYearRange} - {/if} - {#if receivedDocuments.length > 1} - - {/if} -
- - {#if receivedDocuments.length === 0} -
-

{m.person_no_received_docs()}

-
- {:else} - - {#if receivedDocuments.length > DOCS_PREVIEW_LIMIT && !showAllReceived} - - {/if} - {/if} -
+ diff --git a/frontend/src/routes/persons/[id]/CoCorrespondentsList.svelte b/frontend/src/routes/persons/[id]/CoCorrespondentsList.svelte new file mode 100644 index 00000000..5b0409eb --- /dev/null +++ b/frontend/src/routes/persons/[id]/CoCorrespondentsList.svelte @@ -0,0 +1,30 @@ + + +{#if coCorrespondents.length > 0} +
+

+ {m.person_co_correspondents_heading()} +

+
+ {#each coCorrespondents as c (c.id)} + + {c.name} + ({c.count}) + + {/each} +
+
+{/if} diff --git a/frontend/src/routes/persons/[id]/PersonCard.svelte b/frontend/src/routes/persons/[id]/PersonCard.svelte new file mode 100644 index 00000000..c5e2e9e0 --- /dev/null +++ b/frontend/src/routes/persons/[id]/PersonCard.svelte @@ -0,0 +1,246 @@ + + +
+
+ +
+ {#if editMode && canWrite} + +
+
+

+ {m.person_edit_heading()} +

+ + {#if form?.updateError} +

+ {form.updateError} +

+ {/if} + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+
+
+ {:else} + +
+
+
+ {person.firstName[0]}{person.lastName[0]} +
+
+ +
+
+

+ {person.firstName} + {person.lastName} +

+
+ {#if canWrite} + + {/if} +
+
+ +
+
+ {m.person_label_full_name()} + {person.firstName} {person.lastName} +
+ + {#if person.alias} +
+ {m.form_label_alias()} + "{person.alias}" +
+ {/if} + + {#if person.birthYear || person.deathYear} +
+ + {#if person.birthYear && person.deathYear}{m.person_label_birth_year()} / {m.person_label_death_year()}{:else if person.birthYear}{m.person_label_birth_year()}{:else}{m.person_label_death_year()}{/if} + + + {#if person.birthYear}* {person.birthYear}{/if}{#if person.birthYear && person.deathYear} +  {/if}{#if person.deathYear}† {person.deathYear}{/if} + +
+ {/if} + + {#if person.notes} +
+ {m.person_label_notes()} +

+ {person.notes} +

+
+ {/if} +
+
+
+ {/if} +
+
diff --git a/frontend/src/routes/persons/[id]/PersonDocumentList.svelte b/frontend/src/routes/persons/[id]/PersonDocumentList.svelte new file mode 100644 index 00000000..97e6a7e1 --- /dev/null +++ b/frontend/src/routes/persons/[id]/PersonDocumentList.svelte @@ -0,0 +1,132 @@ + + +
+
+

{heading}

+ + {documents.length} + + {#if yearRange} + {yearRange} + {/if} + {#if documents.length > 1} + + {/if} +
+ + {#if documents.length === 0} +
+

{emptyMessage}

+
+ {:else} + + {#if documents.length > DOCS_PREVIEW_LIMIT && !showAll} + + {/if} + {/if} +
diff --git a/frontend/src/routes/persons/[id]/PersonMergePanel.svelte b/frontend/src/routes/persons/[id]/PersonMergePanel.svelte new file mode 100644 index 00000000..0a771b0e --- /dev/null +++ b/frontend/src/routes/persons/[id]/PersonMergePanel.svelte @@ -0,0 +1,83 @@ + + +
+
+

{m.person_merge_heading()}

+

+ {m.person_merge_description()} +

+ + {#if form?.mergeError} +

+ {form.mergeError} +

+ {/if} + +
+ + +
+
+ { + mergeTargetId = value; + showMergeConfirm = false; + }} + /> +
+ + {#if !showMergeConfirm} + + {:else} +
+ + +
+ {/if} +
+ + {#if showMergeConfirm} +

+ {m.person_merge_warning()} {person.firstName} {person.lastName} + {m.person_merge_will_be_deleted()} +

+ {/if} +
+
+