Can join a family
This commit is contained in:
parent
817d14ef36
commit
3721f4ba5a
@ -2,6 +2,14 @@ import { APIClient } from "./ApiClient";
|
|||||||
|
|
||||||
export interface Family {}
|
export interface Family {}
|
||||||
|
|
||||||
|
export enum JoinFamilyResult {
|
||||||
|
TooManyRequests,
|
||||||
|
InvalidCode,
|
||||||
|
AlreadyMember,
|
||||||
|
Error,
|
||||||
|
Success,
|
||||||
|
}
|
||||||
|
|
||||||
export class FamilyApi {
|
export class FamilyApi {
|
||||||
/**
|
/**
|
||||||
* Create a new family
|
* Create a new family
|
||||||
@ -13,4 +21,29 @@ export class FamilyApi {
|
|||||||
jsonData: { name: name },
|
jsonData: { name: name },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join an existing family
|
||||||
|
*/
|
||||||
|
static async JoinFamily(code: string): Promise<JoinFamilyResult> {
|
||||||
|
const res = await APIClient.exec({
|
||||||
|
method: "POST",
|
||||||
|
uri: "/family/join",
|
||||||
|
allowFail: true,
|
||||||
|
jsonData: { code: code },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.status >= 200 && res.status < 300) return JoinFamilyResult.Success;
|
||||||
|
|
||||||
|
switch (res.status) {
|
||||||
|
case 429:
|
||||||
|
return JoinFamilyResult.TooManyRequests;
|
||||||
|
case 404:
|
||||||
|
return JoinFamilyResult.InvalidCode;
|
||||||
|
case 409:
|
||||||
|
return JoinFamilyResult.AlreadyMember;
|
||||||
|
default:
|
||||||
|
return JoinFamilyResult.Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ interface Constraints {
|
|||||||
user_name_len: LenConstraint;
|
user_name_len: LenConstraint;
|
||||||
password_len: LenConstraint;
|
password_len: LenConstraint;
|
||||||
family_name_len: LenConstraint;
|
family_name_len: LenConstraint;
|
||||||
|
invitation_code_len: LenConstraint;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OIDCProvider {
|
interface OIDCProvider {
|
||||||
|
@ -39,7 +39,7 @@ export function CreateFamilyDialog(p: {
|
|||||||
return (
|
return (
|
||||||
<TextInputDialog
|
<TextInputDialog
|
||||||
open={p.open}
|
open={p.open}
|
||||||
title="Creation d'une famille"
|
title="Création d'une famille"
|
||||||
text="Veuillez définir le nom que vous souhaitez donner à la famille créée :"
|
text="Veuillez définir le nom que vous souhaitez donner à la famille créée :"
|
||||||
label="Nom de la famille"
|
label="Nom de la famille"
|
||||||
minLen={ServerApi.Config.constraints.family_name_len.min}
|
minLen={ServerApi.Config.constraints.family_name_len.min}
|
||||||
|
81
geneit_app/src/dialogs/JoinFamilyDialog.tsx
Normal file
81
geneit_app/src/dialogs/JoinFamilyDialog.tsx
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { TextInputDialog } from "./TextInputDialog";
|
||||||
|
import { ServerApi } from "../api/ServerApi";
|
||||||
|
import { FamilyApi, JoinFamilyResult } from "../api/FamilyApi";
|
||||||
|
import { useAlert } from "../widgets/AlertDialogProvider";
|
||||||
|
|
||||||
|
export function JoinFamilyDialog(p: {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
onJoined: () => void;
|
||||||
|
}): React.ReactElement {
|
||||||
|
const [code, setCode] = React.useState("");
|
||||||
|
const [joining, setJoining] = React.useState(false);
|
||||||
|
const [error, setError] = React.useState<string>();
|
||||||
|
|
||||||
|
const alert = useAlert();
|
||||||
|
|
||||||
|
const cancel = () => {
|
||||||
|
setCode("");
|
||||||
|
setJoining(false);
|
||||||
|
setError(undefined);
|
||||||
|
p.onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const joinFamily = async () => {
|
||||||
|
setJoining(true);
|
||||||
|
setError(undefined);
|
||||||
|
try {
|
||||||
|
const res = await FamilyApi.JoinFamily(code);
|
||||||
|
|
||||||
|
switch (res) {
|
||||||
|
case JoinFamilyResult.Success:
|
||||||
|
setCode("");
|
||||||
|
p.onJoined();
|
||||||
|
await alert.alert("La famille a été rejointe avec succès !");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JoinFamilyResult.TooManyRequests:
|
||||||
|
setError("Trop de tentatives, veuillez réessayer ultérieurement...");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JoinFamilyResult.InvalidCode:
|
||||||
|
setError("Le code spécifié est invalide !");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JoinFamilyResult.AlreadyMember:
|
||||||
|
setError("Vous êtes déjà membre de cette famille !");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JoinFamilyResult.Error:
|
||||||
|
setError("Erreur lors de la tentative de jonction à la famille !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
setError("Echec de l'appel au serveur !");
|
||||||
|
}
|
||||||
|
setJoining(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TextInputDialog
|
||||||
|
open={p.open}
|
||||||
|
title="Rejoindre une famille"
|
||||||
|
text="Veuillez spécifier le code d'invitation de la famille :"
|
||||||
|
label="Code de la famille"
|
||||||
|
minLen={ServerApi.Config.constraints.invitation_code_len.min}
|
||||||
|
maxLen={ServerApi.Config.constraints.invitation_code_len.max}
|
||||||
|
onClose={cancel}
|
||||||
|
onCancel={cancel}
|
||||||
|
submitButton="Rejoindre la famille"
|
||||||
|
value={code}
|
||||||
|
onValueChange={setCode}
|
||||||
|
isChecking={joining}
|
||||||
|
checkingMessage="Jointure en cours..."
|
||||||
|
errorIsBlocking={false}
|
||||||
|
error={error}
|
||||||
|
onSubmit={joinFamily}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -3,6 +3,7 @@ import { AsyncWidget } from "../widgets/AsyncWidget";
|
|||||||
import { Family } from "../api/FamilyApi";
|
import { Family } from "../api/FamilyApi";
|
||||||
import { Button, Typography } from "@mui/material";
|
import { Button, Typography } from "@mui/material";
|
||||||
import { CreateFamilyDialog } from "../dialogs/CreateFamilyDialog";
|
import { CreateFamilyDialog } from "../dialogs/CreateFamilyDialog";
|
||||||
|
import { JoinFamilyDialog } from "../dialogs/JoinFamilyDialog";
|
||||||
|
|
||||||
export function FamiliesListRoute(): React.ReactElement {
|
export function FamiliesListRoute(): React.ReactElement {
|
||||||
const loadKey = React.useRef(1);
|
const loadKey = React.useRef(1);
|
||||||
@ -10,6 +11,7 @@ export function FamiliesListRoute(): React.ReactElement {
|
|||||||
const [families, setFamilies] = React.useState<Family[] | null>(null);
|
const [families, setFamilies] = React.useState<Family[] | null>(null);
|
||||||
|
|
||||||
const [createFamily, setCreateFamily] = React.useState(false);
|
const [createFamily, setCreateFamily] = React.useState(false);
|
||||||
|
const [joinFamily, setJoinFamily] = React.useState(false);
|
||||||
|
|
||||||
const load = async () => {
|
const load = async () => {
|
||||||
// TODO : implement
|
// TODO : implement
|
||||||
@ -24,6 +26,10 @@ export function FamiliesListRoute(): React.ReactElement {
|
|||||||
setCreateFamily(true);
|
setCreateFamily(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onRequestJoinFamily = async () => {
|
||||||
|
setJoinFamily(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AsyncWidget
|
<AsyncWidget
|
||||||
loadKey={loadKey.current}
|
loadKey={loadKey.current}
|
||||||
@ -32,7 +38,10 @@ export function FamiliesListRoute(): React.ReactElement {
|
|||||||
build={() => (
|
build={() => (
|
||||||
<>
|
<>
|
||||||
{families!!.length === 0 ? (
|
{families!!.length === 0 ? (
|
||||||
<NoFamilyWidget onRequestCreateFamily={onRequestCreateFamily} />
|
<NoFamilyWidget
|
||||||
|
onRequestCreateFamily={onRequestCreateFamily}
|
||||||
|
onRequestJoinFamily={onRequestJoinFamily}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<HasFamilysWidget onReload={reload} families={families!} />
|
<HasFamilysWidget onReload={reload} families={families!} />
|
||||||
)}
|
)}
|
||||||
@ -46,6 +55,16 @@ export function FamiliesListRoute(): React.ReactElement {
|
|||||||
reload();
|
reload();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/** Join family dialog anchor */}
|
||||||
|
<JoinFamilyDialog
|
||||||
|
open={joinFamily}
|
||||||
|
onClose={() => setJoinFamily(false)}
|
||||||
|
onJoined={() => {
|
||||||
|
setJoinFamily(false);
|
||||||
|
reload();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@ -54,6 +73,7 @@ export function FamiliesListRoute(): React.ReactElement {
|
|||||||
|
|
||||||
function NoFamilyWidget(p: {
|
function NoFamilyWidget(p: {
|
||||||
onRequestCreateFamily: () => void;
|
onRequestCreateFamily: () => void;
|
||||||
|
onRequestJoinFamily: () => void;
|
||||||
}): React.ReactElement {
|
}): React.ReactElement {
|
||||||
return (
|
return (
|
||||||
<div style={{ flex: 1, display: "flex", alignItems: "center" }}>
|
<div style={{ flex: 1, display: "flex", alignItems: "center" }}>
|
||||||
@ -74,7 +94,10 @@ function NoFamilyWidget(p: {
|
|||||||
onClick={p.onRequestCreateFamily}
|
onClick={p.onRequestCreateFamily}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<NoFamilyButton label="Rejoindre une famille" onClick={() => {}} />
|
<NoFamilyButton
|
||||||
|
label="Rejoindre une famille"
|
||||||
|
onClick={p.onRequestJoinFamily}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -23,6 +23,7 @@ pub struct StaticConstraints {
|
|||||||
pub user_name_len: SizeConstraint,
|
pub user_name_len: SizeConstraint,
|
||||||
pub password_len: SizeConstraint,
|
pub password_len: SizeConstraint,
|
||||||
pub family_name_len: SizeConstraint,
|
pub family_name_len: SizeConstraint,
|
||||||
|
pub invitation_code_len: SizeConstraint,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for StaticConstraints {
|
impl Default for StaticConstraints {
|
||||||
@ -32,6 +33,10 @@ impl Default for StaticConstraints {
|
|||||||
user_name_len: SizeConstraint::new(3, 30),
|
user_name_len: SizeConstraint::new(3, 30),
|
||||||
password_len: SizeConstraint::new(8, 255),
|
password_len: SizeConstraint::new(8, 255),
|
||||||
family_name_len: SizeConstraint::new(3, 30),
|
family_name_len: SizeConstraint::new(3, 30),
|
||||||
|
invitation_code_len: SizeConstraint::new(
|
||||||
|
FAMILY_INVITATION_CODE_LEN,
|
||||||
|
FAMILY_INVITATION_CODE_LEN,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user