feat(stammbaum): family network — graph, badge, edit card, /stammbaum page (#358) #360

Merged
marcel merged 57 commits from feat/stammbaum-issue-358 into main 2026-04-28 19:33:33 +02:00
2 changed files with 60 additions and 1 deletions
Showing only changes of commit 48a704f002 - Show all commits

View File

@@ -14,7 +14,10 @@ interface Props {
let { personId, relationships, inferredRelationships }: Props = $props();
const topDerived = $derived(inferredRelationships.slice(0, 5));
const directOtherIds = $derived(new Set(relationships.map((rel) => otherId(rel))));
const topDerived = $derived(
inferredRelationships.filter((d) => !directOtherIds.has(d.person.id)).slice(0, 5)
);
function chipLabel(rel: RelationshipDTO): string {
const viewpointIsSubject = rel.personId === personId;

View File

@@ -0,0 +1,56 @@
import { describe, it, expect } from 'vitest';
import { render } from 'vitest-browser-svelte';
import { page } from 'vitest/browser';
import PersonRelationshipsCard from './PersonRelationshipsCard.svelte';
const PERSON_ID = '00000000-0000-0000-0000-000000000001';
const SPOUSE_ID = '00000000-0000-0000-0000-000000000002';
describe('PersonRelationshipsCard', () => {
it('hides an inferred relationship that is already a direct one', async () => {
render(PersonRelationshipsCard, {
personId: PERSON_ID,
relationships: [
{
id: 'r1',
personId: PERSON_ID,
relatedPersonId: SPOUSE_ID,
personDisplayName: 'Anna Müller',
relatedPersonDisplayName: 'Bertha Müller',
relationType: 'SPOUSE_OF'
}
],
inferredRelationships: [
{
person: {
id: SPOUSE_ID,
displayName: 'Bertha Müller',
familyMember: true
},
label: 'SPOUSE',
hops: 1
}
]
});
const matches = await page.getByText('Bertha Müller').all();
expect(matches).toHaveLength(1);
});
it('still renders inferred relationships that are not direct', async () => {
const COUSIN_ID = '00000000-0000-0000-0000-000000000003';
render(PersonRelationshipsCard, {
personId: PERSON_ID,
relationships: [],
inferredRelationships: [
{
person: { id: COUSIN_ID, displayName: 'Carla Cousine', familyMember: true },
label: 'COUSIN',
hops: 4
}
]
});
await expect.element(page.getByText('Carla Cousine')).toBeInTheDocument();
});
});