import React from "react"; import f3, { f3Data } from "family-chart"; import "./family-chart.css"; import { FamilyTreeNode } from "../../utils/family_tree"; import { fmtDate } from "../../api/MemberApi"; export function ComplexFamilyTree(p: { tree: FamilyTreeNode; }): React.ReactElement { const refCb = (container: HTMLDivElement) => { if (!container) return; const store = f3.createStore({ data: treeToF3Data(p.tree), node_separation: 250, level_separation: 150, }), view = f3.d3AnimationView({ store, cont: document.querySelector("#FamilyChart"), }), Card = f3.elements.Card({ store, svg: view.svg, card_dim: { w: 220, h: 70, text_x: 75, text_y: 15, img_w: 60, img_h: 60, img_x: 5, img_y: 5, }, card_display: [ (d) => `${d.data.first_name || ""} ${d.data.last_name || ""}`, (d) => `${d.data["birthday"] || ""}`, ], mini_tree: true, link_break: false, }); view.setCard(Card); store.setOnUpdate((props) => view.update(props || {})); store.update.tree({ initial: true }); }; return
; } function treeToF3Data(node: FamilyTreeNode): f3Data[] { const availableMembers = new Set(); getAvailableMembers(node, availableMembers); const list: f3Data[] = []; treeToF3DataRecurse(node, list, availableMembers); console.info(list); return list; } function getAvailableMembers(t: FamilyTreeNode, s: Set) { s.add(t.member.id); t.couples?.forEach((c) => { s.add(c.member.id); c.down.forEach((e) => getAvailableMembers(e, s)); }); t.down?.forEach((e) => getAvailableMembers(e, s)); } function treeToF3DataRecurse( node: FamilyTreeNode, array: f3Data[], availableMembers: Set ) { // Get all members ids const children = node?.down?.map((c) => c.member.id.toString()) ?? []; node.couples?.map((c) => c.down.forEach((m) => children.push(m.member.id.toString())) ); array.push({ data: { first_name: node.member.first_name ?? "_", last_name: node.member.last_name ?? "_", gender: node.member.sex ?? "M", avatar: node.member.thumbnailURL ?? undefined, birthday: node.member.dateOfBirth ? fmtDate(node.member.dateOfBirth) : undefined, }, id: node.member.id.toString(), rels: { father: node.member.father && availableMembers.has(node.member.father) ? node.member.father.toString() : undefined, mother: node.member.mother && availableMembers.has(node.member.mother) ? node.member.mother.toString() : undefined, spouses: node.couples?.map((c) => c.member.id.toString()), children: children, }, }); node?.down?.forEach((e) => treeToF3DataRecurse(e, array, availableMembers)); if (node.couples) { for (const c of node.couples) { array.push({ data: { first_name: c.member.first_name ?? "_", last_name: c.member.last_name ?? "_", gender: c.member.sex ?? "M", avatar: c.member.thumbnailURL ?? undefined, birthday: c.member.dateOfBirth ? fmtDate(c.member.dateOfBirth) : undefined, }, id: c.member.id.toString(), rels: { father: c.member.father && availableMembers.has(c.member.father) ? c.member.father.toString() : undefined, mother: c.member.mother && availableMembers.has(c.member.mother) ? c.member.mother.toString() : undefined, spouses: [node.member.id.toString()], children: c.down.map((c) => c.member.id.toString()), }, }); c.down.forEach((e) => treeToF3DataRecurse(e, array, availableMembers)); } } } /* import { jsPDF } from "jspdf"; import "svg2pdf.js"; setTimeout(() => { const doc = new jsPDF({ orientation: "l", format: [1000, 1000], }); const element = document.getElementById("FamilyChart"); console.log(element); doc.svg(element!.children[0], { height: 1000, width: 1000 }).then(() => { // save the created pdf //doc.save("myPDF.pdf"); }); }, 6000);*/