Skip to content

Commit

Permalink
560 connect admin users endpoint (#594)
Browse files Browse the repository at this point in the history
* change api url and params

* use redux return values to show state and return rules to make text field required
  • Loading branch information
Andrewy-gh authored Aug 9, 2024
1 parent 1cdd916 commit c4bea61
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 102 deletions.
8 changes: 5 additions & 3 deletions frontend/front/src/api/apiSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,10 +405,12 @@ export const apiSlice = createApi({
}),
}),
createUser: builder.mutation({
query: ({ email, password }) => ({
url: "/users",
query: ({ email, role, surveyor }) => ({
url: "/admin/users",
method: "POST",
body: { user: { email, password } },
body: {
user: { email, role, surveyor },
},
}),
}),
requestPasswordReset: builder.mutation({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const HeatPumpTextField = ({
message: "Invalid ZIP code.",
};
}
return ruleList;
}, [type, required]);

return (
Expand Down
199 changes: 100 additions & 99 deletions frontend/front/src/pages/Admin/user/CreateNewUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,9 @@ import {
Stack,
Typography,
} from "@mui/material";
import {
ROLE_ADMIN,
ROLE_SURVEYOR,
generatePassword,
} from "../../../features/login/loginUtils";
import React, { useCallback, useState } from "react";
import {
useCreateSurveyorMutation,
useCreateUserMutation,
} from "../../../api/apiSlice";
import { ROLE_ADMIN, ROLE_SURVEYOR } from "../../../features/login/loginUtils";
import { useCallback, useState } from "react";
import { useCreateUserMutation } from "../../../api/apiSlice";

import CustomSnackbar from "../../../components/CustomSnackbar";
import { HeatPumpDropdown } from "../../../components/SurveyComponent/HeatPumpDropdown";
Expand All @@ -32,9 +25,8 @@ const ACTION_NEW = "NEW";
const CreateNewUser = () => {
const navigate = useNavigate();

const [modalData, setModalData] = useState(null);
const [userError, setUserError] = useState(null);
const [isUserLoading, setIsUserLoading] = useState(false);
const [modalOpen, setModalOpen] = useState(false);
const [userError, setUserError] = useState(false);

const { handleSubmit, control, reset } = useForm({
defaultValues: {
Expand All @@ -49,110 +41,97 @@ const CreateNewUser = () => {
role: ROLE_SURVEYOR,
},
});

const [createUser] = useCreateUserMutation();
const [createSurveyor] = useCreateSurveyorMutation();
const [
createUser,
{
data: createUserData,
isLoading: isCreateUserLoading,
error: createUserError,
isSuccess: isCreateUserSuccess,
},
] = useCreateUserMutation();

const handleCancel = useCallback(() => {
navigate(withAdminPrefix(ADMIN_USER));
}, [navigate]);

const onSubmit = useCallback(
async (data) => {
setIsUserLoading(true);

const password = generatePassword();

try {
const user = await createUser({
email: data.email,
password,
}).unwrap();

// TODO: not 100% on whether all this data is necessary
const surveyorPayload = {
...data,
status: "active",
geocode: "unknown",
user_id: user.id,
};

await createSurveyor(surveyorPayload).unwrap();

setModalData({ ...user, password });
} catch (e) {
setUserError(e);
} finally {
setIsUserLoading(false);
}
},
[createUser, createSurveyor]
);

const handleModalClose = useCallback(
(action) => {
if (action === ACTION_BACK) {
handleCancel();
} else if (action === ACTION_NEW) {
reset();
setModalData(null);
setModalOpen(false);
}
},
[reset, handleCancel]
);

const modal = useCallback(
() => (
<Modal
open={modalData !== null}
onClose={() => handleModalClose(ACTION_NEW)}
>
<Box
// style stolen from mui modal example
sx={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 400,
bgcolor: "background.paper",
border: "2px solid #000",
boxShadow: 24,
p: 4,
}}
>
<p>
Succesfully created user <b>'{modalData?.email}'</b> with password{" "}
<b>'{modalData?.password}'</b>
</p>
<p>{"Write down this password to give to the surveyor!"}</p>
<Stack direction="row" justifyContent="right" spacing={2}>
<Button onClick={() => handleModalClose(ACTION_BACK)}>
Dashboard
</Button>
<Button
variant="contained"
onClick={() => handleModalClose(ACTION_NEW)}
>
Create Another
</Button>
</Stack>
</Box>
</Modal>
),
[handleModalClose, modalData]
(user) => {
return (
<Modal open={modalOpen} onClose={() => handleModalClose(ACTION_NEW)}>
<Box
// style stolen from mui modal example
sx={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 400,
bgcolor: "background.paper",
border: "2px solid #000",
boxShadow: 24,
p: 4,
}}
>
<Stack direction="row" justifyContent="center" sx={{ mb: 2 }}>
<p>
Succesfully created user <b>'{user?.email}'</b>
</p>
</Stack>
<Stack direction="row" justifyContent="right" spacing={2}>
<Button onClick={() => handleModalClose(ACTION_BACK)}>
Dashboard
</Button>
<Button
variant="contained"
onClick={() => handleModalClose(ACTION_NEW)}
>
Create Another
</Button>
</Stack>
</Box>
</Modal>
);
},
[handleModalClose, modalOpen]
);

const onSubmit = useCallback(
async (data) => {
setUserError(() => false);
try {
const { email, role, ...surveyor } = data;
const user = await createUser({
email,
role,
surveyor,
}).unwrap();
if (user) {
setModalOpen(true);
}
} catch (error) {
setUserError(() => true);
}
},
[createUser]
);

return (
<Container>
{modal()}
{
<CustomSnackbar
open={userError}
message="Error creating user account."
onClose={() => setUserError(null)}
/>
}
{!!isCreateUserSuccess && !!createUserData && modal(createUserData)}
{userError && <CustomSnackbar message="Error creating user account." />}
<Box sx={{ bgcolor: "primary.main", color: "white" }} p={1} m={1}>
<Typography variant="h5">Create User Profile</Typography>
</Box>
Expand All @@ -162,35 +141,57 @@ const CreateNewUser = () => {
control={control}
name="firstname"
label="First Name"
required
/>
<HeatPumpTextField
control={control}
name="lastname"
label="Last Name"
required
/>
<HeatPumpTextField
control={control}
name="email"
label="Email"
type="email"
required
/>
{/* Error message in case duplicate email */}
{createUserError?.data?.email.length > 0 && (
<Typography color="red" variant="body2">
Email {createUserError?.data?.email?.join(" ")}
</Typography>
)}
<HeatPumpPhoneField
control={control}
name="phone"
label="Phone Number"
required
/>
<HeatPumpTextField
control={control}
name="street_address"
label="Street Address"
required
/>
<HeatPumpTextField
control={control}
name="city"
label="City"
required
/>
<HeatPumpTextField
control={control}
name="state"
label="State"
required
/>
<HeatPumpTextField control={control} name="city" label="City" />
<HeatPumpTextField control={control} name="state" label="State" />
<HeatPumpTextField
control={control}
name="zipcode"
label="ZIP code"
type="zipcode"
required
/>
<HeatPumpDropdown
control={control}
Expand All @@ -203,7 +204,7 @@ const CreateNewUser = () => {
]}
/>
<Stack direction="row" justifyContent="right" spacing={2}>
{isUserLoading && <Loader />}
{!!isCreateUserLoading && <Loader />}
<Button variant="outlined" sx={{ ml: 2 }} type="submit">
Create
</Button>
Expand Down

0 comments on commit c4bea61

Please sign in to comment.