Create families list screen
This commit is contained in:
		@@ -1,6 +1,15 @@
 | 
			
		||||
import { APIClient } from "./ApiClient";
 | 
			
		||||
 | 
			
		||||
export interface Family {}
 | 
			
		||||
export interface Family {
 | 
			
		||||
  user_id: number;
 | 
			
		||||
  family_id: number;
 | 
			
		||||
  name: string;
 | 
			
		||||
  time_create: number;
 | 
			
		||||
  is_admin: boolean;
 | 
			
		||||
  invitation_code: string;
 | 
			
		||||
  count_members: number;
 | 
			
		||||
  count_admins: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum JoinFamilyResult {
 | 
			
		||||
  TooManyRequests,
 | 
			
		||||
@@ -50,10 +59,29 @@ export class FamilyApi {
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the list of families
 | 
			
		||||
   */
 | 
			
		||||
  static async GetList():Promise<Family[]> {
 | 
			
		||||
    return (await APIClient.exec({
 | 
			
		||||
      method: "GET",
 | 
			
		||||
      uri: "/family/list",
 | 
			
		||||
  static async GetList(): Promise<Family[]> {
 | 
			
		||||
    return (
 | 
			
		||||
      await APIClient.exec({
 | 
			
		||||
        method: "GET",
 | 
			
		||||
        uri: "/family/list",
 | 
			
		||||
      })
 | 
			
		||||
    ).data;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    })).data
 | 
			
		||||
  }}
 | 
			
		||||
  /**
 | 
			
		||||
   * Check if the current user user can leave a family
 | 
			
		||||
   */
 | 
			
		||||
  static CanLeaveFamily(f: Family): boolean {
 | 
			
		||||
    return !f.is_admin || f.count_admins > 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Attempt to leave a family
 | 
			
		||||
   */
 | 
			
		||||
  static async LeaveFamily(id: number): Promise<void> {
 | 
			
		||||
    await APIClient.exec({
 | 
			
		||||
      method: "POST",
 | 
			
		||||
      uri: `/family/${id}/leave`,
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,23 @@
 | 
			
		||||
import AddIcon from "@mui/icons-material/Add";
 | 
			
		||||
import ConfirmationNumberIcon from "@mui/icons-material/ConfirmationNumber";
 | 
			
		||||
import { Button, IconButton, Tooltip, Typography } from "@mui/material";
 | 
			
		||||
import {
 | 
			
		||||
  Button,
 | 
			
		||||
  Card,
 | 
			
		||||
  CardActionArea,
 | 
			
		||||
  CardActions,
 | 
			
		||||
  CardContent,
 | 
			
		||||
  IconButton,
 | 
			
		||||
  Tooltip,
 | 
			
		||||
  Typography,
 | 
			
		||||
} from "@mui/material";
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { Family, FamilyApi } from "../api/FamilyApi";
 | 
			
		||||
import { CreateFamilyDialog } from "../dialogs/CreateFamilyDialog";
 | 
			
		||||
import { JoinFamilyDialog } from "../dialogs/JoinFamilyDialog";
 | 
			
		||||
import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
			
		||||
import { TimeWidget } from "../widgets/TimeWidget";
 | 
			
		||||
import { useConfirm } from "../widgets/ConfirmDialogProvider";
 | 
			
		||||
import { useAlert } from "../widgets/AlertDialogProvider";
 | 
			
		||||
 | 
			
		||||
export function FamiliesListRoute(): React.ReactElement {
 | 
			
		||||
  const loadKey = React.useRef(1);
 | 
			
		||||
@@ -21,6 +33,7 @@ export function FamiliesListRoute(): React.ReactElement {
 | 
			
		||||
 | 
			
		||||
  const reload = () => {
 | 
			
		||||
    loadKey.current += 1;
 | 
			
		||||
    setFamilies(null);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const onRequestCreateFamily = async () => {
 | 
			
		||||
@@ -45,9 +58,10 @@ export function FamiliesListRoute(): React.ReactElement {
 | 
			
		||||
              onRequestJoinFamily={onRequestJoinFamily}
 | 
			
		||||
            />
 | 
			
		||||
          ) : (
 | 
			
		||||
            <HasFamilysWidget
 | 
			
		||||
            <HasFamiliesWidget
 | 
			
		||||
              onRequestCreateFamily={onRequestCreateFamily}
 | 
			
		||||
              onRequestJoinFamily={onRequestJoinFamily}
 | 
			
		||||
              onRequestRefresh={reload}
 | 
			
		||||
              families={families!}
 | 
			
		||||
            />
 | 
			
		||||
          )}
 | 
			
		||||
@@ -125,14 +139,21 @@ function NoFamilyButton(p: {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function HasFamilysWidget(p: {
 | 
			
		||||
function HasFamiliesWidget(p: {
 | 
			
		||||
  families: Family[];
 | 
			
		||||
  onRequestCreateFamily: () => void;
 | 
			
		||||
  onRequestJoinFamily: () => void;
 | 
			
		||||
  onRequestRefresh: () => void;
 | 
			
		||||
}): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
    <div style={{ width: "100%", maxWidth: "800px", margin: "20px auto" }}>
 | 
			
		||||
      <div style={{ display: "flex", justifyContent: "space-between" }}>
 | 
			
		||||
      <div
 | 
			
		||||
        style={{
 | 
			
		||||
          display: "flex",
 | 
			
		||||
          justifyContent: "space-between",
 | 
			
		||||
          marginBottom: "10px",
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <Typography variant="h4">Mes familles</Typography>
 | 
			
		||||
        <div>
 | 
			
		||||
          <IconButton aria-label="create" onClick={p.onRequestCreateFamily}>
 | 
			
		||||
@@ -147,7 +168,86 @@ function HasFamilysWidget(p: {
 | 
			
		||||
          </IconButton>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      TODO list of families
 | 
			
		||||
 | 
			
		||||
      {/* Display user memberships */}
 | 
			
		||||
      {p.families.map((f) => (
 | 
			
		||||
        <FamilyCard key={f.family_id} f={f} onFamilyLeft={p.onRequestRefresh} />
 | 
			
		||||
      ))}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function FamilyCard(p: {
 | 
			
		||||
  f: Family;
 | 
			
		||||
  onFamilyLeft: () => void;
 | 
			
		||||
}): React.ReactElement {
 | 
			
		||||
  const canLeave = FamilyApi.CanLeaveFamily(p.f);
 | 
			
		||||
  const confirm = useConfirm();
 | 
			
		||||
  const alert = useAlert();
 | 
			
		||||
 | 
			
		||||
  const leaveFamily = async () => {
 | 
			
		||||
    try {
 | 
			
		||||
      if (
 | 
			
		||||
        !canLeave ||
 | 
			
		||||
        !(await confirm.confirm(
 | 
			
		||||
          "Voulez-vous vraiment quitter la famille " + p.f.name + " ?"
 | 
			
		||||
        ))
 | 
			
		||||
      )
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
      await FamilyApi.LeaveFamily(p.f.family_id);
 | 
			
		||||
 | 
			
		||||
      p.onFamilyLeft();
 | 
			
		||||
 | 
			
		||||
      alert.alert(
 | 
			
		||||
        `La famille ${p.f.name} a été retirée de votre liste de familles !`
 | 
			
		||||
      );
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      console.error(e);
 | 
			
		||||
      alert.alert("Echec du retrait de la famille !");
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Card style={{ margin: "5px" }}>
 | 
			
		||||
      <CardActionArea>
 | 
			
		||||
        <CardContent>
 | 
			
		||||
          <Typography gutterBottom variant="h5" component="div">
 | 
			
		||||
            {p.f.name}
 | 
			
		||||
          </Typography>
 | 
			
		||||
          <Typography variant="body2" color="text.secondary">
 | 
			
		||||
            {p.f.count_members === 1
 | 
			
		||||
              ? "1 membre"
 | 
			
		||||
              : p.f.count_members + " membres"}{" "}
 | 
			
		||||
            <br />
 | 
			
		||||
            {p.f.count_admins === 1
 | 
			
		||||
              ? "1 administrateur"
 | 
			
		||||
              : p.f.count_admins + " administrateurs"}
 | 
			
		||||
            <br />
 | 
			
		||||
            Famille créée il y a <TimeWidget time={p.f.time_create} />
 | 
			
		||||
          </Typography>
 | 
			
		||||
        </CardContent>
 | 
			
		||||
      </CardActionArea>
 | 
			
		||||
      <CardActions>
 | 
			
		||||
        <Tooltip
 | 
			
		||||
          title={
 | 
			
		||||
            canLeave
 | 
			
		||||
              ? "Quitter la famille"
 | 
			
		||||
              : "Vous ne pouvez pas quitter cette famille, pour la retirer de cette liste vous devez la supprimer."
 | 
			
		||||
          }
 | 
			
		||||
        >
 | 
			
		||||
          <span style={{ marginLeft: "auto" }}>
 | 
			
		||||
            <Button
 | 
			
		||||
              size="small"
 | 
			
		||||
              color="primary"
 | 
			
		||||
              disabled={!canLeave}
 | 
			
		||||
              onClick={leaveFamily}
 | 
			
		||||
            >
 | 
			
		||||
              Quitter
 | 
			
		||||
            </Button>
 | 
			
		||||
          </span>
 | 
			
		||||
        </Tooltip>
 | 
			
		||||
      </CardActions>
 | 
			
		||||
    </Card>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -36,21 +36,6 @@ export function AsyncWidget(p: {
 | 
			
		||||
    load();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  if (state === State.Loading || p.ready === false)
 | 
			
		||||
    return (
 | 
			
		||||
      <div
 | 
			
		||||
        style={{
 | 
			
		||||
          display: "flex",
 | 
			
		||||
          justifyContent: "center",
 | 
			
		||||
          alignItems: "center",
 | 
			
		||||
          height: "100%",
 | 
			
		||||
          flex: "1",
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <CircularProgress />
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
  if (state === State.Error)
 | 
			
		||||
    return (
 | 
			
		||||
      <div
 | 
			
		||||
@@ -74,6 +59,21 @@ export function AsyncWidget(p: {
 | 
			
		||||
        <Button onClick={load}>Réessayer</Button>
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  console.log(p, counter.current);
 | 
			
		||||
 | 
			
		||||
  if (state === State.Loading || p.ready === false)
 | 
			
		||||
    return (
 | 
			
		||||
      <div
 | 
			
		||||
        style={{
 | 
			
		||||
          display: "flex",
 | 
			
		||||
          justifyContent: "center",
 | 
			
		||||
          alignItems: "center",
 | 
			
		||||
          height: "100%",
 | 
			
		||||
          flex: "1",
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <CircularProgress />
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
  return p.build();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user