Show couples on members page
This commit is contained in:
parent
ec856b5cb4
commit
23fb77b152
@ -1,5 +1,5 @@
|
|||||||
import { APIClient } from "./ApiClient";
|
import { APIClient } from "./ApiClient";
|
||||||
import { DateValue } from "./MemberApi";
|
import { DateValue, Member } from "./MemberApi";
|
||||||
|
|
||||||
interface CoupleApiInterface {
|
interface CoupleApiInterface {
|
||||||
id: number;
|
id: number;
|
||||||
@ -129,6 +129,10 @@ export class CouplesList {
|
|||||||
get(id: number): Couple | undefined {
|
get(id: number): Couple | undefined {
|
||||||
return this.map.get(id);
|
return this.map.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAllOf(m: Member): Couple[] {
|
||||||
|
return this.filter((c) => c.husband === m.id || c.wife === m.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CoupleApi {
|
export class CoupleApi {
|
||||||
|
@ -3,11 +3,18 @@ import DeleteIcon from "@mui/icons-material/Delete";
|
|||||||
import EditIcon from "@mui/icons-material/Edit";
|
import EditIcon from "@mui/icons-material/Edit";
|
||||||
import FileDownloadIcon from "@mui/icons-material/FileDownload";
|
import FileDownloadIcon from "@mui/icons-material/FileDownload";
|
||||||
import SaveIcon from "@mui/icons-material/Save";
|
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 * 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 { Member, MemberApi } from "../../api/MemberApi";
|
import { Member, MemberApi, fmtDate } from "../../api/MemberApi";
|
||||||
import { ServerApi } from "../../api/ServerApi";
|
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";
|
||||||
@ -27,6 +34,8 @@ import { PropEdit } from "../../widgets/forms/PropEdit";
|
|||||||
import { PropSelect } from "../../widgets/forms/SelectInput";
|
import { PropSelect } from "../../widgets/forms/SelectInput";
|
||||||
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 { Couple } from "../../api/CoupleApi";
|
||||||
|
import { CouplePhoto } from "../../widgets/CouplePhoto";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new member route
|
* Create a new member route
|
||||||
@ -129,6 +138,7 @@ export function FamilyMemberRoute(): React.ReactElement {
|
|||||||
member={member!}
|
member={member!}
|
||||||
children={family.members.children(member!.id)}
|
children={family.members.children(member!.id)}
|
||||||
siblings={family.members.siblings(member!.id)}
|
siblings={family.members.siblings(member!.id)}
|
||||||
|
couples={family.couples.getAllOf(member!)}
|
||||||
creating={false}
|
creating={false}
|
||||||
editing={false}
|
editing={false}
|
||||||
onRequestDelete={deleteMember}
|
onRequestDelete={deleteMember}
|
||||||
@ -209,6 +219,7 @@ export function MemberPage(p: {
|
|||||||
shouldAllowLeaving?: boolean;
|
shouldAllowLeaving?: boolean;
|
||||||
children?: Member[];
|
children?: Member[];
|
||||||
siblings?: Member[];
|
siblings?: Member[];
|
||||||
|
couples?: Couple[];
|
||||||
onCancel?: () => void;
|
onCancel?: () => void;
|
||||||
onSave?: (m: Member) => void;
|
onSave?: (m: Member) => void;
|
||||||
onRequestEdit?: () => void;
|
onRequestEdit?: () => void;
|
||||||
@ -606,12 +617,20 @@ export function MemberPage(p: {
|
|||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Spouse */}
|
{/* Couples */}
|
||||||
<Grid item sm={12} md={6}>
|
{p.couples && (
|
||||||
<PropertiesBox title={member.sex === "F" ? "Époux" : "Épouse"}>
|
<Grid item sm={12} md={6}>
|
||||||
TODO
|
<PropertiesBox title={member.sex === "F" ? "Époux" : "Épouse"}>
|
||||||
</PropertiesBox>
|
{p.couples!.length === 0 ? (
|
||||||
</Grid>
|
<>{member.sex === "F" ? "Aucun époux" : "Aucune épouse"}</>
|
||||||
|
) : (
|
||||||
|
p.couples.map((c) => (
|
||||||
|
<CoupleItem key={c.id} currMemberId={member.id} couple={c} />
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</PropertiesBox>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Children */}
|
{/* Children */}
|
||||||
{p.children && (
|
{p.children && (
|
||||||
@ -656,3 +675,47 @@ export function MemberPage(p: {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<ListItemButton onClick={() => n(family.family.coupleURL(p.couple))}>
|
||||||
|
<ListItemAvatar>
|
||||||
|
{p.couple.hasPhoto ? (
|
||||||
|
<CouplePhoto couple={p.couple!} />
|
||||||
|
) : (
|
||||||
|
<MemberPhoto member={otherSpouse} />
|
||||||
|
)}
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText
|
||||||
|
primary={otherSpouse ? otherSpouse.fullName : "___ ___"}
|
||||||
|
secondary={status.join(" - ")}
|
||||||
|
></ListItemText>
|
||||||
|
</ListItemButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -31,10 +31,12 @@ import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
|
|||||||
import { useSnackbar } from "../hooks/context_providers/SnackbarProvider";
|
import { useSnackbar } from "../hooks/context_providers/SnackbarProvider";
|
||||||
import { AsyncWidget } from "./AsyncWidget";
|
import { AsyncWidget } from "./AsyncWidget";
|
||||||
import { RouterLink } from "./RouterLink";
|
import { RouterLink } from "./RouterLink";
|
||||||
|
import { CoupleApi, CouplesList } from "../api/CoupleApi";
|
||||||
|
|
||||||
interface FamilyContext {
|
interface FamilyContext {
|
||||||
family: Family;
|
family: Family;
|
||||||
members: MembersList;
|
members: MembersList;
|
||||||
|
couples: CouplesList;
|
||||||
familyId: number;
|
familyId: number;
|
||||||
reloadFamilyInfo: () => void;
|
reloadFamilyInfo: () => void;
|
||||||
reloadMembersList: () => Promise<void>;
|
reloadMembersList: () => Promise<void>;
|
||||||
@ -51,6 +53,7 @@ export function BaseFamilyRoute(): React.ReactElement {
|
|||||||
|
|
||||||
const [family, setFamily] = React.useState<null | Family>(null);
|
const [family, setFamily] = React.useState<null | Family>(null);
|
||||||
const [members, setMembers] = React.useState<null | MembersList>(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);
|
||||||
|
|
||||||
@ -60,12 +63,14 @@ export function BaseFamilyRoute(): React.ReactElement {
|
|||||||
const familyID = Number(familyId);
|
const familyID = Number(familyId);
|
||||||
setFamily(await FamilyApi.GetSingle(familyID));
|
setFamily(await FamilyApi.GetSingle(familyID));
|
||||||
setMembers(await MemberApi.GetEntireList(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);
|
setMembers(null);
|
||||||
|
setCouples(null);
|
||||||
|
|
||||||
return new Promise<void>((res, _rej) => {
|
return new Promise<void>((res, _rej) => {
|
||||||
loadPromise.current = () => res();
|
loadPromise.current = () => res();
|
||||||
@ -114,6 +119,7 @@ export function BaseFamilyRoute(): React.ReactElement {
|
|||||||
value={{
|
value={{
|
||||||
family: family!,
|
family: family!,
|
||||||
members: members!,
|
members: members!,
|
||||||
|
couples: couples!,
|
||||||
familyId: family!.family_id,
|
familyId: family!.family_id,
|
||||||
reloadFamilyInfo: onReload,
|
reloadFamilyInfo: onReload,
|
||||||
reloadMembersList: onReload,
|
reloadMembersList: onReload,
|
||||||
|
@ -2,7 +2,7 @@ import { Avatar } from "@mui/material";
|
|||||||
import { Member } from "../api/MemberApi";
|
import { Member } from "../api/MemberApi";
|
||||||
|
|
||||||
export function MemberPhoto(p: {
|
export function MemberPhoto(p: {
|
||||||
member: Member;
|
member?: Member;
|
||||||
width?: number;
|
width?: number;
|
||||||
}): React.ReactElement {
|
}): React.ReactElement {
|
||||||
return (
|
return (
|
||||||
@ -13,7 +13,7 @@ export function MemberPhoto(p: {
|
|||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
src={p.member.thumbnailURL ?? undefined}
|
src={p.member?.thumbnailURL ?? undefined}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user