Can change invitation code
This commit is contained in:
		@@ -132,4 +132,14 @@ export class FamilyApi {
 | 
				
			|||||||
      uri: `/family/${id}/leave`,
 | 
					      uri: `/family/${id}/leave`,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Renew a family invitation code
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  static async RenewInvitationCode(id: number): Promise<void> {
 | 
				
			||||||
 | 
					    await APIClient.exec({
 | 
				
			||||||
 | 
					      method: "POST",
 | 
				
			||||||
 | 
					      uri: `/family/${id}/renew_invitation_code`,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -211,16 +211,19 @@ function FamilyCard(p: {
 | 
				
			|||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Card style={{ margin: "5px" }}>
 | 
					    <Card style={{ margin: "5px" }}>
 | 
				
			||||||
      <CardActionArea>
 | 
					      <CardActionArea>
 | 
				
			||||||
        {" "}
 | 
					 | 
				
			||||||
        <RouterLink to={p.f.BaseURL}>
 | 
					        <RouterLink to={p.f.BaseURL}>
 | 
				
			||||||
          <CardContent>
 | 
					          <CardContent>
 | 
				
			||||||
            <Typography gutterBottom variant="h5" component="div">
 | 
					            <Typography gutterBottom variant="h5" component="div">
 | 
				
			||||||
              {p.f.name}
 | 
					              {p.f.name}
 | 
				
			||||||
            </Typography>
 | 
					            </Typography>
 | 
				
			||||||
            <Typography variant="body2" color="text.secondary">
 | 
					            <Typography variant="body2" color="text.secondary">
 | 
				
			||||||
 | 
					              <span style={{ fontStyle: "italic" }}>
 | 
				
			||||||
 | 
					                {p.f.is_admin ? "Administrateur" : "Membre"}
 | 
				
			||||||
 | 
					              </span>
 | 
				
			||||||
 | 
					              <br />
 | 
				
			||||||
              {p.f.count_members === 1
 | 
					              {p.f.count_members === 1
 | 
				
			||||||
                ? "1 membre"
 | 
					                ? "1 membre"
 | 
				
			||||||
                : p.f.count_members + " membres"}{" "}
 | 
					                : p.f.count_members + " membres"}
 | 
				
			||||||
              <br />
 | 
					              <br />
 | 
				
			||||||
              {p.f.count_admins === 1
 | 
					              {p.f.count_admins === 1
 | 
				
			||||||
                ? "1 administrateur"
 | 
					                ? "1 administrateur"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
import {
 | 
					import {
 | 
				
			||||||
  mdiAccountMultiple,
 | 
					  mdiAccountMultiple,
 | 
				
			||||||
  mdiCog,
 | 
					  mdiCog,
 | 
				
			||||||
 | 
					  mdiContentCopy,
 | 
				
			||||||
  mdiCrowd,
 | 
					  mdiCrowd,
 | 
				
			||||||
  mdiFamilyTree,
 | 
					  mdiFamilyTree,
 | 
				
			||||||
  mdiHumanMaleFemale,
 | 
					  mdiHumanMaleFemale,
 | 
				
			||||||
@@ -11,19 +12,24 @@ import HomeIcon from "@mui/icons-material/Home";
 | 
				
			|||||||
import {
 | 
					import {
 | 
				
			||||||
  Box,
 | 
					  Box,
 | 
				
			||||||
  Divider,
 | 
					  Divider,
 | 
				
			||||||
 | 
					  IconButton,
 | 
				
			||||||
  List,
 | 
					  List,
 | 
				
			||||||
 | 
					  ListItem,
 | 
				
			||||||
  ListItemButton,
 | 
					  ListItemButton,
 | 
				
			||||||
  ListItemIcon,
 | 
					  ListItemIcon,
 | 
				
			||||||
  ListItemText,
 | 
					  ListItemText,
 | 
				
			||||||
  ListSubheader,
 | 
					  ListSubheader,
 | 
				
			||||||
  Tooltip,
 | 
					  Tooltip,
 | 
				
			||||||
} from "@mui/material";
 | 
					} from "@mui/material";
 | 
				
			||||||
 | 
					import { mdiRefresh } from "@mdi/js";
 | 
				
			||||||
import React from "react";
 | 
					import React from "react";
 | 
				
			||||||
import { Outlet, useLocation, useParams } from "react-router-dom";
 | 
					import { Outlet, useLocation, useParams } from "react-router-dom";
 | 
				
			||||||
import { Family, FamilyApi } from "../api/FamilyApi";
 | 
					import { Family, FamilyApi } from "../api/FamilyApi";
 | 
				
			||||||
import { AsyncWidget } from "./AsyncWidget";
 | 
					import { AsyncWidget } from "./AsyncWidget";
 | 
				
			||||||
import { RouterLink } from "./RouterLink";
 | 
					import { RouterLink } from "./RouterLink";
 | 
				
			||||||
import { useSnackbar } from "./SnackbarProvider";
 | 
					import { useSnackbar } from "./SnackbarProvider";
 | 
				
			||||||
 | 
					import { useConfirm } from "./ConfirmDialogProvider";
 | 
				
			||||||
 | 
					import { useAlert } from "./AlertDialogProvider";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface FamilyContext {
 | 
					interface FamilyContext {
 | 
				
			||||||
  family: Family;
 | 
					  family: Family;
 | 
				
			||||||
@@ -35,6 +41,8 @@ const FamilyContextK = React.createContext<FamilyContext | null>(null);
 | 
				
			|||||||
export function BaseFamilyRoute(): React.ReactElement {
 | 
					export function BaseFamilyRoute(): React.ReactElement {
 | 
				
			||||||
  const { familyId } = useParams();
 | 
					  const { familyId } = useParams();
 | 
				
			||||||
  const snackbar = useSnackbar();
 | 
					  const snackbar = useSnackbar();
 | 
				
			||||||
 | 
					  const alert = useAlert();
 | 
				
			||||||
 | 
					  const confirm = useConfirm();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [family, setFamily] = React.useState<null | Family>(null);
 | 
					  const [family, setFamily] = React.useState<null | Family>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -54,10 +62,30 @@ export function BaseFamilyRoute(): React.ReactElement {
 | 
				
			|||||||
    snackbar("Le code d'invitation a été copié dans le presse papier !");
 | 
					    snackbar("Le code d'invitation a été copié dans le presse papier !");
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const changeInvitationCode = async () => {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      if (
 | 
				
			||||||
 | 
					        !(await confirm.confirm(
 | 
				
			||||||
 | 
					          "Voulez-vous vraiment générer un nouveau code d'invitation pour cette famille ? Cette action aura pour effet d'invalider l'ancien code !"
 | 
				
			||||||
 | 
					        ))
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      await FamilyApi.RenewInvitationCode(family!.family_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      snackbar("Le code d'invitation a été changé avec succès !");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      onReload();
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      console.error(e);
 | 
				
			||||||
 | 
					      alert.alert("Echec du renouvellement du code d'invitation !");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <AsyncWidget
 | 
					    <AsyncWidget
 | 
				
			||||||
      ready={family != null}
 | 
					      ready={family != null}
 | 
				
			||||||
      loadKey={`${familyId}-${loadKey}`}
 | 
					      loadKey={`${familyId}-${loadKey.current}`}
 | 
				
			||||||
      load={load}
 | 
					      load={load}
 | 
				
			||||||
      errMsg="Échec du chargement des informations de la famille !"
 | 
					      errMsg="Échec du chargement des informations de la famille !"
 | 
				
			||||||
      build={() => (
 | 
					      build={() => (
 | 
				
			||||||
@@ -76,6 +104,7 @@ export function BaseFamilyRoute(): React.ReactElement {
 | 
				
			|||||||
            <List
 | 
					            <List
 | 
				
			||||||
              component="nav"
 | 
					              component="nav"
 | 
				
			||||||
              sx={{
 | 
					              sx={{
 | 
				
			||||||
 | 
					                minWidth: "280px",
 | 
				
			||||||
                backgroundColor: (theme) =>
 | 
					                backgroundColor: (theme) =>
 | 
				
			||||||
                  theme.palette.mode === "light"
 | 
					                  theme.palette.mode === "light"
 | 
				
			||||||
                    ? theme.palette.grey[100]
 | 
					                    ? theme.palette.grey[100]
 | 
				
			||||||
@@ -118,17 +147,35 @@ export function BaseFamilyRoute(): React.ReactElement {
 | 
				
			|||||||
              />
 | 
					              />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              {/* Invitation code */}
 | 
					              {/* Invitation code */}
 | 
				
			||||||
              <Tooltip title="Copier le code d'invitation dans le presse papier">
 | 
					
 | 
				
			||||||
                <ListItemButton onClick={copyInvitationCode}>
 | 
					              <ListItem
 | 
				
			||||||
                  <ListItemIcon>
 | 
					                dense
 | 
				
			||||||
                    <Icon path={mdiLockCheck} size={1} />
 | 
					                secondaryAction={
 | 
				
			||||||
                  </ListItemIcon>
 | 
					                  <span>
 | 
				
			||||||
                  <ListItemText
 | 
					                    <Tooltip title="Copier le code d'invitation dans le presse papier">
 | 
				
			||||||
                    primary="Code d'invitation"
 | 
					                      <IconButton onClick={copyInvitationCode}>
 | 
				
			||||||
                    secondary={family?.invitation_code}
 | 
					                        <Icon path={mdiContentCopy} size={0.75} />
 | 
				
			||||||
                  />
 | 
					                      </IconButton>
 | 
				
			||||||
                </ListItemButton>
 | 
					                    </Tooltip>
 | 
				
			||||||
              </Tooltip>
 | 
					
 | 
				
			||||||
 | 
					                    {family!.is_admin && (
 | 
				
			||||||
 | 
					                      <Tooltip title="Changer le code d'activation">
 | 
				
			||||||
 | 
					                        <IconButton onClick={changeInvitationCode}>
 | 
				
			||||||
 | 
					                          <Icon path={mdiRefresh} size={0.75} />
 | 
				
			||||||
 | 
					                        </IconButton>
 | 
				
			||||||
 | 
					                      </Tooltip>
 | 
				
			||||||
 | 
					                    )}
 | 
				
			||||||
 | 
					                  </span>
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					                <ListItemIcon>
 | 
				
			||||||
 | 
					                  <Icon path={mdiLockCheck} size={1} />
 | 
				
			||||||
 | 
					                </ListItemIcon>
 | 
				
			||||||
 | 
					                <ListItemText
 | 
				
			||||||
 | 
					                  primary="Code d'invitation"
 | 
				
			||||||
 | 
					                  secondary={family?.invitation_code}
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					              </ListItem>
 | 
				
			||||||
            </List>
 | 
					            </List>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <Box
 | 
					            <Box
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user