diff --git a/geneit_app/src/api/CoupleApi.ts b/geneit_app/src/api/CoupleApi.ts
index 00f7ab7..4199d6e 100644
--- a/geneit_app/src/api/CoupleApi.ts
+++ b/geneit_app/src/api/CoupleApi.ts
@@ -1,5 +1,5 @@
import { APIClient } from "./ApiClient";
-import { DateValue } from "./MemberApi";
+import { DateValue, Member } from "./MemberApi";
interface CoupleApiInterface {
id: number;
@@ -129,6 +129,10 @@ export class CouplesList {
get(id: number): Couple | undefined {
return this.map.get(id);
}
+
+ getAllOf(m: Member): Couple[] {
+ return this.filter((c) => c.husband === m.id || c.wife === m.id);
+ }
}
export class CoupleApi {
diff --git a/geneit_app/src/routes/family/FamilyMemberRoute.tsx b/geneit_app/src/routes/family/FamilyMemberRoute.tsx
index 420375c..e68c22e 100644
--- a/geneit_app/src/routes/family/FamilyMemberRoute.tsx
+++ b/geneit_app/src/routes/family/FamilyMemberRoute.tsx
@@ -3,11 +3,18 @@ import DeleteIcon from "@mui/icons-material/Delete";
import EditIcon from "@mui/icons-material/Edit";
import FileDownloadIcon from "@mui/icons-material/FileDownload";
import SaveIcon from "@mui/icons-material/Save";
-import { Button, Grid, Stack } from "@mui/material";
+import {
+ Button,
+ Grid,
+ ListItemAvatar,
+ ListItemButton,
+ ListItemText,
+ Stack,
+} from "@mui/material";
import * as EmailValidator from "email-validator";
import React from "react";
import { useNavigate, useParams } from "react-router-dom";
-import { Member, MemberApi } from "../../api/MemberApi";
+import { Member, MemberApi, fmtDate } from "../../api/MemberApi";
import { ServerApi } from "../../api/ServerApi";
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
import { useConfirm } from "../../hooks/context_providers/ConfirmDialogProvider";
@@ -27,6 +34,8 @@ import { PropEdit } from "../../widgets/forms/PropEdit";
import { PropSelect } from "../../widgets/forms/SelectInput";
import { SexSelection } from "../../widgets/forms/SexSelection";
import { UploadPhotoButton } from "../../widgets/forms/UploadPhotoButton";
+import { Couple } from "../../api/CoupleApi";
+import { CouplePhoto } from "../../widgets/CouplePhoto";
/**
* Create a new member route
@@ -129,6 +138,7 @@ export function FamilyMemberRoute(): React.ReactElement {
member={member!}
children={family.members.children(member!.id)}
siblings={family.members.siblings(member!.id)}
+ couples={family.couples.getAllOf(member!)}
creating={false}
editing={false}
onRequestDelete={deleteMember}
@@ -209,6 +219,7 @@ export function MemberPage(p: {
shouldAllowLeaving?: boolean;
children?: Member[];
siblings?: Member[];
+ couples?: Couple[];
onCancel?: () => void;
onSave?: (m: Member) => void;
onRequestEdit?: () => void;
@@ -606,12 +617,20 @@ export function MemberPage(p: {
)}
- {/* Spouse */}
-
-
- TODO
-
-
+ {/* Couples */}
+ {p.couples && (
+
+
+ {p.couples!.length === 0 ? (
+ <>{member.sex === "F" ? "Aucun époux" : "Aucune épouse"}>
+ ) : (
+ p.couples.map((c) => (
+
+ ))
+ )}
+
+
+ )}
{/* Children */}
{p.children && (
@@ -656,3 +675,47 @@ export function MemberPage(p: {
);
}
+
+function CoupleItem(p: {
+ currMemberId: number;
+ couple: Couple;
+}): React.ReactElement {
+ const n = useNavigate();
+
+ const family = useFamily();
+
+ const statusStr = ServerApi.Config.couples_states.find(
+ (c) => c.code === p.couple.state
+ )?.fr;
+
+ const status = [];
+ if (statusStr) status.push(statusStr);
+
+ if (p.couple.dateOfWedding)
+ status.push(`Mariage : ${fmtDate(p.couple.dateOfWedding)}`);
+
+ if (p.couple.dateOfDivorce)
+ status.push(`Divorce : ${fmtDate(p.couple.dateOfDivorce)}`);
+
+ const otherSpouseID =
+ p.couple.wife === p.currMemberId ? p.couple.husband : p.couple.wife;
+ const otherSpouse = otherSpouseID
+ ? family.members.get(otherSpouseID)
+ : undefined;
+
+ return (
+ n(family.family.coupleURL(p.couple))}>
+
+ {p.couple.hasPhoto ? (
+
+ ) : (
+
+ )}
+
+
+
+ );
+}
diff --git a/geneit_app/src/widgets/BaseFamilyRoute.tsx b/geneit_app/src/widgets/BaseFamilyRoute.tsx
index a59538d..8528afb 100644
--- a/geneit_app/src/widgets/BaseFamilyRoute.tsx
+++ b/geneit_app/src/widgets/BaseFamilyRoute.tsx
@@ -31,10 +31,12 @@ import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
import { useSnackbar } from "../hooks/context_providers/SnackbarProvider";
import { AsyncWidget } from "./AsyncWidget";
import { RouterLink } from "./RouterLink";
+import { CoupleApi, CouplesList } from "../api/CoupleApi";
interface FamilyContext {
family: Family;
members: MembersList;
+ couples: CouplesList;
familyId: number;
reloadFamilyInfo: () => void;
reloadMembersList: () => Promise;
@@ -51,6 +53,7 @@ export function BaseFamilyRoute(): React.ReactElement {
const [family, setFamily] = React.useState(null);
const [members, setMembers] = React.useState(null);
+ const [couples, setCouples] = React.useState(null);
const loadKey = React.useRef(1);
@@ -60,12 +63,14 @@ export function BaseFamilyRoute(): React.ReactElement {
const familyID = Number(familyId);
setFamily(await FamilyApi.GetSingle(familyID));
setMembers(await MemberApi.GetEntireList(familyID));
+ setCouples(await CoupleApi.GetEntireList(familyID));
};
const onReload = async () => {
loadKey.current += 1;
setFamily(null);
setMembers(null);
+ setCouples(null);
return new Promise((res, _rej) => {
loadPromise.current = () => res();
@@ -114,6 +119,7 @@ export function BaseFamilyRoute(): React.ReactElement {
value={{
family: family!,
members: members!,
+ couples: couples!,
familyId: family!.family_id,
reloadFamilyInfo: onReload,
reloadMembersList: onReload,
diff --git a/geneit_app/src/widgets/MemberPhoto.tsx b/geneit_app/src/widgets/MemberPhoto.tsx
index a0de049..5e19f06 100644
--- a/geneit_app/src/widgets/MemberPhoto.tsx
+++ b/geneit_app/src/widgets/MemberPhoto.tsx
@@ -2,7 +2,7 @@ import { Avatar } from "@mui/material";
import { Member } from "../api/MemberApi";
export function MemberPhoto(p: {
- member: Member;
+ member?: Member;
width?: number;
}): React.ReactElement {
return (
@@ -13,7 +13,7 @@ export function MemberPhoto(p: {
: undefined
}
variant="rounded"
- src={p.member.thumbnailURL ?? undefined}
+ src={p.member?.thumbnailURL ?? undefined}
/>
);
}