@campxdev/shared 0.6.18 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/package.json +2 -1
  2. package/src/components/DrawerWrapper/DialogWrapper.tsx +6 -2
  3. package/src/components/Layout/Header/AppHeader.tsx +2 -2
  4. package/src/components/Layout/Header/HelpWidget/HelpWidget.tsx +298 -0
  5. package/src/components/Layout/Header/HelpWidget/styles.tsx +92 -0
  6. package/src/components/Layout/Header/UserBox.tsx +23 -3
  7. package/src/components/Layout/Header/assets/background.png +0 -0
  8. package/src/components/Layout/Header/assets/campx.png +0 -0
  9. package/src/components/Layout/Header/assets/{newAssets/campx_square_small.svg → campx_square_small.svg} +0 -0
  10. package/src/components/Layout/Header/assets/{newAssets/commuteX.png → commuteX.png} +0 -0
  11. package/src/components/Layout/Header/assets/{newAssets/commutex.png → commutex.png} +0 -0
  12. package/src/components/Layout/Header/assets/{newAssets/commutex.svg → commutex.svg} +0 -0
  13. package/src/components/Layout/Header/assets/{newAssets/commutexSmall.svg → commutexSmall.svg} +0 -0
  14. package/src/components/Layout/Header/assets/contactBg.png +0 -0
  15. package/src/components/Layout/Header/assets/{newAssets/enroll.svg → enroll.svg} +0 -0
  16. package/src/components/Layout/Header/assets/{newAssets/enrollx.svg → enrollx.svg} +0 -0
  17. package/src/components/Layout/Header/assets/{newAssets/entrollx.png → entrollx.png} +0 -0
  18. package/src/components/Layout/Header/assets/{newAssets/exams_small.svg → exams_small.svg} +0 -0
  19. package/src/components/Layout/Header/assets/{newAssets/examsx.svg → examsx.svg} +0 -0
  20. package/src/components/Layout/Header/assets/examx.png +0 -0
  21. package/src/components/Layout/Header/assets/{newAssets/hostel_small.svg → hostel_small.svg} +0 -0
  22. package/src/components/Layout/Header/assets/hostelx.png +0 -0
  23. package/src/components/Layout/Header/assets/{newAssets/hostelx.svg → hostelx.svg} +0 -0
  24. package/src/components/Layout/Header/assets/index.ts +18 -17
  25. package/src/components/Layout/Header/assets/{newAssets/libraryx.svg → libraryx.svg} +0 -0
  26. package/src/components/Layout/Header/assets/{newAssets/libreryx.png → libreryx.png} +0 -0
  27. package/src/components/Layout/Header/assets/{newAssets/pay_small.svg → pay_small.svg} +0 -0
  28. package/src/components/Layout/Header/assets/payx.png +0 -0
  29. package/src/components/Layout/Header/assets/{newAssets/payx.svg → payx.svg} +0 -0
  30. package/src/components/Layout/Header/assets/{newAssets/people_small.svg → people_small.svg} +0 -0
  31. package/src/components/Layout/Header/assets/{newAssets/peoplex.svg → peoplex.svg} +0 -0
  32. package/src/components/Layout/Header/assets/{newAssets/pepolex.png → pepolex.png} +0 -0
  33. package/src/components/Layout/Header/assets/{newAssets/squarex.svg → squarex.svg} +0 -0
  34. package/src/components/Layout/Tickets/MyTickets.tsx +74 -0
  35. package/src/components/Layout/Tickets/Services.tsx +6 -0
  36. package/src/components/Layout/Tickets/TicketDetails.tsx +66 -0
  37. package/src/components/Layout/Tickets/TimeLine.tsx +64 -0
  38. package/src/components/Layout/Tickets/index.tsx +1 -0
  39. package/src/components/Layout/Tickets/styles.tsx +136 -0
  40. package/src/components/ListItemButton.tsx +2 -1
  41. package/src/components/ModalButtons/DialogButton.tsx +1 -1
  42. package/src/components/SideNav.tsx +1 -1
  43. package/src/hooks/useAuth.ts +1 -0
  44. package/src/components/Layout/Header/FreshDeskHelpButton.tsx +0 -19
  45. package/src/components/Layout/Header/assets/campx.svg +0 -29
  46. package/src/components/Layout/Header/assets/collegex.png +0 -0
  47. package/src/components/Layout/Header/assets/enrollx.png +0 -0
  48. package/src/components/Layout/Header/assets/newAssets/campx.png +0 -0
  49. package/src/components/Layout/Header/assets/newAssets/examx.png +0 -0
  50. package/src/components/Layout/Header/assets/newAssets/hostelx.png +0 -0
  51. package/src/components/Layout/Header/assets/newAssets/payx.png +0 -0
  52. package/src/components/Layout/Header/assets/newexamx.png +0 -0
  53. package/src/components/Layout/Header/assets/newpayx.png +0 -0
  54. package/src/components/Layout/Header/assets/payxHeader.svg +0 -21
  55. package/src/components/Layout/Header/assets/peoplex.png +0 -0
  56. package/src/components/Layout/Header/assets/peoplexHeader.svg +0 -14
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@campxdev/shared",
3
- "version": "0.6.18",
3
+ "version": "1.0.0",
4
4
  "main": "./exports.ts",
