mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-05-20 08:28:48 -05:00
fix unset
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
import { Stack, Box } from "@mui/material";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { ConfigBox } from "@/Components/v2/design-elements";
|
||||
import { TextField, Button } from "@/Components/v2/inputs";
|
||||
import { ImageUpload } from "@/Components/v2/inputs";
|
||||
|
||||
import { useTheme } from "@mui/material";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { useProfileForm } from "@/Hooks/useProfileForm";
|
||||
import { usePatch } from "@/Hooks/UseApi";
|
||||
import { setUser } from "@/Features/Auth/authSlice";
|
||||
@@ -13,6 +15,7 @@ import type { RootState } from "@/Types/state";
|
||||
import type { User } from "@/Types/User";
|
||||
|
||||
export const TabProfile = () => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const user = useSelector((state: RootState) => state.auth?.user);
|
||||
@@ -71,74 +74,66 @@ export const TabProfile = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
component="form"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
noValidate
|
||||
<Stack
|
||||
gap={theme.spacing(8)}
|
||||
component="form"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
>
|
||||
<ConfigBox
|
||||
title={t("pages.account.form.name.title")}
|
||||
subtitle={t("pages.account.form.name.description")}
|
||||
rightContent={
|
||||
<Stack gap={theme.spacing(8)}>
|
||||
<Controller
|
||||
name="firstName"
|
||||
control={control}
|
||||
render={({ field, fieldState }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fieldLabel={t("pages.account.form.name.option.firstName.label")}
|
||||
placeholder={t("pages.account.form.name.option.firstName.placeholder")}
|
||||
autoComplete="given-name"
|
||||
error={!!fieldState.error}
|
||||
helperText={fieldState.error?.message ?? ""}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
name="lastName"
|
||||
control={control}
|
||||
render={({ field, fieldState }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fieldLabel={t("pages.account.form.name.option.lastName.label")}
|
||||
placeholder={t("pages.account.form.name.option.lastName.placeholder")}
|
||||
autoComplete="family-name"
|
||||
error={!!fieldState.error}
|
||||
helperText={fieldState.error?.message ?? ""}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Stack>
|
||||
}
|
||||
/>
|
||||
<ConfigBox
|
||||
title={t("pages.account.form.photo.title")}
|
||||
subtitle={t("pages.account.form.photo.description")}
|
||||
rightContent={
|
||||
<ImageUpload
|
||||
src={getCurrentImageSrc()}
|
||||
onChange={handleImageChange}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
loading={patchLoading}
|
||||
sx={{ alignSelf: "flex-end", minWidth: 100 }}
|
||||
>
|
||||
<Stack gap={4}>
|
||||
<ConfigBox
|
||||
title={t("pages.account.form.name.title")}
|
||||
subtitle={t("pages.account.form.name.description")}
|
||||
rightContent={
|
||||
<Stack gap={3}>
|
||||
<Controller
|
||||
name="firstName"
|
||||
control={control}
|
||||
render={({ field, fieldState }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fieldLabel={t("pages.account.form.name.option.firstName.label")}
|
||||
placeholder={t(
|
||||
"pages.account.form.name.option.firstName.placeholder"
|
||||
)}
|
||||
autoComplete="given-name"
|
||||
error={!!fieldState.error}
|
||||
helperText={fieldState.error?.message ?? ""}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
name="lastName"
|
||||
control={control}
|
||||
render={({ field, fieldState }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fieldLabel={t("pages.account.form.name.option.lastName.label")}
|
||||
placeholder={t(
|
||||
"pages.account.form.name.option.lastName.placeholder"
|
||||
)}
|
||||
autoComplete="family-name"
|
||||
error={!!fieldState.error}
|
||||
helperText={fieldState.error?.message ?? ""}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Stack>
|
||||
}
|
||||
/>
|
||||
<ConfigBox
|
||||
title={t("pages.account.form.photo.title")}
|
||||
subtitle={t("pages.account.form.photo.description")}
|
||||
rightContent={
|
||||
<ImageUpload
|
||||
src={getCurrentImageSrc()}
|
||||
onChange={handleImageChange}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
loading={patchLoading}
|
||||
sx={{ alignSelf: "flex-end", minWidth: 100 }}
|
||||
>
|
||||
{t("common.buttons.save")}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Box>
|
||||
</>
|
||||
{t("common.buttons.save")}
|
||||
</Button>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -74,7 +74,6 @@ class AuthController {
|
||||
editUser = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
await editUserBodyValidation.validateAsync(req.body);
|
||||
|
||||
const updatedUser = await this.userService.editUser(req.body, req.file, req.user);
|
||||
|
||||
res.status(200).json({
|
||||
|
||||
@@ -98,10 +98,11 @@ class MongoUsersRepository implements IUsersRepository {
|
||||
|
||||
updateById = async (id: string, patch: Partial<User & { deleteProfileImage?: boolean }>, file?: Express.Multer.File | null): Promise<User> => {
|
||||
const candidateUser = { ...patch };
|
||||
let unsetFields: Record<string, 1> | undefined;
|
||||
|
||||
if (ParseBoolean(candidateUser.deleteProfileImage) === true) {
|
||||
candidateUser.profileImage = undefined;
|
||||
candidateUser.avatarImage = undefined;
|
||||
unsetFields = { profileImage: 1, avatarImage: 1 };
|
||||
delete candidateUser.deleteProfileImage;
|
||||
} else if (file) {
|
||||
// 1. Save the full size image
|
||||
candidateUser.profileImage = {
|
||||
@@ -114,13 +115,14 @@ class MongoUsersRepository implements IUsersRepository {
|
||||
candidateUser.avatarImage = avatar;
|
||||
}
|
||||
|
||||
const updatedUser = await UserModel.findOneAndUpdate(
|
||||
{ _id: id },
|
||||
candidateUser,
|
||||
{ new: true } // Returns updated user instead of pre-update user
|
||||
)
|
||||
.select("-password")
|
||||
.select("-profileImage");
|
||||
delete candidateUser.deleteProfileImage;
|
||||
|
||||
const updateQuery: Record<string, any> = { $set: candidateUser };
|
||||
if (unsetFields) {
|
||||
updateQuery.$unset = unsetFields;
|
||||
}
|
||||
|
||||
const updatedUser = await UserModel.findOneAndUpdate({ _id: id }, updateQuery, { new: true }).select("-password").select("-profileImage");
|
||||
if (!updatedUser) {
|
||||
throw new AppError({ message: "User not found", service: SERVICE_NAME, status: 404 });
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ const editUserBodyValidation = joi.object({
|
||||
profileImage: joi.any(),
|
||||
newPassword: joi.string().min(8).pattern(passwordPattern),
|
||||
password: joi.string().min(8).pattern(passwordPattern),
|
||||
deleteProfileImage: joi.boolean(),
|
||||
deleteProfileImage: joi.alternatives().try(joi.boolean(), joi.string().valid("true", "false")),
|
||||
});
|
||||
|
||||
const recoveryValidation = joi.object({
|
||||
|
||||
Reference in New Issue
Block a user