112 lines
3.1 KiB
TypeScript
112 lines
3.1 KiB
TypeScript
import { mdiBabyCarriage, mdiCross } from "@mdi/js";
|
|
import Icon from "@mdi/react";
|
|
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
|
import { TreeItem, SimpleTreeView } from "@mui/x-tree-view";
|
|
import React from "react";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { Couple } from "../api/genealogy/CoupleApi";
|
|
import { Member, fmtDate } from "../api/genealogy/MemberApi";
|
|
import { FamilyTreeNode } from "../utils/family_tree";
|
|
import { useFamily } from "./BaseFamilyRoute";
|
|
import { MemberPhoto } from "./MemberPhoto";
|
|
|
|
export function BasicFamilyTree(p: {
|
|
tree: FamilyTreeNode;
|
|
depth: number;
|
|
}): React.ReactElement {
|
|
return (
|
|
<SimpleTreeView
|
|
slots={{ collapseIcon: ExpandMoreIcon, expandIcon: ChevronRightIcon }}
|
|
sx={{ flexGrow: 1 }}
|
|
>
|
|
<FamilyTreeItem n={p.tree} depth={p.depth} />
|
|
</SimpleTreeView>
|
|
);
|
|
}
|
|
|
|
function FamilyTreeItem(p: {
|
|
depth: number;
|
|
n: FamilyTreeNode;
|
|
}): React.ReactElement {
|
|
let children = p.n.down ?? [];
|
|
|
|
if (p.n.couples) {
|
|
for (const c of p.n.couples) {
|
|
children = children.concat(c.down);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<TreeItem
|
|
itemId={p.n.member.id.toString()}
|
|
style={{ margin: "10px" }}
|
|
label={
|
|
<div style={{ display: "flex" }}>
|
|
<BasicFamilyMemberItem member={p.n.member} primary={true} />
|
|
|
|
{p.n.couples?.map((c, n) => (
|
|
<span
|
|
key={n}
|
|
style={{
|
|
marginLeft: "20px",
|
|
}}
|
|
>
|
|
<BasicFamilyMemberItem member={c.member} couple={c.couple} />
|
|
</span>
|
|
))}
|
|
</div>
|
|
}
|
|
>
|
|
{p.depth >= 2 &&
|
|
children.map((c) => (
|
|
<FamilyTreeItem depth={p.depth - 1} key={c.member.id} n={c} />
|
|
))}
|
|
</TreeItem>
|
|
);
|
|
}
|
|
|
|
function BasicFamilyMemberItem(p: {
|
|
member: Member;
|
|
primary?: boolean;
|
|
couple?: Couple;
|
|
}): React.ReactElement {
|
|
const family = useFamily();
|
|
const n = useNavigate();
|
|
|
|
return (
|
|
<div
|
|
style={{ display: "flex", alignItems: "center" }}
|
|
onDoubleClick={() => n(family.family.memberURL(p.member))}
|
|
>
|
|
<MemberPhoto member={p.member} />
|
|
<span style={{ width: "10px" }}></span>
|
|
<div style={{ display: "flex", flexDirection: "column" }}>
|
|
<span style={{ fontWeight: p.primary ? "bold" : "unset" }}>
|
|
{p.member.fullName} {p.couple?.state && `(${p.couple.stateFr}) `}
|
|
{p.member?.dead && <Icon path={mdiCross} size={"1rem"} />}
|
|
</span>
|
|
|
|
{/* secondary information */}
|
|
<span style={{ display: "inline-flex", alignItems: "center" }}>
|
|
{p.member.dateOfBirth && (
|
|
<>
|
|
<Icon path={mdiBabyCarriage} size={"1rem"} />{" "}
|
|
{fmtDate(p.member.dateOfBirth)}
|
|
</>
|
|
)}
|
|
|
|
<span style={{ width: "10px" }}></span>
|
|
|
|
{p.member.dateOfDeath && (
|
|
<>
|
|
<Icon path={mdiCross} size={"1rem"} />
|
|
{fmtDate(p.member.dateOfDeath)}
|
|
</>
|
|
)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|