Skip to content

Commit

Permalink
Video-42. Create-User-Edit-Page
Browse files Browse the repository at this point in the history
  • Loading branch information
basir committed Jul 22, 2021
1 parent ede9349 commit d7d9b77
Show file tree
Hide file tree
Showing 3 changed files with 232 additions and 8 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,8 @@ $ Open http://localhost:3000
41. List Users For Admin
1. create users page
2. create users api
3. use api in page
3. use api in page
42. Create User Edit Page
1. create edit page
2. create api for user
3. show user data in form
226 changes: 226 additions & 0 deletions pages/admin/user/[id].js
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import axios from 'axios';
import dynamic from 'next/dynamic';
import { useRouter } from 'next/router';
import NextLink from 'next/link';
import React, { useEffect, useContext, useReducer, useState } from 'react';
import {
Grid,
List,
ListItem,
Typography,
Card,
Button,
ListItemText,
TextField,
CircularProgress,
Checkbox,
FormControlLabel,
} from '@material-ui/core';
import { getError } from '../../../utils/error';
import { Store } from '../../../utils/Store';
import Layout from '../../../components/Layout';
import useStyles from '../../../utils/styles';
import { Controller, useForm } from 'react-hook-form';
import { useSnackbar } from 'notistack';

function reducer(state, action) {
switch (action.type) {
case 'FETCH_REQUEST':
return { ...state, loading: true, error: '' };
case 'FETCH_SUCCESS':
return { ...state, loading: false, error: '' };
case 'FETCH_FAIL':
return { ...state, loading: false, error: action.payload };
case 'UPDATE_REQUEST':
return { ...state, loadingUpdate: true, errorUpdate: '' };
case 'UPDATE_SUCCESS':
return { ...state, loadingUpdate: false, errorUpdate: '' };
case 'UPDATE_FAIL':
return { ...state, loadingUpdate: false, errorUpdate: action.payload };
case 'UPLOAD_REQUEST':
return { ...state, loadingUpload: true, errorUpload: '' };
case 'UPLOAD_SUCCESS':
return {
...state,
loadingUpload: false,
errorUpload: '',
};
case 'UPLOAD_FAIL':
return { ...state, loadingUpload: false, errorUpload: action.payload };

default:
return state;
}
}

function UserEdit({ params }) {
const userId = params.id;
const { state } = useContext(Store);
const [{ loading, error, loadingUpdate }, dispatch] = useReducer(reducer, {
loading: true,
error: '',
});
const {
handleSubmit,
control,
formState: { errors },
setValue,
} = useForm();
const [isAdmin, setIsAdmin] = useState(false);
const { enqueueSnackbar, closeSnackbar } = useSnackbar();
const router = useRouter();
const classes = useStyles();
const { userInfo } = state;

useEffect(() => {
if (!userInfo) {
return router.push('/login');
} else {
const fetchData = async () => {
try {
dispatch({ type: 'FETCH_REQUEST' });
const { data } = await axios.get(`/api/admin/users/${userId}`, {
headers: { authorization: `Bearer ${userInfo.token}` },
});
setIsAdmin(data.isAdmin);
dispatch({ type: 'FETCH_SUCCESS' });
setValue('name', data.name);
} catch (err) {
dispatch({ type: 'FETCH_FAIL', payload: getError(err) });
}
};
fetchData();
}
}, []);

const submitHandler = async ({ name }) => {
closeSnackbar();
try {
dispatch({ type: 'UPDATE_REQUEST' });
await axios.put(
`/api/admin/users/${userId}`,
{
name,
isAdmin,
},
{ headers: { authorization: `Bearer ${userInfo.token}` } }
);
dispatch({ type: 'UPDATE_SUCCESS' });
enqueueSnackbar('User updated successfully', { variant: 'success' });
router.push('/admin/users');
} catch (err) {
dispatch({ type: 'UPDATE_FAIL', payload: getError(err) });
enqueueSnackbar(getError(err), { variant: 'error' });
}
};
return (
<Layout title={`Edit User ${userId}`}>
<Grid container spacing={1}>
<Grid item md={3} xs={12}>
<Card className={classes.section}>
<List>
<NextLink href="/admin/dashboard" passHref>
<ListItem button component="a">
<ListItemText primary="Admin Dashboard"></ListItemText>
</ListItem>
</NextLink>
<NextLink href="/admin/orders" passHref>
<ListItem button component="a">
<ListItemText primary="Orders"></ListItemText>
</ListItem>
</NextLink>
<NextLink href="/admin/products" passHref>
<ListItem button component="a">
<ListItemText primary="Products"></ListItemText>
</ListItem>
</NextLink>
<NextLink href="/admin/users" passHref>
<ListItem selected button component="a">
<ListItemText primary="Users"></ListItemText>
</ListItem>
</NextLink>
</List>
</Card>
</Grid>
<Grid item md={9} xs={12}>
<Card className={classes.section}>
<List>
<ListItem>
<Typography component="h1" variant="h1">
Edit User {userId}
</Typography>
</ListItem>
<ListItem>
{loading && <CircularProgress></CircularProgress>}
{error && (
<Typography className={classes.error}>{error}</Typography>
)}
</ListItem>
<ListItem>
<form
onSubmit={handleSubmit(submitHandler)}
className={classes.form}
>
<List>
<ListItem>
<Controller
name="name"
control={control}
defaultValue=""
rules={{
required: true,
}}
render={({ field }) => (
<TextField
variant="outlined"
fullWidth
id="name"
label="Name"
error={Boolean(errors.name)}
helperText={errors.name ? 'Name is required' : ''}
{...field}
></TextField>
)}
></Controller>
</ListItem>
<ListItem>
<FormControlLabel
label="Is Admin"
control={
<Checkbox
onClick={(e) => setIsAdmin(e.target.checked)}
checked={isAdmin}
name="isAdmin"
/>
}
></FormControlLabel>
</ListItem>
<ListItem>
<Button
variant="contained"
type="submit"
fullWidth
color="primary"
>
Update
</Button>
{loadingUpdate && <CircularProgress />}
</ListItem>
</List>
</form>
</ListItem>
</List>
</Card>
</Grid>
</Grid>
</Layout>
);
}

export async function getServerSideProps({ params }) {
return {
props: { params },
};
}

export default dynamic(() => Promise.resolve(UserEdit), { ssr: false });
8 changes: 1 addition & 7 deletions pages/api/admin/users/[id]/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,7 @@ handler.put(async (req, res) => {
const user = await User.findById(req.query.id);
if (user) {
user.name = req.body.name;
user.slug = req.body.slug;
user.price = req.body.price;
user.category = req.body.category;
user.image = req.body.image;
user.brand = req.body.brand;
user.countInStock = req.body.countInStock;
user.description = req.body.description;
user.isAdmin = Boolean(req.body.isAdmin);
await user.save();
await db.disconnect();
res.send({ message: 'User Updated Successfully' });
Expand Down

0 comments on commit d7d9b77

Please sign in to comment.