Build tree couples
This commit is contained in:
parent
c414defb19
commit
4d5bdaad57
@ -1,5 +1,6 @@
|
|||||||
import { APIClient } from "./ApiClient";
|
import { APIClient } from "./ApiClient";
|
||||||
import { DateValue, Member } from "./MemberApi";
|
import { DateValue, Member } from "./MemberApi";
|
||||||
|
import { ServerApi } from "./ServerApi";
|
||||||
|
|
||||||
interface CoupleApiInterface {
|
interface CoupleApiInterface {
|
||||||
id: number;
|
id: number;
|
||||||
@ -99,6 +100,10 @@ export class Couple implements CoupleApiInterface {
|
|||||||
day: this.divorce_day,
|
day: this.divorce_day,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
otherPersonID(id: number): number | undefined {
|
||||||
|
return id === this.wife ? this.husband : this.wife;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CouplesList {
|
export class CouplesList {
|
||||||
@ -137,6 +142,10 @@ export class CouplesList {
|
|||||||
getAllOf(m: Member): Couple[] {
|
getAllOf(m: Member): Couple[] {
|
||||||
return this.filter((c) => c.husband === m.id || c.wife === m.id);
|
return this.filter((c) => c.husband === m.id || c.wife === m.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFirstMariedOf(m: Member): Couple | undefined {
|
||||||
|
return this.getAllOf(m).find((c) => (c.state = "M"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CoupleApi {
|
export class CoupleApi {
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { useParams } from "react-router-dom";
|
import ClearIcon from "@mui/icons-material/Clear";
|
||||||
import { useFamily } from "../../widgets/BaseFamilyRoute";
|
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
FormControl,
|
FormControl,
|
||||||
@ -12,10 +11,15 @@ import {
|
|||||||
Tab,
|
Tab,
|
||||||
Tabs,
|
Tabs,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { MemberItem } from "../../widgets/MemberItem";
|
|
||||||
import ClearIcon from "@mui/icons-material/Clear";
|
|
||||||
import { RouterLink } from "../../widgets/RouterLink";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import {
|
||||||
|
buildAscendingTree,
|
||||||
|
buildDescendingTree,
|
||||||
|
} from "../../utils/family_tree";
|
||||||
|
import { useFamily } from "../../widgets/BaseFamilyRoute";
|
||||||
|
import { MemberItem } from "../../widgets/MemberItem";
|
||||||
|
import { RouterLink } from "../../widgets/RouterLink";
|
||||||
|
|
||||||
enum CurrTab {
|
enum CurrTab {
|
||||||
BasicTree,
|
BasicTree,
|
||||||
@ -37,6 +41,16 @@ export function FamilyMemberTreeRoute(): React.ReactElement {
|
|||||||
|
|
||||||
const member = family.members.get(Number(memberId));
|
const member = family.members.get(Number(memberId));
|
||||||
|
|
||||||
|
const tree = React.useMemo(
|
||||||
|
() =>
|
||||||
|
!member
|
||||||
|
? null
|
||||||
|
: currMode === TreeMode.Ascending
|
||||||
|
? buildAscendingTree(member.id, family.members, family.couples)
|
||||||
|
: buildDescendingTree(member.id, family.members, family.couples),
|
||||||
|
[member, currMode, family.members, family.couples]
|
||||||
|
);
|
||||||
|
|
||||||
if (!member) {
|
if (!member) {
|
||||||
return (
|
return (
|
||||||
<Alert severity="error">
|
<Alert severity="error">
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { MemberInput } from "../../widgets/forms/MemberInput";
|
|
||||||
import { useFamily } from "../../widgets/BaseFamilyRoute";
|
import { useFamily } from "../../widgets/BaseFamilyRoute";
|
||||||
|
import { MemberInput } from "../../widgets/forms/MemberInput";
|
||||||
|
|
||||||
export function FamilyTreeRoute(): React.ReactElement {
|
export function FamilyTreeRoute(): React.ReactElement {
|
||||||
const n = useNavigate();
|
const n = useNavigate();
|
||||||
|
79
geneit_app/src/utils/family_tree.ts
Normal file
79
geneit_app/src/utils/family_tree.ts
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import { Couple, CouplesList } from "../api/CoupleApi";
|
||||||
|
import { Member, MembersList } from "../api/MemberApi";
|
||||||
|
|
||||||
|
export interface CoupleInformation {
|
||||||
|
couple: Couple;
|
||||||
|
member: Member;
|
||||||
|
down: FamilyTreeNode[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FamilyTreeNode {
|
||||||
|
down?: FamilyTreeNode[];
|
||||||
|
member: Member;
|
||||||
|
couples?: CoupleInformation[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildAscendingTree(
|
||||||
|
memberId: number,
|
||||||
|
members: MembersList,
|
||||||
|
couples: CouplesList
|
||||||
|
): FamilyTreeNode {
|
||||||
|
const member = members.get(memberId)!;
|
||||||
|
|
||||||
|
const parents = [];
|
||||||
|
if (member.father)
|
||||||
|
parents.push(buildAscendingTree(member.father, members, couples));
|
||||||
|
|
||||||
|
if (member.mother)
|
||||||
|
parents.push(buildAscendingTree(member.mother, members, couples));
|
||||||
|
|
||||||
|
return {
|
||||||
|
member: member,
|
||||||
|
down: parents,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildDescendingTree(
|
||||||
|
memberId: number,
|
||||||
|
members: MembersList,
|
||||||
|
couples: CouplesList
|
||||||
|
): FamilyTreeNode {
|
||||||
|
const member = members.get(memberId)!;
|
||||||
|
|
||||||
|
const children = members.children(member.id);
|
||||||
|
|
||||||
|
// Process user couples
|
||||||
|
const member_couples: CoupleInformation[] = [];
|
||||||
|
for (const c of couples.getAllOf(member)) {
|
||||||
|
// Currently, couples with missing pair information are not supported
|
||||||
|
const pairId = c.otherPersonID(member.id);
|
||||||
|
if (!pairId) continue;
|
||||||
|
const pair = members.get(pairId);
|
||||||
|
|
||||||
|
const c_children: Member[] = [];
|
||||||
|
|
||||||
|
// Determine children associated with each couple
|
||||||
|
for (let index = 0; index < children.length; ) {
|
||||||
|
const c = children[index];
|
||||||
|
if (c.mother !== pairId && c.father !== pairId) {
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
children.splice(index, 1);
|
||||||
|
c_children.push(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
member_couples.push({
|
||||||
|
couple: c,
|
||||||
|
member: pair!,
|
||||||
|
down: c_children.map((c) => buildDescendingTree(c.id, members, couples)),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
member: member,
|
||||||
|
down: children.map((c) => buildDescendingTree(c.id, members, couples)),
|
||||||
|
couples: member_couples,
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user