Show couples on members page
This commit is contained in:
		@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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: {
 | 
			
		||||
          </Grid>
 | 
			
		||||
        )}
 | 
			
		||||
 | 
			
		||||
        {/* Spouse */}
 | 
			
		||||
        <Grid item sm={12} md={6}>
 | 
			
		||||
          <PropertiesBox title={member.sex === "F" ? "Époux" : "Épouse"}>
 | 
			
		||||
            TODO
 | 
			
		||||
          </PropertiesBox>
 | 
			
		||||
        </Grid>
 | 
			
		||||
        {/* Couples */}
 | 
			
		||||
        {p.couples && (
 | 
			
		||||
          <Grid item sm={12} md={6}>
 | 
			
		||||
            <PropertiesBox title={member.sex === "F" ? "Époux" : "Épouse"}>
 | 
			
		||||
              {p.couples!.length === 0 ? (
 | 
			
		||||
                <>{member.sex === "F" ? "Aucun époux" : "Aucune épouse"}</>
 | 
			
		||||
              ) : (
 | 
			
		||||
                p.couples.map((c) => (
 | 
			
		||||
                  <CoupleItem key={c.id} currMemberId={member.id} couple={c} />
 | 
			
		||||
                ))
 | 
			
		||||
              )}
 | 
			
		||||
            </PropertiesBox>
 | 
			
		||||
          </Grid>
 | 
			
		||||
        )}
 | 
			
		||||
 | 
			
		||||
        {/* Children */}
 | 
			
		||||
        {p.children && (
 | 
			
		||||
@@ -656,3 +675,47 @@ export function MemberPage(p: {
 | 
			
		||||
    </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 { 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<void>;
 | 
			
		||||
@@ -51,6 +53,7 @@ export function BaseFamilyRoute(): React.ReactElement {
 | 
			
		||||
 | 
			
		||||
  const [family, setFamily] = React.useState<null | Family>(null);
 | 
			
		||||
  const [members, setMembers] = React.useState<null | MembersList>(null);
 | 
			
		||||
  const [couples, setCouples] = React.useState<null | CouplesList>(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<void>((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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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}
 | 
			
		||||
    />
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user