Build tree couples
This commit is contained in:
		| @@ -1,5 +1,6 @@ | ||||
| import { APIClient } from "./ApiClient"; | ||||
| import { DateValue, Member } from "./MemberApi"; | ||||
| import { ServerApi } from "./ServerApi"; | ||||
|  | ||||
| interface CoupleApiInterface { | ||||
|   id: number; | ||||
| @@ -99,6 +100,10 @@ export class Couple implements CoupleApiInterface { | ||||
|       day: this.divorce_day, | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   otherPersonID(id: number): number | undefined { | ||||
|     return id === this.wife ? this.husband : this.wife; | ||||
|   } | ||||
| } | ||||
|  | ||||
| export class CouplesList { | ||||
| @@ -137,6 +142,10 @@ export class CouplesList { | ||||
|   getAllOf(m: Member): Couple[] { | ||||
|     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 { | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| import { useParams } from "react-router-dom"; | ||||
| import { useFamily } from "../../widgets/BaseFamilyRoute"; | ||||
| import ClearIcon from "@mui/icons-material/Clear"; | ||||
| import { | ||||
|   Alert, | ||||
|   FormControl, | ||||
| @@ -12,10 +11,15 @@ import { | ||||
|   Tab, | ||||
|   Tabs, | ||||
| } 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 { 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 { | ||||
|   BasicTree, | ||||
| @@ -37,6 +41,16 @@ export function FamilyMemberTreeRoute(): React.ReactElement { | ||||
|  | ||||
|   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) { | ||||
|     return ( | ||||
|       <Alert severity="error"> | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { useNavigate } from "react-router-dom"; | ||||
| import { MemberInput } from "../../widgets/forms/MemberInput"; | ||||
| import { useFamily } from "../../widgets/BaseFamilyRoute"; | ||||
| import { MemberInput } from "../../widgets/forms/MemberInput"; | ||||
|  | ||||
| export function FamilyTreeRoute(): React.ReactElement { | ||||
|   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, | ||||
|   }; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user