5
5
  "scripts": {
6
6
  "start": "react-scripts start",
@@ -30,6 +30,7 @@
30
30
  "@emotion/styled": "^11.8.1",
31
31
  "@hookform/resolvers": "^2.9.10",
32
32
  "@mui/icons-material": "^5.6.2",
33
+ "@mui/lab": "^5.0.0-alpha.112",
33
34
  "@mui/material": "^5.7.0",
34
35
  "@mui/x-date-pickers": "^5.0.0-alpha.3",
35
36
  "axios": "^0.27.2",
@@ -35,10 +35,14 @@ export default function DialogWrapper({
35
35
  return (
36
36
  <Dialog
37
37
  fullWidth
38
- maxWidth="md"
39
38
  sx={{
40
39
  zIndex: 500,
41
40
  minHeight: '70vh',
41
+ '& .MuiDialog-container': {
42
+ '& .MuiPaper-root': {
43
+ maxWidth: '1420px',
44
+ },
45
+ },
42
46
  }}
43
47
  onClose={onClose}
44
48
  open={open}
@@ -55,7 +59,7 @@ export default function DialogWrapper({
55
59
  <Close />
56
60
  </IconButton>
57
61
  </StyledDialogHeader>
58
- <DialogContent sx={{ padding: '20px' }}>
62
+ <DialogContent sx={{ padding: '0' }}>
59
63
  <>{children}</>
60
64
  </DialogContent>
61
65
  </Dialog>
@@ -15,7 +15,7 @@ import {
15
15
  } from './assets'
16
16
 
17
17
  import CogWheelMenu from './CogWheelMenu'
18
- import FreshDeskHelpButton from './FreshDeskHelpButton'
18
+ import HelpWidget from './HelpWidget/HelpWidget'
19
19
  import Notification from './Notification'
20
20
  import { StyledHeader, StyledImageWrapper } from './styles'
21
21
  import UserBox from './UserBox'
@@ -75,7 +75,7 @@ export default function AppHeader({
75
75
  <AppLogo clientLogo={clientLogo} />
76
76
  </Box>
77
77
  <Box className="actions">
78
- <FreshDeskHelpButton />
78
+ <HelpWidget />
79
79
  {/* <Notification /> */}
80
80
  {cogWheelMenu?.length ? <CogWheelMenu menu={cogWheelMenu} /> : null}
81
81
  <UserBox
@@ -0,0 +1,298 @@
1
+ import { yupResolver } from '@hookform/resolvers/yup'
2
+ import {
3
+ ArrowBackIosNew,
4
+ ArrowForwardIos,
5
+ Close,
6
+ HelpOutline,
7
+ NotesSharp,
8
+ } from '@mui/icons-material'
9
+ import {
10
+ Box,
11
+ Button,
12
+ Card,
13
+ DialogContent,
14
+ IconButton,
15
+ Stack,
16
+ Typography,
17
+ } from '@mui/material'
18
+ import { AxiosRequestConfig } from 'axios'
19
+ import { useState } from 'react'
20
+ import { useForm } from 'react-hook-form'
21
+ import { useQuery } from 'react-query'
22
+ import { toast } from 'react-toastify'
23
+ import axios, { axiosErrorToast } from '../../../../config/axios'
24
+ import { queryClient } from '../../../../contexts/QueryClientProvider'
25
+ import { FormSingleSelect, FormTextField } from '../../../HookForm'
26
+ import ImageUpload from '../../../ImageUpload'
27
+ import MediaRow from '../../../MediaRow'
28
+ import * as yup from 'yup'
29
+ import Spinner from '../../../Spinner'
30
+ import { Media } from '../../../UploadButton/types'
31
+ import {
32
+ StyledCard,
33
+ StyledContactBoxHeader,
34
+ StyledContactHeader,
35
+ StyledDialog,
36
+ StyledDialogCard,
37
+ StyledDialogHeader,
38
+ } from './styles'
39
+ const schema = yup.object().shape({
40
+ name: yup.string().required('Name is required'),
41
+ subject: yup.string().required('Subject is required'),
42
+ description: yup.string().required('Description is required'),
43
+ categoryId: yup.string().required('Category is required'),
44
+ serviceId: yup.string().required('Service is required'),
45
+ })
46
+ const HelpWidget = () => {
47
+ const [open, setOpen] = useState(false)
48
+ const { control, handleSubmit, watch, reset } = useForm({
49
+ resolver: yupResolver(schema),
50
+ })
51
+ const [state, setState] = useState(0)
52
+ const { data: ticketCategories, isLoading } = useQuery(
53
+ 'ticketCategories',
54
+ () => axios.get(`/service-tickets/categories`).then((res) => res.data),
55
+ )
56
+ // console.log(ticketCategories)
57
+ const [uploadMedia, setUploadMedia] = useState<Media[]>([])
58
+
59
+ const handleClickOpen = () => {
60
+ setOpen(true)
61
+ setState(0)
62
+ }
63
+ const handleClose = () => {
64
+ setOpen(false)
65
+ reset()
66
+ }
67
+ const handleUploadImageChange = (v) => {
68
+ setUploadMedia([
69
+ ...uploadMedia,
70
+ { type: 'image', url: v.url, key: v.key, id: v.id },
71
+ ])
72
+ }
73
+
74
+ const handleUploadDeleteImage = (key) => {
75
+ setUploadMedia((prev) => prev.filter((m) => m.key !== key))
76
+ }
77
+
78
+ const onSubmit = async (formData) => {
79
+ const config: AxiosRequestConfig = {
80
+ method: 'POST',
81
+ url: '/service-tickets',
82
+ data: {
83
+ issueFiles: [uploadMedia[0]?.key],
84
+ ...formData,
85
+ },
86
+ }
87
+
88
+ try {
89
+ await axios(config)
90
+ queryClient.invalidateQueries('ticketCategories')
91
+ toast.success('Ticket Created Successfully')
92
+ handleClose()
93
+ reset()
94
+ setUploadMedia([])
95
+ } catch (error) {
96
+ axiosErrorToast(error)
97
+ }
98
+ }
99
+ if (isLoading) return <Spinner />
100
+
101
+ return (
102
+ <div>
103
+ <StyledDialog
104
+ fullWidth
105
+ onClose={handleClose}
106
+ open={open}
107
+ PaperProps={{
108
+ sx: {
109
+ borderRadius: '10px',
110
+ },
111
+ }}
112
+ >
113
+ {state == 0 ? (
114
+ <>
115
+ <StyledDialogHeader>
116
+ <IconButton onClick={handleClose}>
117
+ <Close sx={{ position: 'absolute', color: 'white', top: 5 }} />
118
+ </IconButton>
119
+ </StyledDialogHeader>
120
+ <DialogContent sx={{ padding: '0' }}>
121
+ <Box>
122
+ <StyledCard>
123
+ <Box
124
+ sx={{ display: 'flex', gap: '10px', alignItems: 'center' }}
125
+ >
126
+ <NotesSharp />
127
+ <Typography variant="h5" sx={{ fontSize: '14px' }}>
128
+ Knowledge Base
129
+ </Typography>
130
+ </Box>
131
+ <ArrowForwardIos sx={{ width: '15px', color: 'blue' }} />
132
+ </StyledCard>
133
+ </Box>
134
+ <Box
135
+ sx={{
136
+ padding: '15px 20px 20px 20px',
137
+ }}
138
+ >
139
+ <Card
140
+ sx={{
141
+ boxShadow: '0px 3px 15px #0000001A',
142
+ padding: '20px 15px',
143
+ marginTop: '30px',
144
+ }}
145
+ >
146
+ <Stack gap={1}>
147
+ <Typography variant="h3">Want to get in touch?</Typography>
148
+ <Typography variant="subtitle2" sx={{ maxWidth: '290px' }}>
149
+ We’re standing by to answer all of your questions right
150
+ now.
151
+ </Typography>
152
+ </Stack>
153
+ <Button
154
+ fullWidth
155
+ sx={{
156
+ borderRadius: '8px',
157
+ marginTop: '15px',
158
+ height: '50px',
159
+ }}
160
+ onClick={() => setState(1)}
161
+ >
162
+ Contact Us
163
+ </Button>
164
+ </Card>
165
+ </Box>
166
+ </DialogContent>
167
+ </>
168
+ ) : (
169
+ <>
170
+ <Box>
171
+ <StyledContactHeader>
172
+ <StyledContactBoxHeader onClick={() => setState(0)}>
173
+ <ArrowBackIosNew sx={{ fontSize: 'small', color: 'white' }} />
174
+ <Typography sx={{ color: 'white' }} variant="h3">
175
+ Contact Us
176
+ </Typography>
177
+ </StyledContactBoxHeader>
178
+ <IconButton onClick={handleClose}>
179
+ <Close
180
+ sx={{
181
+ position: 'absolute',
182
+ color: 'white',
183
+ top: 5,
184
+ right: 2,
185
+ }}
186
+ />
187
+ </IconButton>
188
+ </StyledContactHeader>
189
+ <DialogContent sx={{ height: '500px' }}>
190
+ <StyledDialogCard>
191
+ <form onSubmit={handleSubmit(onSubmit)}>
192
+ <Stack gap={'20px'}>
193
+ <FormTextField
194
+ label={'Your Name'}
195
+ name={'name'}
196
+ control={control}
197
+ />
198
+ <FormTextField
199
+ label={'Subject'}
200
+ name={'subject'}
201
+ control={control}
202
+ />
203
+ <FormTextField
204
+ label={'Description'}
205
+ name={'description'}
206
+ control={control}
207
+ multiline
208
+ rows={5}
209
+ required
210
+ />
211
+ <FormSingleSelect
212
+ label={'Category'}
213
+ name={'categoryId'}
214
+ control={control}
215
+ options={ticketCategories?.map((item) => {
216
+ return { label: item.name, value: item._id }
217
+ })}
218
+ // onChange={(value) => {
219
+ // mutate({ id: value })
220
+ // }}
221
+ required
222
+ />
223
+ <FormSingleSelect
224
+ label={'Service'}
225
+ name={'serviceId'}
226
+ control={control}
227
+ options={
228
+ ticketCategories
229
+ ?.find((item) => item?._id === watch('categoryId'))
230
+ ?.services?.map((item) => ({
231
+ label: item.name,
232
+ value: item._id,
233
+ })) ?? []
234
+ }
235
+ required
236
+ />
237
+
238
+ {/* <StyledContactCard>
239
+ <Screenshot />
240
+ <Typography sx={{ fontSize: '12px' }} variant="h5">
241
+ Take screenshot
242
+ </Typography>
243
+ </StyledContactCard> */}
244
+ {/* <StyledContactCard
245
+ sx={{
246
+ minHeight: '120px',
247
+ flexDirection: 'column',
248
+ border: '2px dashed #0000001A',
249
+ }}
250
+ > */}
251
+ {/* <Upload />
252
+ <Typography sx={{ fontSize: '12px' }} variant="h5">
253
+ Upload files (max 5)
254
+ </Typography>
255
+ <Typography variant="h4" sx={{ fontSize: '10px' }}>
256
+ Click to add or drag & drop files
257
+ </Typography> */}
258
+ {/* category id , service id and priority is required */}
259
+ {!uploadMedia?.length ? (
260
+ <ImageUpload
261
+ onFileUploaded={handleUploadImageChange}
262
+ postUrl="/tickets/upload-issue-file"
263
+ // postUrl="/"
264
+ />
265
+ ) : (
266
+ <MediaRow
267
+ list={uploadMedia}
268
+ onDelete={handleUploadDeleteImage}
269
+ />
270
+ )}
271
+ {/* </StyledContactCard> */}
272
+ <Button
273
+ type="submit"
274
+ fullWidth
275
+ sx={{
276
+ height: '60px',
277
+ borderRadius: '10px',
278
+ fontSize: '18px',
279
+ }}
280
+ >
281
+ Send
282
+ </Button>
283
+ </Stack>
284
+ </form>
285
+ </StyledDialogCard>
286
+ </DialogContent>
287
+ </Box>
288
+ </>
289
+ )}
290
+ </StyledDialog>
291
+
292
+ <IconButton color="secondary">
293
+ <HelpOutline onClick={handleClickOpen} />
294
+ </IconButton>
295
+ </div>
296
+ )
297
+ }
298
+ export default HelpWidget
@@ -0,0 +1,92 @@
1
+ import { alpha, Box, Card, Dialog, styled } from '@mui/material'
2
+ import { background, contactBg } from '../assets'
3
+ // import background from '../../Header/assets/background.png'
4
+ export const StyledDialogHeader = styled(Box)(({ theme }) => ({
5
+ height: '180px',
6
+ backgroundColor: alpha(theme.palette.text.secondary, 0.1),
7
+ backgroundImage: `url(${background})`,
8
+ backgroundSize: 'cover',
9
+ display: 'flex',
10
+ alignItems: 'start',
11
+ justifyContent: 'flex-end',
12
+ padding: '0.6rem 1rem',
13
+ }))
14
+ export const StyledDialog = styled(Dialog)(() => ({
15
+ zIndex: 500,
16
+ transition: 'max-height 0.3s ease-in-out',
17
+ '& .MuiDialog-container': {
18
+ justifyContent: 'flex-end',
19
+ alignItems: 'end',
20
+
21
+ '& .MuiPaper-root': {
22
+ maxWidth: '380px',
23
+ },
24
+ },
25
+ }))
26
+ export const StyledCard = styled(Card)(() => ({
27
+ display: 'flex',
28
+ position: 'absolute',
29
+ width: '340px',
30
+ justifyContent: 'space-between',
31
+ margin: '-30px 20px 0 20px',
32
+ padding: '20px 15px',
33
+ cursor: 'pointer',
34
+ boxShadow: '0px 3px 15px #0000001A',
35
+ }))
36
+
37
+ export const StyledContactHeader = styled(Box)(({ theme }) => ({
38
+ height: '170px',
39
+ backgroundColor: alpha(theme.palette.text.secondary, 0.1),
40
+ backgroundImage: `url(${contactBg})`,
41
+ backgroundSize: 'cover',
42
+ display: 'flex',
43
+ alignItems: 'start',
44
+ justifyContent: 'space-between',
45
+ padding: '0.6rem 1rem',
46
+ }))
47
+
48
+ // export const StyledContact = styled(Dialog)(() => ({
49
+ // zIndex: 500,
50
+ // height: '950px',
51
+ // '& .MuiDialog-container': {
52
+ // bottom: 0,
53
+ // justifyContent: 'flex-end',
54
+ // alignItems: 'end',
55
+ // '& .MuiPaper-root': {
56
+ // maxWidth: '380px',
57
+ // },
58
+ // },
59
+ // }))
60
+
61
+ export const StyledContactCard = styled(Card)(() => ({
62
+ minHeight: '50px',
63
+ display: 'flex',
64
+ justifyContent: 'center',
65
+ alignItems: 'center',
66
+ padding: '10px',
67
+ cursor: 'pointer',
68
+ border: '1px solid #0000001A',
69
+ backgroundColor: '#cfbdbd1a',
70
+ }))
71
+
72
+ export const StyledDialogCard = styled(Card)(() => ({
73
+ padding: '20px',
74
+ boxShadow: '0px 5px 10px #0000001A',
75
+ maxHeight: '550px',
76
+ overflowY: 'auto',
77
+ '&::-webkit-scrollbar': {
78
+ width: '0px',
79
+ height: '0px',
80
+ },
81
+ marginTop: '-90px',
82
+ marginLeft: '-4px',
83
+ position: 'absolute',
84
+ }))
85
+
86
+ export const StyledContactBoxHeader = styled(Box)(() => ({
87
+ marginTop: '40px',
88
+ display: 'flex',
89
+ alignItems: 'center',
90
+ gap: '5px',
91
+ cursor: 'pointer',
92
+ }))
@@ -6,7 +6,9 @@ import { StyledUser } from './styles'
6
6
  import logout from '../../../utils/logout'
7
7
  import ChangePassword from '../../ChangePassword'
8
8
  import { ExitToAppOutlined, HttpsOutlined } from '@mui/icons-material'
9
-
9
+ import ConfirmationNumberOutlinedIcon from '@mui/icons-material/ConfirmationNumberOutlined'
10
+ import DialogWrapper from '../../DrawerWrapper/DialogWrapper'
11
+ import MyTickets from '../Tickets/MyTickets'
10
12
  export default function UserBox({
11
13
  username,
12
14
  profileIcon,
@@ -17,14 +19,19 @@ export default function UserBox({
17
19
  actions: { label: ReactNode; icon?: ReactNode; onClick: any }[]
18
20
  }) {
19
21
  const [open, setOpen] = useState(false)
20
-
22
+ const [openTicket, setOpenTicket] = useState(false)
21
23
  const handleClickOpen = () => {
22
24
  setOpen(true)
23
25
  }
24
26
  const handleClose = (value: string) => {
25
27
  setOpen(false)
26
28
  }
27
-
29
+ const handleTicketOpen = () => {
30
+ setOpenTicket(true)
31
+ }
32
+ const handleTicketClose = () => {
33
+ setOpenTicket(false)
34
+ }
28
35
  return (
29
36
  <>
30
37
  <MenuButton
@@ -48,6 +55,11 @@ export default function UserBox({
48
55
  }
49
56
  menu={[
50
57
  ...actions,
58
+ {
59
+ label: 'My Tickets',
60
+ icon: <ConfirmationNumberOutlinedIcon />,
61
+ onClick: handleTicketOpen,
62
+ },
51
63
 
52
64
  {
53
65
  label: 'Change Password',
@@ -64,6 +76,14 @@ export default function UserBox({
64
76
  PaperProps: { sx: { top: '64px !important' } },
65
77
  }}
66
78
  />
79
+ <DialogWrapper
80
+ open={openTicket}
81
+ title={'All Tickets'}
82
+ children={<MyTickets />}
83
+ onClose={() => {
84
+ handleTicketClose()
85
+ }}
86
+ />
67
87
  <ChangePassword open={open} onClose={handleClose} />
68
88
  </>
69
89
  )
@@ -1,17 +1,18 @@
1
- import collegex from './newAssets/campx.png'
2
- import enrollx from './newAssets/entrollx.png'
3
- import examx from './newAssets/examx.png'
4
- import payx from './newAssets/payx.png'
5
- import peoplex from './newAssets/pepolex.png'
6
- import campxSquareSmall from './newAssets/campx_square_small.svg'
7
- import examsSmall from './newAssets/exams_small.svg'
8
- import paySmall from './newAssets/pay_small.svg'
9
- import peopleSmall from './newAssets/people_small.svg'
10
- import hostelSmall from './newAssets/hostel_small.svg'
11
- import commuteSmall from './newAssets/commutexSmall.svg'
12
- import commutex from './newAssets/commuteX.png'
13
- import hostelx from './newAssets/hostelx.png'
14
-
1
+ import collegex from './campx.png'
2
+ import enrollx from './entrollx.png'
3
+ import examx from './examx.png'
4
+ import payx from './payx.png'
5
+ import peoplex from './pepolex.png'
6
+ import campxSquareSmall from './campx_square_small.svg'
7
+ import examsSmall from './exams_small.svg'
8
+ import paySmall from './pay_small.svg'
9
+ import peopleSmall from './people_small.svg'
10
+ import hostelSmall from './hostel_small.svg'
11
+ import background from './background.png'
12
+ import contactBg from './contactBg.png'
13
+ import commuteSmall from './commutexSmall.svg'
14
+ import commutex from './commutex.png'
15
+ import hostelx from './hostelx.png'
15
16
 
16
17
  export {
17
18
  collegex,
@@ -25,8 +26,8 @@ export {
25
26
  paySmall,
26
27
  peopleSmall,
27
28
  hostelSmall,
29
+ background,
30
+ contactBg,
28
31
  commutex,
29
-
30
- commuteSmall
31
-
32
+ commuteSmall,
32
33
  }
@@ -0,0 +1,74 @@
1
+ import { Box, Typography } from '@mui/material'
2
+ import moment from 'moment'
3
+ import { useState } from 'react'
4
+ import { useQuery } from 'react-query'
5
+ import axios from '../../../config/axios'
6
+ import Spinner from '../../Spinner'
7
+ // import { getImage } from './Services'
8
+ import { StyledCardData, StyledLeftContainer, StyledListItem } from './styles'
9
+ import TicketDetails from './TicketDetails'
10
+
11
+ function MyTickets() {
12
+ const [currentTicket, setCurrentTicket] = useState(null)
13
+ const { data, isLoading } = useQuery<any>('tickets', () =>
14
+ axios.get('/service-tickets/my-tickets').then((res) => res.data.result),
15
+ )
16
+ // const { data: imageData } = useQuery('imageData', () => getImage(data))
17
+ if (isLoading) return <Spinner />
18
+ return (
19
+ <Box sx={{ display: 'flex', gap: '20px' }}>
20
+ <Box sx={{ margin: '10px', borderRadius: '10px' }}>
21
+ <StyledLeftContainer>
22
+ {data?.map((item) => (
23
+ <TicketListItem
24
+ key={item}
25
+ data={item}
26
+ setCurrentTicket={setCurrentTicket}
27
+ currentTicket={currentTicket}
28
+ />
29
+ ))}
30
+ </StyledLeftContainer>
31
+ </Box>
32
+ {currentTicket?._id ? (
33
+ <TicketDetails data={currentTicket} id={currentTicket._id} />
34
+ ) : (
35
+ ''
36
+ )}
37
+ </Box>
38
+ )
39
+ }
40
+
41
+ export default MyTickets
42
+
43
+ const TicketListItem = ({ data, setCurrentTicket, currentTicket }) => {
44
+ return (
45
+ <StyledListItem
46
+ isActive={currentTicket?._id === data?._id ? true : false}
47
+ onClick={() => {
48
+ // set selected ticket data
49
+ setCurrentTicket(data)
50
+ }}
51
+ >
52
+ <Box
53
+ sx={{
54
+ width: '400px',
55
+ display: 'flex',
56
+ }}
57
+ >
58
+ <Box className="left">
59
+ <Typography variant="body2">{data?.name}</Typography>
60
+ <Typography variant="subtitle2">
61
+ {moment(data?.createdAt).format('DD MMMM, YYYY hh:mm: a')}
62
+ </Typography>
63
+ </Box>
64
+ <Box className="right">
65
+ <StyledCardData>
66
+ <Typography variant="h5" sx={{ fontSize: '9px' }}>
67
+ {data?.status.replace('_', ' ')}
68
+ </Typography>
69
+ </StyledCardData>
70
+ </Box>
71
+ </Box>
72
+ </StyledListItem>
73
+ )
74
+ }
@@ -0,0 +1,6 @@
1
+ import axios from '../../../config/axios'
2
+
3
+ export const getImage = async (id: string) => {
4
+ let imageData = await axios.get(`/service-tickets/${id}`)
5
+ return imageData?.data
6
+ }
@@ -0,0 +1,66 @@
1
+ /* eslint-disable react/jsx-key */
2
+ import { Box, Card, Stack, Typography } from '@mui/material'
3
+ import axios from 'axios'
4
+ import moment from 'moment'
5
+ import { useQuery } from 'react-query'
6
+ import { getImage } from './Services'
7
+ import { StyledBoxDetails, StyledCardData } from './styles'
8
+ import StyledTimeLine from './TimeLine'
9
+ // export const getImage = async (id: string) => {
10
+ // let imgData = await axios.get(`/service-tickets/${id}`)
11
+ // return imgData?.data
12
+ // }
13
+ function TicketDetails({ data, id }) {
14
+ const { data: imageData } = useQuery(['imageData', id], () => getImage(id))
15
+ console.log(imageData, 'imagedata')
16
+ return (
17
+ <Box>
18
+ {data ? (
19
+ <Card
20
+ sx={{
21
+ marginTop: '20px',
22
+ }}
23
+ >
24
+ <StyledBoxDetails>
25
+ <Box>
26
+ <Typography variant="h5">{data?.name}</Typography>
27
+ <Typography variant="subtitle2" sx={{ marginTop: '5px' }}>
28
+ {moment(data?.createdAt).format('DD MMMM, YYYY hh:mm: a') ??
29
+ ' '}
30
+ </Typography>
31
+ <Typography
32
+ sx={{ marginTop: '20px', maxWidth: '500px', fontSize: '14px' }}
33
+ >
34
+ {data?.description}
35
+ </Typography>
36
+ <Stack direction={'column'} gap="20px" sx={{ marginTop: '10px' }}>
37
+ {imageData?.issueFiles?.map((item) => (
38
+ <img src={item?.url} height={'100px'} width={'200px'} />
39
+ ))}
40
+ </Stack>
41
+ </Box>
42
+ <StyledCardData
43
+ sx={{
44
+ marginRight: '10px',
45
+ }}
46
+ >
47
+ <Typography variant="h5" sx={{ fontSize: '10px' }}>
48
+ {data.status.replace('_', ' ')}
49
+ </Typography>
50
+ </StyledCardData>
51
+ </StyledBoxDetails>
52
+ </Card>
53
+ ) : (
54
+ ''
55
+ )}
56
+ <Box sx={{ marginTop: '30px', marginBottom: '30px' }}>
57
+ <Typography variant="h1" sx={{ marginBottom: '10px' }}>
58
+ {data?.timelineLogs ? 'Ticket Timeline' : ''}
59
+ </Typography>
60
+ <StyledTimeLine data={data?.timelineLogs} />
61
+ </Box>
62
+ </Box>
63
+ )
64
+ }
65
+
66
+ export default TicketDetails
@@ -0,0 +1,64 @@
1
+ /* eslint-disable react/jsx-key */
2
+ import moment from 'moment'
3
+ import { Typography } from '@mui/material'
4
+ import {
5
+ TimelineSeparator,
6
+ TimelineConnector,
7
+ TimelineDot,
8
+ TimelineContent,
9
+ } from '@mui/lab'
10
+ import { StyledTimelineBox, StyledTimeLineItem } from './styles'
11
+
12
+ interface TimelineComponentProps {
13
+ data: any
14
+ }
15
+
16
+ function StyledTimeLine({ data }: TimelineComponentProps) {
17
+ return data?.map((item, index) => (
18
+ <StyledTimeLineItem key={index}>
19
+ <TimelineSeparator>
20
+ <TimelineDot
21
+ variant="outlined"
22
+ sx={{ width: '20px', height: '20px' }}
23
+ />
24
+ {!(index === data.length - 1) ? <TimelineConnector /> : ''}
25
+ </TimelineSeparator>
26
+ <TimelineContent>
27
+ <Typography variant="h6">{item?.message}</Typography>
28
+ <Typography sx={{ marginTop: '10px' }}>
29
+ {moment(item?.createdAt).format(' h:mmA Do MMMM YYYY, ')}
30
+ </Typography>
31
+ <RenderContent timeLog={item} />
32
+ </TimelineContent>
33
+ </StyledTimeLineItem>
34
+ ))
35
+ }
36
+ export default StyledTimeLine
37
+
38
+ const RenderContent = ({ timeLog }) => {
39
+ if (timeLog?.files) {
40
+ return (
41
+ <StyledTimelineBox>
42
+ <Typography sx={{ marginBottom: '3px' }}>{timeLog?.notes}</Typography>
43
+ {/* {timeLog?.files?.map((item) => (
44
+ <img src={item?.url} height={'100px'} width={'200px'} />
45
+ ))} */}
46
+ </StyledTimelineBox>
47
+ )
48
+ }
49
+
50
+ if (timeLog?.notes) {
51
+ return (
52
+ <StyledTimelineBox
53
+ sx={{
54
+ maxWidth: '400px',
55
+ }}
56
+ >
57
+ <Typography sx={{ wordWrap: 'break-word' }}>
58
+ {timeLog?.notes}
59
+ </Typography>
60
+ </StyledTimelineBox>
61
+ )
62
+ }
63
+ return <></>
64
+ }
@@ -0,0 +1 @@
1
+ export { default } from './MyTickets'
@@ -0,0 +1,136 @@
1
+ import { TimelineItem } from '@mui/lab'
2
+ import { alpha, Box, Card, styled, Typography } from '@mui/material'
3
+
4
+ export const StyledListItem = styled(Box, {
5
+ shouldForwardProp: (prop) => prop !== 'isActive',
6
+ })<{ isActive: boolean }>(({ theme, isActive }) => ({
7
+ maxWidth: '400px',
8
+ height: '85px',
9
+ display: 'flex',
10
+ border: theme.borders.grayLight,
11
+
12
+ alignItems: 'center',
13
+ cursor: 'pointer',
14
+ transition: 'all 0.2s ease',
15
+ ':first-child': {
16
+ borderTopRightRadius: '10px',
17
+ borderTopLeftRadius: '10px',
18
+ },
19
+ '&:hover': {
20
+ background: alpha(theme.palette.secondary.main, 0.02),
21
+ },
22
+
23
+ '& .left': {
24
+ paddingLeft: '10px',
25
+ marginRight: 'auto',
26
+ '& .MuiTypography-root': {
27
+ marginTop: '4px',
28
+ '& > span': {
29
+ color: theme.palette.secondary.main,
30
+ },
31
+ },
32
+ },
33
+ '& .right': {
34
+ paddingRight: '15px',
35
+ display: 'flex',
36
+ },
37
+ '&:before': {
38
+ transition: 'all 0.2s ease',
39
+ content: "''",
40
+ height: '95%',
41
+ width: '4px',
42
+ borderRadius: '2px',
43
+ background: 'transparent',
44
+ ...(isActive && {
45
+ background: theme.palette.common.yellow,
46
+ }),
47
+ },
48
+
49
+ ...(isActive && {
50
+ background: alpha(theme.palette.secondary.main, 0.035),
51
+ }),
52
+ }))
53
+
54
+ export const StyledRemarksContainer = styled(Box)({
55
+ height: '170px',
56
+ borderRadius: '10px',
57
+ border: '1px solid #1212121A',
58
+ marginBottom: '20px ',
59
+ })
60
+ export const StyledLetterBackGround = styled(Box)({
61
+ width: '60px',
62
+ height: '60px',
63
+ display: 'flex',
64
+ backgroundColor: 'black',
65
+ justifyContent: 'center',
66
+ alignItems: 'center',
67
+ })
68
+ export const StyledNamecontainer = styled(Box)({
69
+ display: 'flex',
70
+ gap: '20px',
71
+ alignItems: 'center',
72
+ margin: '25px',
73
+ })
74
+
75
+ export const StyledLetter = ({ letter }) => {
76
+ //letter?.split(' ')[0][0]}${letter?.split(' ')[1][0]
77
+ const value = `${letter?.split(' ')[0][0]}`
78
+
79
+ return (
80
+ <StyledLetterBackGround>
81
+ <Typography variant="h1" sx={{ color: 'white' }}>
82
+ {value.toLocaleUpperCase()}
83
+ </Typography>
84
+ </StyledLetterBackGround>
85
+ )
86
+ }
87
+ export const StyledBox = styled(Box)({
88
+ width: '900px',
89
+ height: 'calc(80vh - 100px)',
90
+ overflowY: 'auto',
91
+ '&::-webkit-scrollbar': {
92
+ width: '0px',
93
+ height: '0px',
94
+ },
95
+ })
96
+
97
+ export const StyledTimelineBox = styled(Box)({
98
+ borderRadius: '10px',
99
+ border: '1px solid #1212121A',
100
+ margin: '20px 0',
101
+ padding: '20px',
102
+ maxWidth: '600px',
103
+ })
104
+
105
+ export const StyledTimeLineItem = styled(TimelineItem)(({ theme }) => ({
106
+ '& .MuiTimelineDot-root': {
107
+ backgroundColor: theme.palette.secondary,
108
+ },
109
+ '&:before': {
110
+ content: 'none',
111
+ },
112
+ }))
113
+
114
+ export const StyledLeftContainer = styled(Box)({
115
+ maxHeight: 'calc(80vh - 50px)',
116
+ // maxHeight: 'calc(80vh - 130px)', 1st default value
117
+ overflowY: 'auto',
118
+ '&::-webkit-scrollbar': {
119
+ width: '0px',
120
+ height: '0px',
121
+ },
122
+ })
123
+
124
+ export const StyledCardData = styled(Card)({
125
+ borderRadius: '4px',
126
+ width: 'auto',
127
+ backgroundColor: '#1E19F51A',
128
+ padding: '6px 10px',
129
+ })
130
+
131
+ export const StyledBoxDetails = styled(Box)({
132
+ display: 'flex',
133
+ justifyContent: 'space-between',
134
+ width: '950px',
135
+ padding: '20px',
136
+ })
@@ -49,6 +49,7 @@ export const StyledListItemButton = styled(MuiListItemButton)<{
49
49
  }>(({ theme, isActive, dropDown = false }) => ({
50
50
  gap: '10px',
51
51
  fontWeight: 'bold',
52
+ padding: '8px 20px',
52
53
  backgroundColor: isActive && '#1d1d1d',
53
54
  '&:hover': {
54
55
  backgroundColor: isActive && '#1d1d1d',
@@ -59,7 +60,7 @@ export const StyledListItemButton = styled(MuiListItemButton)<{
59
60
  height: '100%',
60
61
  left: 0,
61
62
  top: 0,
62
- width: isActive ? '5px' : 0,
63
+ width: isActive ? '6px' : 0,
63
64
  opacity: isActive ? (dropDown ? 0 : 1) : 0,
64
65
  transition: theme.transitions.create(['opacity', 'width']),
65
66
  background: theme.palette.common.yellow,
@@ -51,7 +51,7 @@ export default function DialogButton({
51
51
  const [open, setOpen] = useState(false)
52
52
 
53
53
  const ButtonEl = (props) => (
54
- <Button {...props} {...btnProps}>
54
+ <Button {...props} {...btnProps} sx={{ fontSize: '14px', fontWeight: 600 }}>
55
55
  {btnTxt}
56
56
  </Button>
57
57
  )
@@ -40,7 +40,7 @@ const SideNav = ({
40
40
  }}
41
41
  >
42
42
  {header ? header : null}
43
- <Box>
43
+ <Box sx={{ ':first-child': { marginTop: '25px' } }}>
44
44
  {menuItems.map((item, index) => (
45
45
  <RenderMenuItem key={index} menuItem={item} />
46
46
  ))}
@@ -30,6 +30,7 @@ function useAuth(): {
30
30
 
31
31
  axios
32
32
  .get('/auth/my-permissions')
33
+
33
34
  .then((res) => {
34
35
  console.log(res.data)
35
36
  setLoading(false)
@@ -1,19 +0,0 @@
1
- import { HelpOutline } from '@mui/icons-material'
2
- import { Button, IconButton } from '@mui/material'
3
-
4
- export default function FreshDeskHelpButton() {
5
- const handleOpenFreshDeskWidget = () => {
6
- try {
7
- ;(window as any)?.openFreshDeskWidget()
8
- } catch (error) {
9
- // eslint-disable-next-line no-console
10
- console.error('Error launching Freshdesk')
11
- }
12
- }
13
-
14
- return (
15
- <IconButton color="secondary" onClick={handleOpenFreshDeskWidget}>
16
- <HelpOutline />
17
- </IconButton>
18
- )
19
- }
@@ -1,29 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="231" height="35" viewBox="0 0 231 35">
2
- <defs>
3
- <linearGradient id="linear-gradient" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox">
4
- <stop offset="0" stop-color="#596e79"/>
5
- <stop offset="1" stop-color="#7c909b"/>
6
- </linearGradient>
7
- </defs>
8
- <g id="Group_4457" data-name="Group 4457" transform="translate(-110 -27.5)">
9
- <text id="CAMPX_SQUARE" data-name="CAMPX SQUARE" transform="translate(157 53)" font-size="22" font-family="Nexa-XBold, Nexa" font-weight="700"><tspan x="0" y="0">CAMPX SQUARE</tspan></text>
10
- <g id="Group_4467" data-name="Group 4467">
11
- <g id="Rectangle_8974" data-name="Rectangle 8974" transform="translate(115 27.5)" fill="#fff" stroke="#fff" stroke-width="1">
12
- <rect width="25" height="2" stroke="none"/>
13
- <rect x="0.5" y="0.5" width="24" height="1" fill="none"/>
14
- </g>
15
- <g id="Rectangle_8975" data-name="Rectangle 8975" transform="translate(115 60.5)" fill="#fff" stroke="#fff" stroke-width="1">
16
- <rect width="25" height="2" stroke="none"/>
17
- <rect x="0.5" y="0.5" width="24" height="1" fill="none"/>
18
- </g>
19
- </g>
20
- <g id="Group_4468" data-name="Group 4468" transform="translate(-215 -207.49)">
21
- <g id="Group_4487" data-name="Group 4487" transform="translate(325 234.99)">
22
- <g id="Group_4480" data-name="Group 4480">
23
- <path id="Subtraction_36" data-name="Subtraction 36" d="M35,35H30V34h4V1H30V0H5V1H1V34H5v1H0V0H35V35Z" fill="#121212"/>
24
- </g>
25
- </g>
26
- <path id="Subtraction_37" data-name="Subtraction 37" d="M20,20H0V0H20V20ZM4,4V16H16V4Z" transform="translate(332.5 242.491)" fill="url(#linear-gradient)"/>
27
- </g>
28
- </g>
29
- </svg>
@@ -1,21 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="40" height="40" viewBox="0 0 40 40">
2
- <defs>
3
- <linearGradient id="linear-gradient" x1="0.222" y1="1" x2="0.787" gradientUnits="objectBoundingBox">
4
- <stop offset="0" stop-color="#88b053"/>
5
- <stop offset="1" stop-color="#50840b"/>
6
- </linearGradient>
7
- </defs>
8
- <g id="Group_4498" data-name="Group 4498" transform="translate(-325 -234.99)">
9
- <g id="Group_4464" data-name="Group 4464" transform="translate(336.956 243.562)">
10
- <g id="Group_4461" data-name="Group 4461" transform="translate(0)">
11
- <g id="Group_4460" data-name="Group 4460" transform="translate(0 0)">
12
- <path id="Subtraction_8" data-name="Subtraction 8" d="M5.723,11.749,14.229.041,14.172,0H8.564L2.875,7.829v0L.026,11.747v0h5.7Z" transform="translate(1.858 11.108)" fill="url(#linear-gradient)"/>
13
- <path id="Subtraction_8-2" data-name="Subtraction 8" d="M8.532,0,.026,11.707l.057.041H5.692L11.38,3.92v0L14.229,0V0h-5.7Z" transform="translate(-0.026 0)" fill="url(#linear-gradient)"/>
14
- </g>
15
- </g>
16
- </g>
17
- <g id="Group_4480" data-name="Group 4480" transform="translate(325 234.99)">
18
- <path id="Subtraction_36" data-name="Subtraction 36" d="M40,40H34.286V38.857h4.571V1.143H34.286V0H5.714V1.143H1.143V38.857H5.714V40H0V0H40V40Z" fill="#121212"/>
19
- </g>
20
- </g>
21
- </svg>
@@ -1,14 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="40" height="40" viewBox="0 0 40 40">
2
- <defs>
3
- <linearGradient id="linear-gradient" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox">
4
- <stop offset="0" stop-color="#d0002b"/>
5
- <stop offset="1" stop-color="#ea4a6b"/>
6
- </linearGradient>
7
- </defs>
8
- <g id="Group_4500" data-name="Group 4500" transform="translate(-325 -234.99)">
9
- <path id="Union_5" data-name="Union 5" d="M23.169,22.857,19.574,17.91l-.669.921L21.792,22.8l-.073.053H8.659v0l2.926-4.027-.667-.919L7.322,22.857H0l0,0,3.66-5.038,0,0,7.232-9.955.036.049.022-.03,4.293,5.909,4.307-5.928.036.049.022-.03L30.45,22.8l-.074.053ZM12.2,7.761v0h.183l-.093.128ZM3.63,7.887l-.091-.126,0,0h.183l-.093.128Zm23.243-.024-.076-.1h.04l.074.053-.037.05h0Zm-8.657,0-.076-.1h.04l.073.053-.037.05h0ZM16.574,2.881a2.881,2.881,0,1,1,2.881,2.881A2.881,2.881,0,0,1,16.574,2.881Zm-8.564,0a2.881,2.881,0,1,1,2.881,2.881A2.881,2.881,0,0,1,8.01,2.881Z" transform="translate(329.775 243.534)" fill="url(#linear-gradient)"/>
10
- <g id="Group_4480" data-name="Group 4480" transform="translate(325 234.99)">
11
- <path id="Subtraction_36" data-name="Subtraction 36" d="M40,40H34.286V38.857h4.571V1.143H34.286V0H5.714V1.143H1.143V38.857H5.714V40H0V0H40V40Z" fill="#121212"/>
12
- </g>
13
- </g>
14
- </svg>