1
+ import { useState , useEffect } from "react" ;
2
+ import useApi from "../../hooks/APIHandler" ;
3
+ import { useNavigate } from "react-router-dom" ;
4
+ import { Box , Breadcrumbs , Button , Dialog , DialogContent , Divider , IconButton , LinearProgress , Table , TextField , Typography } from "@mui/material" ;
5
+ import { DataGrid , GridToolbar } from "@mui/x-data-grid" ;
6
+ import { isValidUrl } from "../../utils/Helper" ;
7
+ import Add from '@mui/icons-material/Add' ;
8
+ import Delete from '@mui/icons-material/Delete' ;
9
+ import Edit from '@mui/icons-material/Edit' ;
10
+ import RenderImage from "../../components/RenderImage" ;
11
+ import { Circle , Dashboard } from "@mui/icons-material" ;
12
+ import { set } from "react-hook-form" ;
13
+ import React from "react" ;
14
+ import ViewCompactIcon from '@mui/icons-material/ViewCompact' ;
15
+
16
+ const ManageProducts = ( ) => {
17
+ const [ data , setData ] = useState ( [ ] ) ;
18
+ const [ columns , setColumns ] = useState ( [ ] ) ;
19
+ const [ paginationModel , setPaginationModel ] = useState ( {
20
+ page :0 ,
21
+ pageSize :5
22
+ } )
23
+ const [ totalItems , setTotalItems ] = useState ( 0 ) ;
24
+ const [ searchQuery , setSearchQuery ] = useState ( "" ) ;
25
+ const [ debounceSearch , setDebounceSearch ] = useState ( "" ) ;
26
+ const [ ordering , setOrdering ] = useState ( [ { field :'id' , sort :'desc' } ] ) ;
27
+ const { error, loading, callApi} = useApi ( ) ;
28
+ const [ jsonData , setJsonData ] = useState ( [ ] ) ;
29
+ const [ open , setOpen ] = useState ( false ) ;
30
+ const [ htmldata , setHtmldata ] = useState ( '' ) ;
31
+ const [ openHtml , setOpenHtml ] = useState ( false ) ;
32
+ const [ modalTitle , setModalTitle ] = useState ( '' ) ;
33
+ const navigate = useNavigate ( ) ;
34
+
35
+ useEffect ( ( ) => {
36
+ const timer = setTimeout ( ( ) => {
37
+ setDebounceSearch ( searchQuery ) ;
38
+ } , 1000 )
39
+
40
+ return ( ) => {
41
+ clearTimeout ( timer ) ;
42
+ }
43
+ } , [ searchQuery ] )
44
+
45
+ const handleClose = ( ) => {
46
+ setOpen ( false ) ;
47
+ }
48
+
49
+ const handleClose2 = ( ) => {
50
+ setOpenHtml ( false ) ;
51
+ }
52
+
53
+ const getProducts = async ( ) => {
54
+ let order = '-id' ;
55
+ if ( ordering . length > 0 ) {
56
+ order = ordering [ 0 ] . sort === 'asc' ?ordering [ 0 ] . field :'-' + ordering [ 0 ] . field
57
+ }
58
+ const result = await callApi ( { url :'products/' , method :'GET' , params :{
59
+ page :paginationModel . page + 1 ,
60
+ pageSize :paginationModel . pageSize ,
61
+ search :debounceSearch ,
62
+ ordering :order
63
+ } } )
64
+ if ( result ) {
65
+ setData ( result . data . data . data ) ;
66
+ setTotalItems ( result . data . data . totalItems ) ;
67
+ generateColumns ( result . data . data . data ) ;
68
+ }
69
+ }
70
+
71
+ const onDeleteClick = ( params ) => {
72
+ console . log ( params ) ;
73
+ }
74
+ const onEditClick = ( params ) => {
75
+ console . log ( params ) ;
76
+ navigate ( `/form/product/${ params . row . id } ` )
77
+ }
78
+ const onAddClick = ( params ) => {
79
+ console . log ( params ) ;
80
+ navigate ( '/form/product' )
81
+ }
82
+
83
+ const showHTMLData = ( row ) => {
84
+ setHtmldata ( row ) ;
85
+ setOpenHtml ( true ) ;
86
+ }
87
+ const showJSONData = ( item , title ) => {
88
+ setModalTitle ( title )
89
+ setJsonData ( item )
90
+ setOpen ( true ) ;
91
+ }
92
+
93
+ const generateColumns = ( data ) => {
94
+ if ( data . length > 0 ) {
95
+ let columns = [ { field :'action' , headerName :'Action' , width :180 , sortable :false , renderCell :( params ) => {
96
+ return < >
97
+ < IconButton onClick = { ( ) => onAddClick ( params ) } >
98
+ < Add color = "light" />
99
+ </ IconButton >
100
+ < IconButton onClick = { ( ) => onEditClick ( params ) } >
101
+ < Edit color = "primary" />
102
+ </ IconButton >
103
+ < IconButton onClick = { ( ) => onDeleteClick ( params ) } >
104
+ < Delete color = "secondary" />
105
+ </ IconButton >
106
+ </ >
107
+ } } ] ;
108
+ for ( const key in data [ 0 ] ) {
109
+ if ( key === 'image' ) {
110
+ columns . push ( { field :key , headerName :key . charAt ( 0 ) . toUpperCase ( ) + key . slice ( 1 ) . replaceAll ( "_" , " " ) , width :150 , sortable :false , renderCell :( params ) => {
111
+ return < RenderImage data = { params . row . image } name = { params . row . name } />
112
+ } } )
113
+ }
114
+ else {
115
+ columns . push ( { field :key , headerName :key . charAt ( 0 ) . toUpperCase ( ) + key . slice ( 1 ) . replaceAll ( "_" , " " ) , width :200 } )
116
+ }
117
+ }
118
+ columns . push ( { field :'questions' , headerName :'Questions' , width :150 , sortable :false , renderCell :( params ) => {
119
+ return < Button startIcon = { < ViewCompactIcon /> } variant = "contained" > View</ Button >
120
+ } } )
121
+ columns . push ( { field :'reviews' , headerName :'Reviews' , width :150 , sortable :false , renderCell :( params ) => {
122
+ return < Button startIcon = { < ViewCompactIcon /> } variant = "contained" > View</ Button >
123
+ } } )
124
+ columns = columns . map ( ( column ) => {
125
+ if ( column . field === 'specifications' || column . field === 'highlights' || column . field === 'seo_keywords' || column . field === 'addition_details' ) {
126
+ return { field :column . field , headerName :column . field . charAt ( 0 ) . toUpperCase ( ) + column . field . slice ( 1 ) . replaceAll ( "_" , " " ) , width :150 , sortable :false , renderCell :( params ) => {
127
+ return < Button onClick = { ( ) => showJSONData ( params . row [ column . field ] , column . field . charAt ( 0 ) . toUpperCase ( ) + column . field . slice ( 1 ) . replaceAll ( "_" , " " ) ) } startIcon = { < ViewCompactIcon /> } variant = "contained" > View</ Button >
128
+ } }
129
+ }
130
+ if ( column . field === 'html_description' ) {
131
+ return { field :'html_description' , headerName :'HTML Description' , width :150 , sortable :false , renderCell :( params ) => {
132
+ return < Button onClick = { ( ) => showHTMLData ( params . row . html_description ) } startIcon = { < ViewCompactIcon /> } variant = "contained" > View</ Button >
133
+ } }
134
+ }
135
+
136
+ return column ;
137
+ } )
138
+ setColumns ( columns ) ;
139
+ }
140
+ }
141
+
142
+ const handleSorting = ( newModel ) => {
143
+ setOrdering ( newModel ) ;
144
+ }
145
+
146
+ useEffect ( ( ) => {
147
+ getProducts ( ) ;
148
+ } , [ paginationModel , debounceSearch , ordering ] )
149
+
150
+ return (
151
+ < Box component = { "div" } sx = { { width :'100%' } } >
152
+ < Breadcrumbs >
153
+ < Typography variant = "body2" onClick = { ( ) => navigate ( '/' ) } > Home</ Typography >
154
+ < Typography variant = "body2" onClick = { ( ) => navigate ( '/manage/product' ) } > Manage Products</ Typography >
155
+ </ Breadcrumbs >
156
+ < TextField label = "Search" variant = "outlined" fullWidth onChange = { ( e ) => setSearchQuery ( e . target . value ) } margin = "normal" />
157
+ < DataGrid
158
+ rows = { data }
159
+ columns = { columns }
160
+ rowHeight = { 75 }
161
+ sortingOrder = { [ 'asc' , 'desc' ] }
162
+ sortModel = { ordering }
163
+ onSortModelChange = { handleSorting }
164
+ paginationMode = "server"
165
+ initialState = { {
166
+ ...data . initialState ,
167
+ pagination :{ paginationModel :paginationModel }
168
+ } }
169
+ pageSizeOptions = { [ 5 , 10 , 20 ] }
170
+ pagination
171
+ rowCount = { totalItems }
172
+ loading = { loading }
173
+ rowSelection = { false }
174
+ onPaginationModelChange = { ( pagedetails ) => {
175
+ setPaginationModel ( {
176
+ page :pagedetails . page ,
177
+ pageSize :pagedetails . pageSize
178
+
179
+ } )
180
+ } }
181
+ slots = {
182
+ {
183
+
184
+ loadingOverlay :LinearProgress ,
185
+ toolbar :GridToolbar ,
186
+
187
+ }
188
+ }
189
+
190
+ />
191
+ < Dialog open = { open } fullWidth = { true } onClose = { handleClose } aria-labelledby = "form-dialog-title" >
192
+ < DialogContent >
193
+ < Typography variant = "h5" mb = { 2 } > { modalTitle } Details </ Typography >
194
+ < Divider />
195
+ {
196
+ jsonData . map ( ( item , index ) => (
197
+ < React . Fragment key = { index } >
198
+ < Typography mt = { 2 } > < Circle sx = { { fontSize :'12px' , marginRight :'10px' } } /> { item . key } - { item . value } </ Typography >
199
+ < Divider />
200
+ </ React . Fragment >
201
+ ) )
202
+ }
203
+ </ DialogContent >
204
+ </ Dialog >
205
+ < Dialog open = { openHtml } fullWidth = { true } onClose = { handleClose2 } aria-labelledby = "form-dialog-title" >
206
+ < DialogContent >
207
+ < Typography variant = "h5" mb = { 2 } > HTML Description </ Typography >
208
+ < Divider />
209
+ < div dangerouslySetInnerHTML = { { __html :htmldata } } />
210
+ </ DialogContent >
211
+ </ Dialog >
212
+ </ Box >
213
+ )
214
+ }
215
+
216
+ export default ManageProducts ;
0 commit comments