Skip to content

Commit 52878fc

Browse files
(Add):<-Modal Delete->
1 parent ca4e509 commit 52878fc

File tree

7 files changed

+150
-28
lines changed

7 files changed

+150
-28
lines changed

db.json

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,6 @@
6060
"country": "Australia",
6161
"price": 289.88
6262
},
63-
{
64-
"id": 7,
65-
"name": "MegaMax M2",
66-
"description": "A plus-sized phone with a massive display and battery.",
67-
"year_of_creation": 2021,
68-
"rating": 4,
69-
"views": 9800,
70-
"country": "India",
71-
"price": 399.75
72-
},
7363
{
7464
"id": 8,
7565
"name": "Zenith Z9",
@@ -79,16 +69,6 @@
7969
"views": 5400,
8070
"country": "Italy",
8171
"price": 529.5
82-
},
83-
{
84-
"id": 9,
85-
"name": "RetroPhone R1",
86-
"description": "A nostalgic throwback to classic cellphones, reimagined for the modern era.",
87-
"year_of_creation": 2022,
88-
"rating": 4.3,
89-
"views": 3200,
90-
"country": "Japan",
91-
"price": 315
9272
}
9373
]
9474
}

index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
</head>
99
<body class="capitalize text-black dark:text-white bg-white dark:bg-black">
1010
<div id="root"></div>
11+
<div id="modal-root"></div>
1112
<script type="module" src="/src/main.tsx"></script>
1213
</body>
1314
</html>

