Skip to content

Commit

Permalink
Video-40-Create-And-Delete-Products
Browse files Browse the repository at this point in the history
  • Loading branch information
basir committed Jul 22, 2021
1 parent 29bc4df commit 1007ba3
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 27 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 +189,9 @@ $ Open http://localhost:3000
1. create cloudinary account
2. get cloudinary keys
3. create upload api
4. upload files in edit page
4. upload files in edit page
40. Create And Delete Products
1. add create product button
2. build new product api
3. add handler for delete
4. implement delete api
94 changes: 87 additions & 7 deletions pages/admin/products.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { getError } from '../../utils/error';
import { Store } from '../../utils/Store';
import Layout from '../../components/Layout';
import useStyles from '../../utils/styles';
import { useSnackbar } from 'notistack';

function reducer(state, action) {
switch (action.type) {
Expand All @@ -32,6 +33,20 @@ function reducer(state, action) {
return { ...state, loading: false, products: action.payload, error: '' };
case 'FETCH_FAIL':
return { ...state, loading: false, error: action.payload };
case 'CREATE_REQUEST':
return { ...state, loadingCreate: true };
case 'CREATE_SUCCESS':
return { ...state, loadingCreate: false };
case 'CREATE_FAIL':
return { ...state, loadingCreate: false };
case 'DELETE_REQUEST':
return { ...state, loadingDelete: true };
case 'DELETE_SUCCESS':
return { ...state, loadingDelete: false, successDelete: true };
case 'DELETE_FAIL':
return { ...state, loadingDelete: false };
case 'DELETE_RESET':
return { ...state, loadingDelete: false, successDelete: false };
default:
state;
}
Expand All @@ -43,7 +58,10 @@ function AdminDashboard() {
const classes = useStyles();
const { userInfo } = state;

const [{ loading, error, products }, dispatch] = useReducer(reducer, {
const [
{ loading, error, products, loadingCreate, successDelete, loadingDelete },
dispatch,
] = useReducer(reducer, {
loading: true,
products: [],
error: '',
Expand All @@ -64,8 +82,51 @@ function AdminDashboard() {
dispatch({ type: 'FETCH_FAIL', payload: getError(err) });
}
};
fetchData();
}, []);
if (successDelete) {
dispatch({ type: 'DELETE_RESET' });
} else {
fetchData();
}
}, [successDelete]);

const { enqueueSnackbar } = useSnackbar();
const createHandler = async () => {
if (!window.confirm('Are you sure?')) {
return;
}
try {
dispatch({ type: 'CREATE_REQUEST' });
const { data } = await axios.post(
`/api/admin/products`,
{},
{
headers: { authorization: `Bearer ${userInfo.token}` },
}
);
dispatch({ type: 'CREATE_SUCCESS' });
enqueueSnackbar('Product created successfully', { variant: 'success' });
router.push(`/admin/product/${data.product._id}`);
} catch (err) {
dispatch({ type: 'CREATE_FAIL' });
enqueueSnackbar(getError(err), { variant: 'error' });
}
};
const deleteHandler = async (productId) => {
if (!window.confirm('Are you sure?')) {
return;
}
try {
dispatch({ type: 'DELETE_REQUEST' });
await axios.delete(`/api/admin/products/${productId}`, {
headers: { authorization: `Bearer ${userInfo.token}` },
});
dispatch({ type: 'DELETE_SUCCESS' });
enqueueSnackbar('Product deleted successfully', { variant: 'success' });
} catch (err) {
dispatch({ type: 'DELETE_FAIL' });
enqueueSnackbar(getError(err), { variant: 'error' });
}
};
return (
<Layout title="Products">
<Grid container spacing={1}>
Expand Down Expand Up @@ -94,9 +155,24 @@ function AdminDashboard() {
<Card className={classes.section}>
<List>
<ListItem>
<Typography component="h1" variant="h1">
Products
</Typography>
<Grid container alignItems="center">
<Grid item xs={6}>
<Typography component="h1" variant="h1">
Products
</Typography>
{loadingDelete && <CircularProgress />}
</Grid>
<Grid align="right" item xs={6}>
<Button
onClick={createHandler}
color="primary"
variant="contained"
>
Create
</Button>
{loadingCreate && <CircularProgress />}
</Grid>
</Grid>
</ListItem>

<ListItem>
Expand Down Expand Up @@ -138,7 +214,11 @@ function AdminDashboard() {
Edit
</Button>
</NextLink>{' '}
<Button size="small" variant="contained">
<Button
onClick={() => deleteHandler(product._id)}
size="small"
variant="contained"
>
Delete
</Button>
</TableCell>
Expand Down
19 changes: 0 additions & 19 deletions pages/api/admin/products.js

This file was deleted.

13 changes: 13 additions & 0 deletions pages/api/admin/products/[id]/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,17 @@ handler.put(async (req, res) => {
}
});

handler.delete(async (req, res) => {
await db.connect();
const product = await Product.findById(req.query.id);
if (product) {
await product.remove();
await db.disconnect();
res.send({ message: 'Product Deleted' });
} else {
await db.disconnect();
res.status(404).send({ message: 'Product Not Found' });
}
});

export default handler;
36 changes: 36 additions & 0 deletions pages/api/admin/products/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import nc from 'next-connect';
import { isAdmin, isAuth } from '../../../../utils/auth';
import Product from '../../../../models/Product';
import db from '../../../../utils/db';

const handler = nc();
handler.use(isAuth, isAdmin);

handler.get(async (req, res) => {
await db.connect();
const products = await Product.find({});
await db.disconnect();
res.send(products);
});

handler.post(async (req, res) => {
await db.connect();
const newProduct = new Product({
name: 'sample name',
slug: 'sample-slug-' + Math.random(),
image: '/images/shirt1.jpg',
price: 0,
category: 'sample category',
brand: 'sample brand',
countInStock: 0,
description: 'sample description',
rating: 0,
numReviews: 0,
});

const product = await newProduct.save();
await db.disconnect();
res.send({ message: 'Product Created', product });
});

export default handler;

0 comments on commit 1007ba3

Please sign in to comment.