Skip to content

Commit 6e719cf

Browse files
[start 187584874] seller delete item
1 parent e3c1e41 commit 6e719cf

13 files changed

+193
-72
lines changed

Diff for: package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: src/App.scss

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@
2727
@import "./assets/styles/SellerProduct.scss";
2828
@import "./assets/styles/SellerCollection.scss";
2929
@import "./assets/styles/SellerLayout.scss";
30-
@import "./assets/styles/tables.scss";
30+
@import "./assets/styles/tables.scss";
31+
@import "./assets/styles/SellerDeleteItem.scss"

Diff for: src/assets/styles/SellerDeleteItem.scss

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
@import "./Colors";
2+
3+
.confirm-dialog {
4+
margin-left: 27rem;
5+
border-radius: 2.2rem;
6+
margin-top: 9rem;
7+
width: 80%;
8+
height: 87vh;
9+
position: fixed;
10+
top: 0;
11+
left: 0;
12+
right: 0;
13+
bottom: 0;
14+
background-color: rgba(0, 0, 0, 0.5);
15+
display: flex;
16+
justify-content: center;
17+
align-items: center;
18+
z-index: 1000;
19+
font-size: 1.6rem;
20+
21+
.confirm-dialog-content {
22+
background-color: white;
23+
padding: 20px;
24+
border-radius: 8px;
25+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
26+
text-align: center;
27+
28+
.modal-header {
29+
font-size: 1.8rem;
30+
font-weight: bold;
31+
margin-bottom: 1.5;
32+
display: flex;
33+
flex-direction: column;
34+
align-items: center;
35+
36+
.icon__delete {
37+
color: $red-color;
38+
font-size: 3rem;
39+
}
40+
}
41+
p{
42+
padding: 1rem 0;
43+
i{
44+
text-transform: uppercase;
45+
font-weight: bold;
46+
}
47+
}
48+
.modal-footer{
49+
float: right;
50+
button {
51+
margin: 0 10px;
52+
padding: .7rem 3rem;
53+
border: none;
54+
border-radius: 1rem;
55+
font-family: $text-family;
56+
}
57+
.delete-btn{
58+
background: $red-middle-color;
59+
color: $red-color;
60+
}
61+
.cancel-btn{
62+
background: lighten($fifth-color, 19%);
63+
color: $fifth-color;
64+
}
65+
}
66+
}
67+
}

Diff for: src/components/product/ConfirmModal.tsx

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* eslint-disable */
2+
import React from 'react';
3+
import DeleteIcon from '@mui/icons-material/Delete';
4+
5+
interface ConfirmModalProps {
6+
isOpen: boolean;
7+
title: string;
8+
message: string;
9+
onConfirm: () => void;
10+
onCancel: () => void;
11+
}
12+
13+
const ConfirmModal: React.FC<ConfirmModalProps> = ({ isOpen, title, message, onConfirm, onCancel }) => {
14+
if (!isOpen) return null;
15+
16+
return (
17+
<div className="confirm-dialog">
18+
<div className="confirm-dialog-content">
19+
<div className="modal-header">
20+
<DeleteIcon className='icon__delete' /> {title}
21+
</div>
22+
<p dangerouslySetInnerHTML={{ __html: message }} />
23+
<div className="modal-footer">
24+
<button onClick={onCancel} className='cancel-btn'>Cancel</button>
25+
<button onClick={onConfirm} className='delete-btn'>Delete</button>
26+
</div>
27+
</div>
28+
</div>
29+
);
30+
};
31+
32+
export default ConfirmModal;

Diff for: src/components/product/SellerProduct.tsx

+18-1
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@ import { fetchSingleSellerProduct } from '../../store/features/product/sellerPro
1010
import { Link } from 'react-router-dom';
1111
import { PuffLoader } from 'react-spinners';
1212
import { Meta } from '../Meta';
13+
import { deleteItem } from '../../store/features/product/sellerCollectionProductsSlice';
14+
import ConfirmModal from './ConfirmModal';
1315

