Show children on member page
This commit is contained in:
		@@ -191,6 +191,10 @@ export class MembersList {
 | 
			
		||||
  get(id: number): Member | undefined {
 | 
			
		||||
    return this.map.get(id);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  children(id: number): Member[] {
 | 
			
		||||
    return this.list.filter((m) => m.mother === id || m.father === id);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class MemberApi {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ 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 { MemberItem } from "../../widgets/MemberItem";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create a new member route
 | 
			
		||||
@@ -126,6 +127,7 @@ export function FamilyMemberRoute(): React.ReactElement {
 | 
			
		||||
      build={() => (
 | 
			
		||||
        <MemberPage
 | 
			
		||||
          member={member!}
 | 
			
		||||
          children={family.members.children(member!.id)}
 | 
			
		||||
          creating={false}
 | 
			
		||||
          editing={false}
 | 
			
		||||
          onRequestDelete={deleteMember}
 | 
			
		||||
@@ -144,13 +146,14 @@ export function FamilyMemberRoute(): React.ReactElement {
 | 
			
		||||
 */
 | 
			
		||||
export function FamilyEditMemberRoute(): React.ReactElement {
 | 
			
		||||
  const n = useNavigate();
 | 
			
		||||
  const { memberId } = useParams();
 | 
			
		||||
 | 
			
		||||
  const alert = useAlert();
 | 
			
		||||
  const snackbar = useSnackbar();
 | 
			
		||||
 | 
			
		||||
  const [shouldQuit, setShouldQuit] = React.useState(false);
 | 
			
		||||
 | 
			
		||||
  const family = useFamily();
 | 
			
		||||
  const { memberId } = useParams();
 | 
			
		||||
 | 
			
		||||
  const [member, setMember] = React.useState<Member>();
 | 
			
		||||
  const load = async () => {
 | 
			
		||||
@@ -202,6 +205,7 @@ export function MemberPage(p: {
 | 
			
		||||
  editing: boolean;
 | 
			
		||||
  creating: boolean;
 | 
			
		||||
  shouldAllowLeaving?: boolean;
 | 
			
		||||
  children?: Member[];
 | 
			
		||||
  onCancel?: () => void;
 | 
			
		||||
  onSave?: (m: Member) => void;
 | 
			
		||||
  onRequestEdit?: () => void;
 | 
			
		||||
@@ -211,6 +215,8 @@ export function MemberPage(p: {
 | 
			
		||||
  const confirm = useConfirm();
 | 
			
		||||
  const snackbar = useSnackbar();
 | 
			
		||||
 | 
			
		||||
  const family = useFamily();
 | 
			
		||||
 | 
			
		||||
  const [changed, setChanged] = React.useState(false);
 | 
			
		||||
  const [member, setMember] = React.useState(
 | 
			
		||||
    new Member(structuredClone(p.member))
 | 
			
		||||
@@ -604,9 +610,24 @@ export function MemberPage(p: {
 | 
			
		||||
        </Grid>
 | 
			
		||||
 | 
			
		||||
        {/* Children */}
 | 
			
		||||
        <Grid item sm={12} md={6}>
 | 
			
		||||
          <PropertiesBox title="Enfants">TODO</PropertiesBox>
 | 
			
		||||
        </Grid>
 | 
			
		||||
        {p.children && (
 | 
			
		||||
          <Grid item sm={12} md={6}>
 | 
			
		||||
            <PropertiesBox title="Enfants">
 | 
			
		||||
              {p.children.length === 0 ? (
 | 
			
		||||
                <>Aucun enfant</>
 | 
			
		||||
              ) : (
 | 
			
		||||
                p.children.map((c) => (
 | 
			
		||||
                  <RouterLink
 | 
			
		||||
                    key={c.id}
 | 
			
		||||
                    to={family.family.URL(`member/${c.id}`)}
 | 
			
		||||
                  >
 | 
			
		||||
                    <MemberItem member={c} />
 | 
			
		||||
                  </RouterLink>
 | 
			
		||||
                ))
 | 
			
		||||
              )}
 | 
			
		||||
            </PropertiesBox>
 | 
			
		||||
          </Grid>
 | 
			
		||||
        )}
 | 
			
		||||
      </Grid>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										45
									
								
								geneit_app/src/widgets/MemberItem.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								geneit_app/src/widgets/MemberItem.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
import { mdiCross } from "@mdi/js";
 | 
			
		||||
import {
 | 
			
		||||
  ListItemAvatar,
 | 
			
		||||
  ListItemButton,
 | 
			
		||||
  ListItemSecondaryAction,
 | 
			
		||||
  ListItemText,
 | 
			
		||||
} from "@mui/material";
 | 
			
		||||
import { Member, fmtDate } from "../api/MemberApi";
 | 
			
		||||
import { MemberPhoto } from "./MemberPhoto";
 | 
			
		||||
import Icon from "@mdi/react";
 | 
			
		||||
import FemaleIcon from "@mui/icons-material/Female";
 | 
			
		||||
import MaleIcon from "@mui/icons-material/Male";
 | 
			
		||||
 | 
			
		||||
export function MemberItem(p: {
 | 
			
		||||
  member?: Member;
 | 
			
		||||
  onClick?: () => void;
 | 
			
		||||
  secondary?: React.ReactElement;
 | 
			
		||||
}): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
    <ListItemButton onClick={p.onClick}>
 | 
			
		||||
      <ListItemAvatar>
 | 
			
		||||
        <MemberPhoto member={p.member!} />
 | 
			
		||||
      </ListItemAvatar>
 | 
			
		||||
      <ListItemText
 | 
			
		||||
        primary={
 | 
			
		||||
          <>
 | 
			
		||||
            {p.member?.fullName}{" "}
 | 
			
		||||
            {p.member?.sex === "F" ? (
 | 
			
		||||
              <FemaleIcon fontSize="small" htmlColor="pink" />
 | 
			
		||||
            ) : (
 | 
			
		||||
              <MaleIcon fontSize="small" htmlColor="lightBlue" />
 | 
			
		||||
            )}{" "}
 | 
			
		||||
            {p.member?.dead && <Icon path={mdiCross} size={"1rem"} />}
 | 
			
		||||
          </>
 | 
			
		||||
        }
 | 
			
		||||
        secondary={`${fmtDate(p.member?.dateOfBirth)} - ${fmtDate(
 | 
			
		||||
          p.member?.dateOfDeath
 | 
			
		||||
        )}`}
 | 
			
		||||
      />
 | 
			
		||||
      {p.secondary && (
 | 
			
		||||
        <ListItemSecondaryAction>{p.secondary}</ListItemSecondaryAction>
 | 
			
		||||
      )}
 | 
			
		||||
    </ListItemButton>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@@ -1,21 +1,10 @@
 | 
			
		||||
import { mdiCross } from "@mdi/js";
 | 
			
		||||
import Icon from "@mdi/react";
 | 
			
		||||
import ClearIcon from "@mui/icons-material/Clear";
 | 
			
		||||
import {
 | 
			
		||||
  Autocomplete,
 | 
			
		||||
  IconButton,
 | 
			
		||||
  ListItemAvatar,
 | 
			
		||||
  ListItemButton,
 | 
			
		||||
  ListItemSecondaryAction,
 | 
			
		||||
  ListItemText,
 | 
			
		||||
  TextField,
 | 
			
		||||
  Typography,
 | 
			
		||||
} from "@mui/material";
 | 
			
		||||
import { Autocomplete, IconButton, TextField, Typography } from "@mui/material";
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { useNavigate } from "react-router-dom";
 | 
			
		||||
import { Member, fmtDate } from "../../api/MemberApi";
 | 
			
		||||
import { Member } from "../../api/MemberApi";
 | 
			
		||||
import { useFamily } from "../BaseFamilyRoute";
 | 
			
		||||
import { MemberPhoto } from "../MemberPhoto";
 | 
			
		||||
import { MemberItem } from "../MemberItem";
 | 
			
		||||
 | 
			
		||||
export function MemberInput(p: {
 | 
			
		||||
  editable: boolean;
 | 
			
		||||
@@ -92,31 +81,3 @@ export function MemberInput(p: {
 | 
			
		||||
    />
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function MemberItem(p: {
 | 
			
		||||
  member?: Member;
 | 
			
		||||
  onClick?: () => void;
 | 
			
		||||
  secondary?: React.ReactElement;
 | 
			
		||||
}): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
    <ListItemButton onClick={p.onClick}>
 | 
			
		||||
      <ListItemAvatar>
 | 
			
		||||
        <MemberPhoto member={p.member!} />
 | 
			
		||||
      </ListItemAvatar>
 | 
			
		||||
      <ListItemText
 | 
			
		||||
        primary={
 | 
			
		||||
          <>
 | 
			
		||||
            {p.member?.fullName}{" "}
 | 
			
		||||
            {p.member?.dead && <Icon path={mdiCross} size={"1rem"} />}
 | 
			
		||||
          </>
 | 
			
		||||
        }
 | 
			
		||||
        secondary={`${fmtDate(p.member?.dateOfBirth)} - ${fmtDate(
 | 
			
		||||
          p.member?.dateOfDeath
 | 
			
		||||
        )}`}
 | 
			
		||||
      />
 | 
			
		||||
      {p.secondary && (
 | 
			
		||||
        <ListItemSecondaryAction>{p.secondary}</ListItemSecondaryAction>
 | 
			
		||||
      )}
 | 
			
		||||
    </ListItemButton>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user