Genealogy as a feature #175

Merged
pierre merged 16 commits from genealogy_as_a_feature into master 2024-05-16 19:15:16 +00:00
9 changed files with 72 additions and 66 deletions
Showing only changes of commit 28b29d6cd6 - Show all commits

View File

@ -6,12 +6,14 @@ import SaveIcon from "@mui/icons-material/Save";
import { Button, Grid, Stack } from "@mui/material"; import { Button, Grid, Stack } from "@mui/material";
import React from "react"; import React from "react";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { ServerApi } from "../../../api/ServerApi";
import { Couple, CoupleApi } from "../../../api/genealogy/CoupleApi"; import { Couple, CoupleApi } from "../../../api/genealogy/CoupleApi";
import { Member } from "../../../api/genealogy/MemberApi"; import { Member } from "../../../api/genealogy/MemberApi";
import { ServerApi } from "../../../api/ServerApi";
import { useAlert } from "../../../hooks/context_providers/AlertDialogProvider"; import { useAlert } from "../../../hooks/context_providers/AlertDialogProvider";
import { useConfirm } from "../../../hooks/context_providers/ConfirmDialogProvider"; import { useConfirm } from "../../../hooks/context_providers/ConfirmDialogProvider";
import { useLoadingMessage } from "../../../hooks/context_providers/LoadingMessageProvider";
import { useSnackbar } from "../../../hooks/context_providers/SnackbarProvider"; import { useSnackbar } from "../../../hooks/context_providers/SnackbarProvider";
import { useQuery } from "../../../hooks/useQuery";
import { AsyncWidget } from "../../../widgets/AsyncWidget"; import { AsyncWidget } from "../../../widgets/AsyncWidget";
import { useFamily } from "../../../widgets/BaseFamilyRoute"; import { useFamily } from "../../../widgets/BaseFamilyRoute";
import { ConfirmLeaveWithoutSaveDialog } from "../../../widgets/ConfirmLeaveWithoutSaveDialog"; import { ConfirmLeaveWithoutSaveDialog } from "../../../widgets/ConfirmLeaveWithoutSaveDialog";
@ -24,8 +26,7 @@ import { DateInput } from "../../../widgets/forms/DateInput";
import { MemberInput } from "../../../widgets/forms/MemberInput"; import { MemberInput } from "../../../widgets/forms/MemberInput";
import { PropSelect } from "../../../widgets/forms/PropSelect"; import { PropSelect } from "../../../widgets/forms/PropSelect";
import { UploadPhotoButton } from "../../../widgets/forms/UploadPhotoButton"; import { UploadPhotoButton } from "../../../widgets/forms/UploadPhotoButton";
import { useQuery } from "../../../hooks/useQuery"; import { useGenealogy } from "../../../widgets/genealogy/BaseGenealogyRoute";
import { useLoadingMessage } from "../../../hooks/context_providers/LoadingMessageProvider";
/** /**
* Create a new couple route * Create a new couple route
@ -36,6 +37,7 @@ export function FamilyCreateCoupleRoute(): React.ReactElement {
const [shouldQuit, setShouldQuit] = React.useState(false); const [shouldQuit, setShouldQuit] = React.useState(false);
const n = useNavigate(); const n = useNavigate();
const genealogy = useGenealogy();
const family = useFamily(); const family = useFamily();
const params = useQuery(); const params = useQuery();
@ -49,7 +51,7 @@ export function FamilyCreateCoupleRoute(): React.ReactElement {
try { try {
const r = await CoupleApi.Create(m); const r = await CoupleApi.Create(m);
await family.reloadCouplesList(); await genealogy.reloadCouplesList();
setShouldQuit(true); setShouldQuit(true);
n(family.family.coupleURL(r)); n(family.family.coupleURL(r));
@ -89,6 +91,7 @@ export function FamilyCoupleRoute(): React.ReactElement {
const snackbar = useSnackbar(); const snackbar = useSnackbar();
const family = useFamily(); const family = useFamily();
const genealogy = useGenealogy();
const { coupleId } = useParams(); const { coupleId } = useParams();
const [couple, setCouple] = React.useState<Couple>(); const [couple, setCouple] = React.useState<Couple>();
@ -100,7 +103,7 @@ export function FamilyCoupleRoute(): React.ReactElement {
count.current += 1; count.current += 1;
setCouple(undefined); setCouple(undefined);
await family.reloadCouplesList(); await genealogy.reloadCouplesList();
}; };
const deleteCouple = async () => { const deleteCouple = async () => {
@ -117,7 +120,7 @@ export function FamilyCoupleRoute(): React.ReactElement {
snackbar("La fiche du couple a été supprimée avec succès !"); snackbar("La fiche du couple a été supprimée avec succès !");
n(family.family.URL("genealogy/couples")); n(family.family.URL("genealogy/couples"));
await family.reloadCouplesList(); await genealogy.reloadCouplesList();
} catch (e) { } catch (e) {
console.error(e); console.error(e);
alert("Échec de la suppression du couple !"); alert("Échec de la suppression du couple !");
@ -133,7 +136,7 @@ export function FamilyCoupleRoute(): React.ReactElement {
build={() => ( build={() => (
<CouplePage <CouplePage
couple={couple!} couple={couple!}
children={family.members.childrenOfCouple(couple!)} children={genealogy.members.childrenOfCouple(couple!)}
creating={false} creating={false}
editing={false} editing={false}
onRequestDelete={deleteCouple} onRequestDelete={deleteCouple}
@ -157,6 +160,7 @@ export function FamilyEditCoupleRoute(): React.ReactElement {
const [shouldQuit, setShouldQuit] = React.useState(false); const [shouldQuit, setShouldQuit] = React.useState(false);
const genealogy = useGenealogy();
const family = useFamily(); const family = useFamily();
const [couple, setCouple] = React.useState<Couple>(); const [couple, setCouple] = React.useState<Couple>();
@ -176,7 +180,7 @@ export function FamilyEditCoupleRoute(): React.ReactElement {
snackbar("Les informations du couple ont été mises à jour avec succès !"); snackbar("Les informations du couple ont été mises à jour avec succès !");
await family.reloadCouplesList(); await genealogy.reloadCouplesList();
setShouldQuit(true); setShouldQuit(true);
n(family.family.coupleURL(c, false)); n(family.family.coupleURL(c, false));

View File

@ -17,6 +17,7 @@ import { CouplePhoto } from "../../../widgets/CouplePhoto";
import { FamilyPageTitle } from "../../../widgets/FamilyPageTitle"; import { FamilyPageTitle } from "../../../widgets/FamilyPageTitle";
import { MemberPhoto } from "../../../widgets/MemberPhoto"; import { MemberPhoto } from "../../../widgets/MemberPhoto";
import { RouterLink } from "../../../widgets/RouterLink"; import { RouterLink } from "../../../widgets/RouterLink";
import { useGenealogy } from "../../../widgets/genealogy/BaseGenealogyRoute";
export function FamilyCouplesListRoute(): React.ReactElement { export function FamilyCouplesListRoute(): React.ReactElement {
const alert = useAlert(); const alert = useAlert();
@ -24,6 +25,7 @@ export function FamilyCouplesListRoute(): React.ReactElement {
const snackbar = useSnackbar(); const snackbar = useSnackbar();
const family = useFamily(); const family = useFamily();
const genealogy = useGenealogy();
const [filter, setFilter] = React.useState(""); const [filter, setFilter] = React.useState("");
@ -37,7 +39,7 @@ export function FamilyCouplesListRoute(): React.ReactElement {
return; return;
await CoupleApi.Delete(c); await CoupleApi.Delete(c);
await family.reloadCouplesList(); await genealogy.reloadCouplesList();
snackbar("La fiche du couple a été supprimée avec succès !"); snackbar("La fiche du couple a été supprimée avec succès !");
} catch (e) { } catch (e) {
@ -63,7 +65,7 @@ export function FamilyCouplesListRoute(): React.ReactElement {
</RouterLink> </RouterLink>
</div> </div>
{family.couples.isEmpty ? ( {genealogy.couples.isEmpty ? (
<p> <p>
Votre famille n'a aucun couple enregistré pour le moment ! Utilisez le Votre famille n'a aucun couple enregistré pour le moment ! Utilisez le
bouton situé en haut à droite pour créer le premier ! bouton situé en haut à droite pour créer le premier !
@ -81,16 +83,16 @@ export function FamilyCouplesListRoute(): React.ReactElement {
<CouplesTable <CouplesTable
couples={ couples={
filter === "" filter === ""
? family.couples.fullList ? genealogy.couples.fullList
: family.couples.filter( : genealogy.couples.filter(
(m) => (m) =>
(m.wife && (m.wife &&
family.members genealogy.members
.get(m.wife)! .get(m.wife)!
.fullName.toLocaleLowerCase() .fullName.toLocaleLowerCase()
.includes(filter.toLocaleLowerCase())) || .includes(filter.toLocaleLowerCase())) ||
(m.husband && (m.husband &&
family.members genealogy.members
.get(m.husband)! .get(m.husband)!
.fullName.toLocaleLowerCase() .fullName.toLocaleLowerCase()
.includes(filter.toLocaleLowerCase())) === true .includes(filter.toLocaleLowerCase())) === true
@ -109,14 +111,18 @@ function CouplesTable(p: {
onDelete: (m: Couple) => void; onDelete: (m: Couple) => void;
}): React.ReactElement { }): React.ReactElement {
const family = useFamily(); const family = useFamily();
const genealogy = useGenealogy();
const n = useNavigate(); const n = useNavigate();
const compareInvertedMembersNames = ( const compareInvertedMembersNames = (
v1: number | undefined, v1: number | undefined,
v2: number | undefined v2: number | undefined
) => { ) => {
const n1 = ((v1 && family.members.get(v1)?.invertedFullName) ?? "") || ""; const n1 =
const n2 = ((v2 && family.members.get(v2)?.invertedFullName) ?? "") || ""; ((v1 && genealogy.members.get(v1)?.invertedFullName) ?? "") || "";
const n2 =
((v2 && genealogy.members.get(v2)?.invertedFullName) ?? "") || "";
return n1?.localeCompare(n2, undefined, { return n1?.localeCompare(n2, undefined, {
ignorePunctuation: true, ignorePunctuation: true,
@ -259,10 +265,10 @@ function CouplesTable(p: {
} }
function MemberCell(p: { id?: number }): React.ReactElement { function MemberCell(p: { id?: number }): React.ReactElement {
const family = useFamily(); const genealogy = useGenealogy();
if (!p.id) return <></>; if (!p.id) return <></>;
const member = family.members.get(p.id!)!; const member = genealogy.members.get(p.id!)!;
return ( return (
<Tooltip title="Double-cliquez ici pour accéder à la fiche du membre"> <Tooltip title="Double-cliquez ici pour accéder à la fiche du membre">

View File

@ -1,3 +1,5 @@
import { mdiFamilyTree } from "@mdi/js";
import Icon from "@mdi/react";
import ClearIcon from "@mui/icons-material/Clear"; import ClearIcon from "@mui/icons-material/Clear";
import DeleteIcon from "@mui/icons-material/Delete"; import DeleteIcon from "@mui/icons-material/Delete";
import EditIcon from "@mui/icons-material/Edit"; import EditIcon from "@mui/icons-material/Edit";
@ -14,12 +16,14 @@ import {
import * as EmailValidator from "email-validator"; import * as EmailValidator from "email-validator";
import React from "react"; import React from "react";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { ServerApi } from "../../../api/ServerApi";
import { Couple } from "../../../api/genealogy/CoupleApi"; import { Couple } from "../../../api/genealogy/CoupleApi";
import { Member, MemberApi, fmtDate } from "../../../api/genealogy/MemberApi"; import { Member, MemberApi, fmtDate } from "../../../api/genealogy/MemberApi";
import { ServerApi } from "../../../api/ServerApi";
import { useAlert } from "../../../hooks/context_providers/AlertDialogProvider"; import { useAlert } from "../../../hooks/context_providers/AlertDialogProvider";
import { useConfirm } from "../../../hooks/context_providers/ConfirmDialogProvider"; import { useConfirm } from "../../../hooks/context_providers/ConfirmDialogProvider";
import { useLoadingMessage } from "../../../hooks/context_providers/LoadingMessageProvider";
import { useSnackbar } from "../../../hooks/context_providers/SnackbarProvider"; import { useSnackbar } from "../../../hooks/context_providers/SnackbarProvider";
import { useQuery } from "../../../hooks/useQuery";
import { AsyncWidget } from "../../../widgets/AsyncWidget"; import { AsyncWidget } from "../../../widgets/AsyncWidget";
import { useFamily } from "../../../widgets/BaseFamilyRoute"; import { useFamily } from "../../../widgets/BaseFamilyRoute";
import { ConfirmLeaveWithoutSaveDialog } from "../../../widgets/ConfirmLeaveWithoutSaveDialog"; import { ConfirmLeaveWithoutSaveDialog } from "../../../widgets/ConfirmLeaveWithoutSaveDialog";
@ -36,10 +40,7 @@ import { PropEdit } from "../../../widgets/forms/PropEdit";
import { PropSelect } from "../../../widgets/forms/PropSelect"; import { PropSelect } from "../../../widgets/forms/PropSelect";
import { SexSelection } from "../../../widgets/forms/SexSelection"; import { SexSelection } from "../../../widgets/forms/SexSelection";
import { UploadPhotoButton } from "../../../widgets/forms/UploadPhotoButton"; import { UploadPhotoButton } from "../../../widgets/forms/UploadPhotoButton";
import { useQuery } from "../../../hooks/useQuery"; import { useGenealogy } from "../../../widgets/genealogy/BaseGenealogyRoute";
import { mdiFamilyTree } from "@mdi/js";
import Icon from "@mdi/react";
import { useLoadingMessage } from "../../../hooks/context_providers/LoadingMessageProvider";
/** /**
* Create a new member route * Create a new member route
@ -50,6 +51,7 @@ export function FamilyCreateMemberRoute(): React.ReactElement {
const [shouldQuit, setShouldQuit] = React.useState(false); const [shouldQuit, setShouldQuit] = React.useState(false);
const n = useNavigate(); const n = useNavigate();
const genealogy = useGenealogy();
const family = useFamily(); const family = useFamily();
const parameters = useQuery(); const parameters = useQuery();
@ -60,7 +62,7 @@ export function FamilyCreateMemberRoute(): React.ReactElement {
try { try {
const r = await MemberApi.Create(m); const r = await MemberApi.Create(m);
await family.reloadMembersList(); await genealogy.reloadMembersList();
setShouldQuit(true); setShouldQuit(true);
n(family.family.URL(`genealogy/member/${r.id}`)); n(family.family.URL(`genealogy/member/${r.id}`));
@ -104,6 +106,7 @@ export function FamilyMemberRoute(): React.ReactElement {
const snackbar = useSnackbar(); const snackbar = useSnackbar();
const family = useFamily(); const family = useFamily();
const genealogy = useGenealogy();
const { memberId } = useParams(); const { memberId } = useParams();
const [member, setMember] = React.useState<Member>(); const [member, setMember] = React.useState<Member>();
@ -115,7 +118,7 @@ export function FamilyMemberRoute(): React.ReactElement {
count.current += 1; count.current += 1;
setMember(undefined); setMember(undefined);
await family.reloadMembersList(); await genealogy.reloadMembersList();
}; };
const deleteMember = async () => { const deleteMember = async () => {
@ -132,7 +135,7 @@ export function FamilyMemberRoute(): React.ReactElement {
snackbar("La fiche de membre a été supprimée avec succès !"); snackbar("La fiche de membre a été supprimée avec succès !");
n(family.family.URL("genealogy/members")); n(family.family.URL("genealogy/members"));
await family.reloadMembersList(); await genealogy.reloadMembersList();
} catch (e) { } catch (e) {
console.error(e); console.error(e);
alert("Échec de la suppression du membre !"); alert("Échec de la suppression du membre !");
@ -148,9 +151,9 @@ export function FamilyMemberRoute(): React.ReactElement {
build={() => ( build={() => (
<MemberPage <MemberPage
member={member!} member={member!}
children={family.members.children(member!.id)} children={genealogy.members.children(member!.id)}
siblings={family.members.siblings(member!.id)} siblings={genealogy.members.siblings(member!.id)}
couples={family.couples.getAllOf(member!)} couples={genealogy.couples.getAllOf(member!)}
creating={false} creating={false}
editing={false} editing={false}
onrequestOpenTree={() => n(family.family.familyTreeURL(member!))} onrequestOpenTree={() => n(family.family.familyTreeURL(member!))}
@ -176,6 +179,7 @@ export function FamilyEditMemberRoute(): React.ReactElement {
const [shouldQuit, setShouldQuit] = React.useState(false); const [shouldQuit, setShouldQuit] = React.useState(false);
const family = useFamily(); const family = useFamily();
const genealogy = useGenealogy();
const [member, setMember] = React.useState<Member>(); const [member, setMember] = React.useState<Member>();
const load = async () => { const load = async () => {
@ -194,7 +198,7 @@ export function FamilyEditMemberRoute(): React.ReactElement {
snackbar("Les informations du membre ont été mises à jour avec succès !"); snackbar("Les informations du membre ont été mises à jour avec succès !");
await family.reloadMembersList(); await genealogy.reloadMembersList();
setShouldQuit(true); setShouldQuit(true);
n(family.family.memberURL(member!)); n(family.family.memberURL(member!));
@ -741,6 +745,7 @@ function CoupleItem(p: {
const n = useNavigate(); const n = useNavigate();
const family = useFamily(); const family = useFamily();
const genealogy = useGenealogy();
const statusStr = ServerApi.Config.couples_states.find( const statusStr = ServerApi.Config.couples_states.find(
(c) => c.code === p.couple.state (c) => c.code === p.couple.state
@ -758,7 +763,7 @@ function CoupleItem(p: {
const otherSpouseID = const otherSpouseID =
p.couple.wife === p.currMemberId ? p.couple.husband : p.couple.wife; p.couple.wife === p.currMemberId ? p.couple.husband : p.couple.wife;
const otherSpouse = otherSpouseID const otherSpouse = otherSpouseID
? family.members.get(otherSpouseID) ? genealogy.members.get(otherSpouseID)
: undefined; : undefined;
return ( return (

View File

@ -26,6 +26,7 @@ import { useFamily } from "../../../widgets/BaseFamilyRoute";
import { BasicFamilyTree } from "../../../widgets/BasicFamilyTree"; import { BasicFamilyTree } from "../../../widgets/BasicFamilyTree";
import { MemberItem } from "../../../widgets/MemberItem"; import { MemberItem } from "../../../widgets/MemberItem";
import { RouterLink } from "../../../widgets/RouterLink"; import { RouterLink } from "../../../widgets/RouterLink";
import { useGenealogy } from "../../../widgets/genealogy/BaseGenealogyRoute";
import { SimpleFamilyTree } from "../../../widgets/simple_family_tree/SimpleFamilyTree"; import { SimpleFamilyTree } from "../../../widgets/simple_family_tree/SimpleFamilyTree";
enum CurrTab { enum CurrTab {
@ -41,22 +42,23 @@ enum TreeMode {
export function FamilyMemberTreeRoute(): React.ReactElement { export function FamilyMemberTreeRoute(): React.ReactElement {
const { memberId } = useParams(); const { memberId } = useParams();
const genealogy = useGenealogy();
const family = useFamily(); const family = useFamily();
const [currTab, setCurrTab] = React.useState(CurrTab.SimpleTree); const [currTab, setCurrTab] = React.useState(CurrTab.SimpleTree);
const [currMode, setCurrMode] = React.useState(TreeMode.Descending); const [currMode, setCurrMode] = React.useState(TreeMode.Descending);
const member = family.members.get(Number(memberId)); const member = genealogy.members.get(Number(memberId));
const memo: [FamilyTreeNode, number] | null = React.useMemo(() => { const memo: [FamilyTreeNode, number] | null = React.useMemo(() => {
if (!member) return null; if (!member) return null;
const tree = const tree =
currMode === TreeMode.Ascending currMode === TreeMode.Ascending
? buildAscendingTree(member.id, family.members, family.couples) ? buildAscendingTree(member.id, genealogy.members, genealogy.couples)
: buildDescendingTree(member.id, family.members, family.couples); : buildDescendingTree(member.id, genealogy.members, genealogy.couples);
return [tree, treeHeight(tree)]; return [tree, treeHeight(tree)];
}, [member, currMode, family.members, family.couples]); }, [member, currMode, genealogy.members, genealogy.couples]);
const [currDepth, setCurrDepth] = React.useState(0); const [currDepth, setCurrDepth] = React.useState(0);

View File

@ -21,12 +21,14 @@ import { useFamily } from "../../../widgets/BaseFamilyRoute";
import { FamilyPageTitle } from "../../../widgets/FamilyPageTitle"; import { FamilyPageTitle } from "../../../widgets/FamilyPageTitle";
import { MemberPhoto } from "../../../widgets/MemberPhoto"; import { MemberPhoto } from "../../../widgets/MemberPhoto";
import { RouterLink } from "../../../widgets/RouterLink"; import { RouterLink } from "../../../widgets/RouterLink";
import { useGenealogy } from "../../../widgets/genealogy/BaseGenealogyRoute";
export function FamilyMembersListRoute(): React.ReactElement { export function FamilyMembersListRoute(): React.ReactElement {
const alert = useAlert(); const alert = useAlert();
const confirm = useConfirm(); const confirm = useConfirm();
const snackbar = useSnackbar(); const snackbar = useSnackbar();
const genealogy = useGenealogy();
const family = useFamily(); const family = useFamily();
const [filter, setFilter] = React.useState(""); const [filter, setFilter] = React.useState("");
@ -41,7 +43,7 @@ export function FamilyMembersListRoute(): React.ReactElement {
return; return;
await MemberApi.Delete(m); await MemberApi.Delete(m);
await family.reloadMembersList(); await genealogy.reloadMembersList();
snackbar("La fiche du membre a été supprimée avec succès !"); snackbar("La fiche du membre a été supprimée avec succès !");
} catch (e) { } catch (e) {
@ -67,7 +69,7 @@ export function FamilyMembersListRoute(): React.ReactElement {
</RouterLink> </RouterLink>
</div> </div>
{family.members.isEmpty ? ( {genealogy.members.isEmpty ? (
<p> <p>
Votre famille n'a aucun membre pour le moment ! Utilisez le bouton Votre famille n'a aucun membre pour le moment ! Utilisez le bouton
situé en haut à droite pour créer le premier ! situé en haut à droite pour créer le premier !
@ -85,8 +87,8 @@ export function FamilyMembersListRoute(): React.ReactElement {
<MembersTable <MembersTable
members={ members={
filter === "" filter === ""
? family.members.fullList ? genealogy.members.fullList
: family.members.filter((m) => : genealogy.members.filter((m) =>
m.fullName.toLowerCase().includes(filter.toLowerCase()) m.fullName.toLowerCase().includes(filter.toLowerCase())
) )
} }
@ -102,6 +104,7 @@ function MembersTable(p: {
members: Member[]; members: Member[];
onDelete: (m: Member) => void; onDelete: (m: Member) => void;
}): React.ReactElement { }): React.ReactElement {
const genealogy = useGenealogy();
const family = useFamily(); const family = useFamily();
const n = useNavigate(); const n = useNavigate();
@ -178,7 +181,7 @@ function MembersTable(p: {
renderCell(params) { renderCell(params) {
if (!params.row.father) if (!params.row.father)
return <Typography color="red">Non renseigné</Typography>; return <Typography color="red">Non renseigné</Typography>;
return family.members.get(params.row.father)!.fullName; return genealogy.members.get(params.row.father)!.fullName;
}, },
}, },
{ {
@ -188,7 +191,7 @@ function MembersTable(p: {
renderCell(params) { renderCell(params) {
if (!params.row.mother) if (!params.row.mother)
return <Typography color="red">Non renseignée</Typography>; return <Typography color="red">Non renseignée</Typography>;
return family.members.get(params.row.mother)!.fullName; return genealogy.members.get(params.row.mother)!.fullName;
}, },
}, },
{ {

View File

@ -1,8 +1,8 @@
import { useFamily } from "../../../widgets/BaseFamilyRoute";
import { FamilyPageTitle } from "../../../widgets/FamilyPageTitle"; import { FamilyPageTitle } from "../../../widgets/FamilyPageTitle";
import { useGenealogy } from "../../../widgets/genealogy/BaseGenealogyRoute";
export function GenealogyHomeRoute(): React.ReactElement { export function GenealogyHomeRoute(): React.ReactElement {
const family = useFamily(); const genealogy = useGenealogy();
return ( return (
<> <>
<FamilyPageTitle title="Généalogie de votre famille" /> <FamilyPageTitle title="Généalogie de votre famille" />
@ -12,8 +12,8 @@ export function GenealogyHomeRoute(): React.ReactElement {
compléter l'abre généalogique de votre famille. compléter l'abre généalogique de votre famille.
</p> </p>
<p>&nbsp;</p> <p>&nbsp;</p>
<p>Nombre de fiches de membres: {family.members.size}</p> <p>Nombre de fiches de membres: {genealogy.members.size}</p>
<p>Nombre de fiches de couples: {family.couples.size}</p> <p>Nombre de fiches de couples: {genealogy.couples.size}</p>
</div> </div>
</> </>
); );

View File

@ -27,8 +27,6 @@ import {
import React from "react"; import React from "react";
import { Outlet, useLocation, useParams } from "react-router-dom"; import { Outlet, useLocation, useParams } from "react-router-dom";
import { ExtendedFamilyInfo, FamilyApi } from "../api/FamilyApi"; import { ExtendedFamilyInfo, FamilyApi } from "../api/FamilyApi";
import { CoupleApi, CouplesList } from "../api/genealogy/CoupleApi";
import { MemberApi, MembersList } from "../api/genealogy/MemberApi";
import { useAlert } from "../hooks/context_providers/AlertDialogProvider"; import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider"; import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
import { useSnackbar } from "../hooks/context_providers/SnackbarProvider"; import { useSnackbar } from "../hooks/context_providers/SnackbarProvider";
@ -37,12 +35,8 @@ import { RouterLink } from "./RouterLink";
interface FamilyContext { interface FamilyContext {
family: ExtendedFamilyInfo; family: ExtendedFamilyInfo;
members: MembersList;
couples: CouplesList;
familyId: number; familyId: number;
reloadFamilyInfo: () => void; reloadFamilyInfo: () => void;
reloadMembersList: () => Promise<void>;
reloadCouplesList: () => Promise<void>;
} }
const FamilyContextK = React.createContext<FamilyContext | null>(null); const FamilyContextK = React.createContext<FamilyContext | null>(null);
@ -54,8 +48,6 @@ export function BaseFamilyRoute(): React.ReactElement {
const confirm = useConfirm(); const confirm = useConfirm();
const [family, setFamily] = React.useState<null | ExtendedFamilyInfo>(null); const [family, setFamily] = React.useState<null | ExtendedFamilyInfo>(null);
const [members, setMembers] = React.useState<null | MembersList>(null);
const [couples, setCouples] = React.useState<null | CouplesList>(null);
const loadKey = React.useRef(1); const loadKey = React.useRef(1);
@ -64,15 +56,11 @@ export function BaseFamilyRoute(): React.ReactElement {
const load = async () => { const load = async () => {
const familyID = Number(familyId); const familyID = Number(familyId);
setFamily(await FamilyApi.GetSingle(familyID)); setFamily(await FamilyApi.GetSingle(familyID));
setMembers(await MemberApi.GetEntireList(familyID));
setCouples(await CoupleApi.GetEntireList(familyID));
}; };
const onReload = async () => { const onReload = async () => {
loadKey.current += 1; loadKey.current += 1;
setFamily(null); setFamily(null);
setMembers(null);
setCouples(null);
return new Promise<void>((res, _rej) => { return new Promise<void>((res, _rej) => {
loadPromise.current = () => res(); loadPromise.current = () => res();
@ -106,7 +94,7 @@ export function BaseFamilyRoute(): React.ReactElement {
return ( return (
<AsyncWidget <AsyncWidget
ready={family !== null && members !== null} ready={family !== null}
loadKey={`${familyId}-${loadKey.current}`} loadKey={`${familyId}-${loadKey.current}`}
load={load} load={load}
errMsg="Échec du chargement des informations de la famille !" errMsg="Échec du chargement des informations de la famille !"
@ -120,12 +108,8 @@ export function BaseFamilyRoute(): React.ReactElement {
<FamilyContextK.Provider <FamilyContextK.Provider
value={{ value={{
family: family!, family: family!,
members: members!,
couples: couples!,
familyId: family!.family_id, familyId: family!.family_id,
reloadFamilyInfo: onReload, reloadFamilyInfo: onReload,
reloadMembersList: onReload,
reloadCouplesList: onReload,
}} }}
> >
<Box <Box

View File

@ -5,6 +5,7 @@ import { useNavigate } from "react-router-dom";
import { Member } from "../../api/genealogy/MemberApi"; import { Member } from "../../api/genealogy/MemberApi";
import { useFamily } from "../BaseFamilyRoute"; import { useFamily } from "../BaseFamilyRoute";
import { MemberItem } from "../MemberItem"; import { MemberItem } from "../MemberItem";
import { useGenealogy } from "../genealogy/BaseGenealogyRoute";
export function MemberInput(p: { export function MemberInput(p: {
editable: boolean; editable: boolean;
@ -15,13 +16,14 @@ export function MemberInput(p: {
}): React.ReactElement { }): React.ReactElement {
const n = useNavigate(); const n = useNavigate();
const family = useFamily(); const family = useFamily();
const genealogy = useGenealogy();
const choices = family.members.filter(p.filter); const choices = genealogy.members.filter(p.filter);
const [inputValue, setInputValue] = React.useState(""); const [inputValue, setInputValue] = React.useState("");
if (p.current) { if (p.current) {
const member = family.members.get(p.current)!; const member = genealogy.members.get(p.current)!;
return ( return (
<div style={{ display: "flex", alignItems: "center" }}> <div style={{ display: "flex", alignItems: "center" }}>
<Typography variant="body2">{p.label}</Typography> <Typography variant="body2">{p.label}</Typography>
@ -55,7 +57,7 @@ export function MemberInput(p: {
return ( return (
<Autocomplete <Autocomplete
value={p.current ? family.members.get(p.current) : undefined} value={p.current ? genealogy.members.get(p.current) : undefined}
onChange={(_event: any, newValue: Member | null | undefined) => { onChange={(_event: any, newValue: Member | null | undefined) => {
p.onValueChange(newValue?.id); p.onValueChange(newValue?.id);
}} }}

View File

@ -41,7 +41,7 @@ export function BaseGenealogyRoute(): React.ReactElement {
return ( return (
<AsyncWidget <AsyncWidget
ready={family !== null && members !== null} ready={members !== null && couples !== null}
loadKey={`${family.familyId}-${loadKey.current}`} loadKey={`${family.familyId}-${loadKey.current}`}
load={load} load={load}
errMsg="Échec du chargement des informations de généalogie de la famille !" errMsg="Échec du chargement des informations de généalogie de la famille !"