fix errors

This commit is contained in:
karenvicent committed 2025-08-31 10:18:15 -04:00
1 parent 7c8ab64e34
commit e45dd4240e
6 files changed
+95 -70

No files matched your search

+1 -1
View File
@@ -65,7 +65,7 @@ const Check = ({ text, noHighlightText, variant = "info", outlined = false }) =>
};
Check.propTypes = {
text: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
text: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
noHighlightText: PropTypes.string,
variant: PropTypes.oneOf(["info", "error", "success"]),
outlined: PropTypes.bool,
@@ -67,7 +67,7 @@ GenericDialog.propTypes = {
theme: PropTypes.object.isRequired,
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node])
.isRequired,
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
};
export { GenericDialog };
+30 -12
View File
@@ -14,24 +14,23 @@ const useGetInviteToken = () => {
const clearToken = () => {
setToken(undefined);
};
const fetchToken = async (email, role) => {
const response = await networkService.requestInvitationToken({ email, role });
const token = response?.data?.data?.token;
if (typeof token === "undefined") {
throw new Error(t("inviteNoTokenFound"));
}
return token;
};
const getInviteToken = async ({ email, role }) => {
try {
const response = await networkService.requestInvitationToken({
email,
role,
});
const token = response?.data?.data?.token;
if (typeof token === "undefined") {
throw new Error(t("inviteNoTokenFound"));
}
setIsLoading(true);
const token = await fetchToken(email, role);
let inviteLink = token;
if (typeof CLIENT_HOST !== "undefined") {
inviteLink = `${CLIENT_HOST}/register/${token}`;
}
setToken(inviteLink);
return token;
} catch (error) {
@@ -41,7 +40,26 @@ const useGetInviteToken = () => {
}
};
return [getInviteToken, clearToken, isLoading, error, token];
const addTeamMember = async (formData, role) => {
try {
setIsLoading(true);
const token = await fetchToken(formData.email, role);
const toSubmit = {
...formData,
inviteToken: token,
};
delete toSubmit.confirm;
const responseRegister = await networkService.registerUser(toSubmit);
return responseRegister;
} catch (error) {
setError(error);
throw error;
} finally {
setIsLoading(false);
}
};
return [getInviteToken, clearToken, isLoading, error, token, addTeamMember];
};
export { useGetInviteToken };
@@ -0,0 +1,44 @@
import { useState } from "react";
import { newOrChangedCredentials } from "../../../../../Validation/validation";
const useAddTeamMember = () => {
const [errors, setErrors] = useState({});
const clearErrors = () => setErrors({});
const validateFields = (name, value, formData) => {
const { error } = newOrChangedCredentials.validate(
{ [name]: value },
{ abortEarly: false, context: { password: formData.password } }
);
setErrors((prev) => ({
...prev,
[name]: error?.details?.[0]?.message || "",
}));
};
const validateForm = (formData, role) => {
const { error } = newOrChangedCredentials.validate(formData, {
abortEarly: false,
context: { password: formData.password },
});
const formErrors = {};
if (error) {
for (const err of error.details) {
formErrors[err.path[0]] = err.message;
}
}
if (!role[0] || role.length === 0) {
formErrors.role = "Role is required";
}
if (Object.keys(formErrors).length > 0) {
setErrors(formErrors);
return false;
}
setErrors({});
return true;
};
return { errors, setErrors, clearErrors, validateFields, validateForm };
};
export default useAddTeamMember;
@@ -2,14 +2,13 @@ import { Button, Stack } from "@mui/material";
import { GenericDialog } from "../../../../Components/Dialog/genericDialog";
import TextInput from "../../../../Components/Inputs/TextInput";
import Select from "../../../../Components/Inputs/Select";
import { newOrChangedCredentials } from "../../../../Validation/validation";
import { useGetInviteToken } from "../../../../Hooks/inviteHooks";
import { useTheme } from "@emotion/react";
import { useTranslation } from "react-i18next";
import { createToast } from "../../../../Utils/toastUtils";
import { useState } from "react";
import { networkService } from "../../../../main";
import PasswordTooltip from "../../../Auth/components/PasswordTooltip";
import useAddTeamMember from "./hooks/useAddTeamMember";
import usePasswordFeedback from "../../../Auth/hooks/usePasswordFeedback";
import { PasswordEndAdornment } from "../../../../Components/Inputs/TextInput/Adornments";
import PropTypes from "prop-types";
@@ -26,16 +25,19 @@ const INITIAL_ROLE_STATE = ["user"];
const AddTeamMember = ({ handleIsRegisterOpen, isRegisterOpen, onMemberAdded }) => {
const theme = useTheme();
const { t } = useTranslation();
const { errors, setErrors, clearErrors, validateFields, validateForm } =
useAddTeamMember();
const { feedback, handlePasswordFeedback } = usePasswordFeedback();
const [getInviteToken, clearToken] = useGetInviteToken();
const [getInviteToken, clearToken, isLoading, error, token, addTeamMember] =
useGetInviteToken();
const [form, setForm] = useState(INITIAL_FORM_STATE);
const [role, setRole] = useState(INITIAL_ROLE_STATE);
const [errors, setErrors] = useState({});
const [isLoadingSubmit, setIsLoadingSubmit] = useState(false);
const closeAddMemberModal = () => {
handleIsRegisterOpen(false);
setForm(INITIAL_FORM_STATE);
setRole(INITIAL_ROLE_STATE);
setErrors({});
clearErrors();
clearToken();
};
@@ -43,17 +45,7 @@ const AddTeamMember = ({ handleIsRegisterOpen, isRegisterOpen, onMemberAdded })
let { name, value } = e.target;
if (name === "email") value = value.toLowerCase();
const updatedForm = { ...form, [name]: value };
const { error } = newOrChangedCredentials.validate(
{ [name]: value },
{ abortEarly: false, context: { password: form.password } }
);
setErrors((prev) => ({
...prev,
[name]: error?.details?.[0]?.message || "",
}));
validateFields(name, value, updatedForm);
setForm(updatedForm);
if (name === "password" || name === "confirm") {
@@ -63,42 +55,23 @@ const AddTeamMember = ({ handleIsRegisterOpen, isRegisterOpen, onMemberAdded })
const onsubmitAddMember = async (event) => {
event.preventDefault();
const { error } = newOrChangedCredentials.validate(form, {
abortEarly: false,
context: { password: form.password },
});
if (error) {
const formErrors = {};
for (const err of error.details) {
formErrors[err.path[0]] = err.message;
}
setErrors(formErrors);
return;
}
const token = await getInviteToken({ email: form.email, role: role });
const toSubmit = {
...form,
inviteToken: token,
};
delete toSubmit.confirm;
if (!validateForm(form, role)) return;
setIsLoadingSubmit(true);
try {
await networkService.registerUser(toSubmit);
await addTeamMember(form, role);
createToast({
body: t("teamPanel.registerToast.success"),
});
closeAddMemberModal();
onMemberAdded();
closeAddMemberModal();
} catch (error) {
const errorMsg = error.response?.data?.msg || error.message || "unknownError";
createToast({
type: "error",
body: t(errorMsg),
});
} finally {
setIsLoadingSubmit(false);
}
};
const tErr = (key) => (key ? t([`teamPanel.registerTeamMember.${key}`, key]) : "");
@@ -172,7 +145,6 @@ const AddTeamMember = ({ handleIsRegisterOpen, isRegisterOpen, onMemberAdded })
<PasswordTooltip
feedback={feedback}
form={form}
offset={[0, 45]}
>
<TextInput
type="password"
@@ -214,6 +186,7 @@ const AddTeamMember = ({ handleIsRegisterOpen, isRegisterOpen, onMemberAdded })
variant="contained"
color="error"
onClick={closeAddMemberModal}
disabled={isLoadingSubmit}
>
{t("teamPanel.cancel")}
</Button>
@@ -221,6 +194,7 @@ const AddTeamMember = ({ handleIsRegisterOpen, isRegisterOpen, onMemberAdded })
variant="contained"
color="accent"
onClick={onsubmitAddMember}
disabled={isLoadingSubmit}
>
{t("teamPanel.addTeamMember.addButton")}
</Button>
@@ -4,7 +4,7 @@ import { Tooltip, useTheme } from "@mui/material";
import { useTranslation } from "react-i18next";
import PropTypes from "prop-types";
const PasswordTooltip = ({ feedback, form, children, offset = [0, 0] }) => {
const PasswordTooltip = ({ feedback, form, children }) => {
const theme = useTheme();
const { t } = useTranslation();
const hasPassword = form.password.length > 0;
@@ -73,16 +73,6 @@ const PasswordTooltip = ({ feedback, form, children, offset = [0, 0] }) => {
</Stack>
}
slotProps={{
popper: {
modifiers: [
{
name: "offset",
options: {
offset: offset,
},
},
],
},
tooltip: {
sx: {
backgroundColor: theme.palette.tertiary.background,
@@ -103,14 +93,14 @@ const PasswordTooltip = ({ feedback, form, children, offset = [0, 0] }) => {
},
}}
>
{children}
<span style={{ display: "inline-block", width: "100%" }}>{children}</span>
</Tooltip>
);
};
PasswordTooltip.propTypes = {
feedback: PropTypes.shape({
length: PropTypes.string.isRequired,
length: PropTypes.string,
special: PropTypes.string,
number: PropTypes.string,
uppercase: PropTypes.string,
@@ -121,7 +111,6 @@ PasswordTooltip.propTypes = {
password: PropTypes.string.isRequired,
}),
children: PropTypes.node,
offset: PropTypes.arrayOf(PropTypes.number),
};
export default PasswordTooltip;