1416
const SellerProduct = ({ productId }: { productId: string }) => {
1517
const dispatch = useAppDispatch();
1618
const { product, isError, isSuccess, isLoading, message }: ISingleProductInitialResponse = useAppSelector((state: any) => state.singleSellerProduct);
1719

1820
const [updatedProduct, setUpdatedProduct] = useState<ISingleProduct | null>(null);
21+
const [showConfirm, setShowConfirm] = useState(false);
22+
const [itemToDelete, setItemToDelete] = useState<string | null>(null);
1923

2024
useEffect(() => {
2125
dispatch(fetchSingleSellerProduct(productId));
@@ -40,6 +44,12 @@ const SellerProduct = ({ productId }: { productId: string }) => {
4044
const handleSave = () => {
4145
console.log('Updated product:', updatedProduct);
4246
};
47+
const handleDelete = async () => {
48+
if (updatedProduct) {
49+
await dispatch(deleteItem(itemToDelete));
50+
setShowConfirm(false);
51+
}
52+
};
4353

4454
return (
4555
<>
@@ -60,7 +70,7 @@ const SellerProduct = ({ productId }: { productId: string }) => {
6070
<h1>Product View</h1>
6171
<div className="header-btns">
6272
<button className='edit-btn' onClick={handleSave}><FaPen /> Save</button>
63-
<button className='delete-btn'><FaTrash /> Delete</button>
73+
<button className='delete-btn' onClick={() => { setShowConfirm(true); setItemToDelete(productId); }}><FaTrash /> Delete</button>
6474
</div>
6575
</div>
6676

@@ -151,6 +161,13 @@ const SellerProduct = ({ productId }: { productId: string }) => {
151161
<Link to="/seller/products" className="btn-link">View all my products</Link>
152162
</div>
153163
)}
164+
<ConfirmModal
165+
isOpen={showConfirm}
166+
title="Confirm Deletion"
167+
message={`Are you sure you want to delete the product <i>${product?.name}</i>? This action cannot be undone.`}
168+
onConfirm={handleDelete}
169+
onCancel={() => setShowConfirm(false)}
170+
/>
154171
</>
155172
)
156173
}

Diff for: src/pages/SellerDeleteItem.tsx

-34
This file was deleted.

Diff for: src/pages/seller/SellerCollection.tsx

+33-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/* eslint-disable */
2-
import React, { useEffect } from 'react'
2+
import React, { useEffect, useState } from 'react'
33
import Table from '../../components/table/Table';
44
import { useAppDispatch, useAppSelector } from '../../store/store';
5-
import { fetchSellerCollectionProduct } from '../../store/features/product/sellerCollectionProductsSlice';
5+
import { deleteItem, fetchSellerCollectionProduct } from '../../store/features/product/sellerCollectionProductsSlice';
66
import Zoom from '@mui/material/Zoom';
77
import Tooltip from '@mui/material/Tooltip';
88
import DeleteIcon from '@mui/icons-material/Delete';
@@ -14,6 +14,8 @@ import LinearProgress from '@mui/material/LinearProgress';
1414
import { useNavigate } from 'react-router-dom';
1515
import { Meta } from '../../components/Meta';
1616
import { FaEye } from 'react-icons/fa';
17+
import ConfirmModal from '../../components/product/ConfirmModal';
18+
1719
export default function SellerCollection() {
1820
const navigate = useNavigate()
1921
const dispatch = useAppDispatch();
@@ -23,7 +25,23 @@ export default function SellerCollection() {
2325
dispatch(fetchSellerCollectionProduct())
2426
}, [dispatch]);
2527

26-
const rows = data.products ? data.products
28+
const [showConfirm, setShowConfirm] = useState(false);
29+
const [itemToDelete, setItemToDelete] = useState<{ id: string; name: string } | null>(null);
30+
31+
32+
const handleDelete = async () => {
33+
try {
34+
if (itemToDelete !== null) {
35+
await dispatch(deleteItem(itemToDelete.id));
36+
setShowConfirm(false);
37+
setItemToDelete(null)
38+
}
39+
} catch (error) {
40+
console.error('Error deleting item:', error);
41+
}
42+
};
43+
44+
const rows = data?.products ? data.products
2745
.map((product, index) => [
2846
index + 1,
2947
<img src={product.images[0]} alt="image" className='product-img' />,
@@ -40,7 +58,7 @@ export default function SellerCollection() {
4058
</IconButton>
4159
</Tooltip>
4260
<Tooltip TransitionComponent={Zoom} title="Delete" arrow>
43-
<IconButton>
61+
<IconButton onClick={() => { setShowConfirm(true); setItemToDelete({ id: product.id, name: product.name }); }}>
4462
<DeleteIcon className='icon__delete' />
4563
</IconButton>
4664
</Tooltip>
@@ -52,6 +70,7 @@ export default function SellerCollection() {
5270
</div>
5371
]) : [];
5472

73+
const popupMessage= `Deleting this product <i>${itemToDelete?.name}</i> will be permanently removed from the system. This can’t be undone!`;
5574

5675
return (
5776
<div className='seller__main__container'>
@@ -64,6 +83,16 @@ export default function SellerCollection() {
6483
</div>
6584
)}
6685
<Table title={'Product List'} headers={headers} rows={rows} />
86+
87+
{showConfirm && (
88+
<ConfirmModal
89+
isOpen={showConfirm}
90+
title="Are you sure?"
91+
message={popupMessage}
92+
onConfirm={handleDelete}
93+
onCancel={() => setShowConfirm(false)}
94+
/>
95+
)}
6796
</div>
6897
)
6998
}

Diff for: src/router.tsx

-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import SellerViewProduct from "./pages/seller/SellerViewProduct";
2222
import SellerCollection from "./pages/seller/SellerCollection";
2323
import { SellerLayout } from "./components/layout/SellerLayout";
2424
import SellerDashboard from "./pages/seller/SellerDashboard";
25-
import SellerDeleteItem from "./pages/SellerDeleteItem";
2625

2726
const AppRouter: React.FC = () => {
2827
return (
@@ -60,7 +59,6 @@ const AppRouter: React.FC = () => {
6059
<Route path="shopping-cart" element={<UserViewCart />} />
6160
<Route path="*" element={<NotFound />} />
6261
<Route path="seller/login" element={<SellerLogin />} />
63-
<Route path="/deleteItem" element={<SellerDeleteItem/>}/>
6462
</Route>
6563
<Route path="/seller" element={<SellerLayout/>}>
6664
<Route index element={<Navigate to="dashboard" replace />} />

Diff for: src/store/features/product/productService.tsx

+11-1
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,23 @@ const fetchSellerSingleProduct = async (id: string) => {
6161
}
6262
};
6363

64+
const SellerDeleteItem = async(id: string)=>{
65+
try{
66+
const response = await axiosInstance.delete(`api/shop/seller-delete-product/${id}`);
67+
return response.data
68+
}catch(error){
69+
throw new Error("failed to delete product")
70+
}
71+
}
72+
6473
const productService = {
6574
fetchProducts,
6675
fetchSingleProduct,
6776
fetchProductReviews,
6877
fetchShopInfo,
6978
searchProduct,
7079
fetchSellerProducts,
71-
fetchSellerSingleProduct
80+
fetchSellerSingleProduct,
81+
SellerDeleteItem
7282
}
7383
export default productService;

Diff for: src/store/features/product/productSlice.tsx

+1-26
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,6 @@ export const searchProduct = createAsyncThunk<IProduct, SearchCriteria>("product
3131
}
3232
);
3333

34-
export const deleteItem = createAsyncThunk<ISingleProduct, string>("product/deleteProduct", async(id, thunkApi)=>{
35-
try{
36-
const response = await productService.deleteItem(id)
37-
return response
38-
} catch(error){
39-
return thunkApi.rejectWithValue(error)
40-
}
41-
})
42-
4334
const productSlice = createSlice({
4435
name: "products",
4536
initialState,
@@ -78,23 +69,7 @@ const productSlice = createSlice({
7869
state.message = action.payload;
7970
state.isSuccess = false;
8071
})
81-
.addCase(deleteItem.pending, (state)=>{
82-
state.isLoading = true,
83-
state.isError = false,
84-
state.isSuccess = false
85-
})
86-
.addCase(deleteItem.fulfilled, (state, action: PayloadAction<ISingleProduct>)=>{
87-
state.isLoading = false,
88-
state.isError = false,
89-
state.products = state.products.filter(product => product.id !== action.payload.id),
90-
state.isSuccess = true
91-
})
92-
.addCase(deleteItem.rejected, (state, action: PayloadAction<any>)=>{
93-
state.isLoading = false,
94-
state.isError = true,
95-
state.products = action.payload,
96-
state.isSuccess = false
97-
});
72+
;
9873
}
9974
})
10075

0 commit comments

Comments
 (0)