SHOW:
|
|
- or go back to the newest paste.
1 | // pages/cms/products/CMSProductsPage.tsx | |
2 | import clsx from 'clsx'; | |
3 | import { useEffect } from 'react'; | |
4 | import { useProductsService } from '@/services/products'; | |
5 | import { ServerError, Spinner } from '@/shared/'; | |
6 | ||
7 | export function CMSProductsPage() { | |
8 | const { state, actions } = useProductsService(); | |
9 | ||
10 | useEffect(() => { | |
11 | actions.getProducts() | |
12 | }, []) | |
13 | ||
14 | return ( | |
15 | <div> | |
16 | <h1 className="title">CMS</h1> | |
17 | ||
18 | {state.pending && <Spinner />} | |
19 | {state.error && <ServerError message={state.error} />} | |
20 | ||
21 | <div className="mt-12"> | |
22 | <table className="table-auto w-full hover"> | |
23 | <thead> | |
24 | <tr> | |
25 | <th className="text-left">PRODUCTS</th> | |
26 | <th className="text-left">IMAGE</th> | |
27 | <th>COST</th> | |
28 | <th>DELETE</th> | |
29 | </tr> | |
30 | </thead> | |
31 | ||
32 | <tbody> | |
33 | { | |
34 | state.products.map(item => { | |
35 | return ( | |
36 | <tr | |
37 | key={item.id} | |
38 | className={clsx( | |
39 | 'cursor-pointer', | |
40 | { 'bg-sky-200 text-black pointer-events-none': item.id === state.activeItem?.id } | |
41 | )} | |
42 | onClick={() => { | |
43 | actions.setActiveItem(item) | |
44 | }} | |
45 | > | |
46 | <td>{item.name}</td> | |
47 | <td> | |
48 | { item.tmb && <img src={item.tmb} alt={item.name} className="h-16 rounded-xl"/>} | |
49 | </td> | |
50 | <td className="text-center">€ {item.cost}</td> | |
51 | <td className="text-center"> | |
52 | <i | |
53 | className="fa fa-trash" | |
54 | onClick={(e) => { | |
55 | e.stopPropagation() | |
56 | actions.deleteProduct(item.id) | |
57 | }} | |
58 | /> | |
59 | </td> | |
60 | </tr> | |
61 | ) | |
62 | }) | |
63 | } | |
64 | </tbody> | |
65 | </table> | |
66 | </div> | |
67 | ||
68 | <pre>{JSON.stringify(state.activeItem, null, 2)}</pre> | |
69 | </div> | |
70 | ) | |
71 | } | |
72 |