package-lock.json

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"db": "json-server -p 5007 -w db.json"
1212
},
1313
"dependencies": {
14+
"@headlessui/react": "^1.7.17",
1415
"@reduxjs/toolkit": "^1.9.5",
1516
"@supabase/supabase-js": "^2.32.0",
1617
"@tanstack/react-query": "^4.32.6",

src/Components/Modal/index.tsx

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
import { Fragment } from 'react';
4+
import { Dialog, Transition } from '@headlessui/react';
5+
import * as Icons from 'react-icons/md';
6+
interface ModalProps {
7+
isOpen: boolean;
8+
onClose: () => void;
9+
children?: React.ReactNode;
10+
title?: string;
11+
}
12+
13+
const Modal: React.FC<ModalProps> = ({ isOpen, onClose, children, title }) => {
14+
return ReactDOM.createPortal(
15+
<Transition appear show={isOpen} as={Fragment}>
16+
<Dialog as="div" className="relative z-50" onClose={onClose}>
17+
<Transition.Child
18+
as={Fragment}
19+
enter="ease-out duration-300"
20+
enterFrom="opacity-0"
21+
enterTo="opacity-100"
22+
leave="ease-in duration-200"
23+
leaveFrom="opacity-100"
24+
leaveTo="opacity-0"
25+
>
26+
<div className="fixed inset-0 bg-black bg-opacity-25" />
27+
</Transition.Child>
28+
29+
<div className="fixed inset-0 overflow-y-auto">
30+
<div className="flex min-h-full items-center justify-center p-4 text-center">
31+
<Transition.Child
32+
as={Fragment}
33+
enter="ease-out duration-300"
34+
enterFrom="opacity-0 scale-95"
35+
enterTo="opacity-100 scale-100"
36+
leave="ease-in duration-200"
37+
leaveFrom="opacity-100 scale-100"
38+
leaveTo="opacity-0 scale-95"
39+
>
40+
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all">
41+
{title && (
42+
<Dialog.Title
43+
as="h3"
44+
className="text-lg font-medium leading-6 text-gray-900"
45+
>
46+
{title}
47+
</Dialog.Title>
48+
)}
49+
{children}
50+
</Dialog.Panel>
51+
</Transition.Child>
52+
</div>
53+
</div>
54+
</Dialog>
55+
</Transition>,
56+
document.getElementById('modal-root')!
57+
);
58+
};
59+
60+
export default Modal;

src/Components/Product/ProductTable/Cells.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import React from 'react';
22
import { ProductState } from '../../../Model/Product';
33
import * as Icons from 'react-icons/md';
4-
import useDeleteProduct from '../../../Hook/useDeleteProduct';
4+
55
interface CellsState {
66
products: ProductState[];
7+
handleSelectProductToDelete(product: ProductState): void;
78
}
89

9-
const Cells: React.FC<CellsState> = ({ products }) => {
10-
const { mutate: mutateDelete, status: statusDelete } = useDeleteProduct();
11-
const handleAsyncDeleteProduct = (id: number) => {
12-
mutateDelete(id);
13-
};
10+
const Cells: React.FC<CellsState> = ({
11+
products,
12+
handleSelectProductToDelete,
13+
}) => {
1414
return (
1515
<tbody className="divide-y divide-gray-300">
1616
{products?.map((product) => (
@@ -30,7 +30,7 @@ const Cells: React.FC<CellsState> = ({ products }) => {
3030
</button>
3131
<button
3232
className="px-3 py-1.5 bg-red-500 rounded-md capitalize hover:bg-orange-600"
33-
onClick={() => handleAsyncDeleteProduct(product.id)}
33+
onClick={() => handleSelectProductToDelete(product)}
3434
>
3535
<Icons.MdDelete size="1.4rem" />
3636
</button>

src/Components/Product/ProductTable/index.tsx

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,80 @@
11
import { ProductState } from '../../../Model/Product';
22
import Rows from './Rows';
33
import Cells from './Cells';
4+
import Modal from '../../Modal';
5+
import { useState } from 'react';
6+
import useDeleteProduct from '../../../Hook/useDeleteProduct';
47
interface ProductTableProps {
58
products?: ProductState[];
69
}
710

811
const ProductTable: React.FC<ProductTableProps> = ({ products }) => {
12+
// States
13+
const [isOpen, setIsOpen] = useState(false);
14+
const [selectProductToDelete, setSelectProductToDelete] =
15+
useState<ProductState>({} as ProductState);
16+
17+
// Select Product To Delete
18+
const handleSelectProductToDelete = (product: ProductState) => {
19+
setSelectProductToDelete(product);
20+
setIsOpen(true);
21+
};
22+
23+
// Close Modal
24+
const onClose = () => {
25+
setIsOpen(false);
26+
setSelectProductToDelete({} as ProductState);
27+
};
28+
29+
// Action Delete Product (Request)
30+
const { mutate: mutateDelete, status: statusDelete } = useDeleteProduct();
31+
const handleAsyncDeleteProduct = () => {
32+
mutateDelete(selectProductToDelete.id);
33+
setIsOpen(false);
34+
setSelectProductToDelete({} as ProductState);
35+
};
936
return (
1037
<div>
1138
<table className="min-w-full bg-white rounded-lg overflow-hidden shadow-md">
1239
{products && (
1340
<>
1441
<Rows products={products} />
15-
<Cells products={products} />
42+
<Cells
43+
products={products}
44+
handleSelectProductToDelete={handleSelectProductToDelete}
45+
/>
1646
</>
1747
)}
1848
</table>
49+
{/* Modal */}
50+
<Modal
51+
title=" Are you sure of removing the product?"
52+
isOpen={isOpen}
53+
onClose={onClose}
54+
>
55+
<div className="mt-2">
56+
<p className="text-sm text-gray-500">
57+
By deleting you no longer have access
58+
</p>
59+
</div>
60+
<div className="mt-4 flex gap-4">
61+
<button
62+
disabled={statusDelete === 'loading' ? true : false}
63+
type="button"
64+
className=" capitalize inline-flex justify-center rounded-md border border-transparent bg-red-100 px-4 py-2 text-sm font-medium text-red-900 hover:bg-red-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-red-500 focus-visible:ring-offset-2"
65+
onClick={handleAsyncDeleteProduct}
66+
>
67+
delete
68+
</button>
69+
<button
70+
type="button"
71+
className=" capitalize inline-flex justify-center rounded-md border border-transparent bg-green-100 px-4 py-2 text-sm font-medium text-green-900 hover:bg-green-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-green-500 focus-visible:ring-offset-2"
72+
onClick={onClose}
73+
>
74+
cancel
75+
</button>
76+
</div>
77+
</Modal>
1978
</div>
2079
);
2180
};

0 commit comments

Comments
 (0)