1 | import { useState, useEffect, useContext, useRef, useMemo } from 'react';
|
---|
2 | import moment from 'moment';
|
---|
3 |
|
---|
4 | import SessionGuest from './SessionGuest';
|
---|
5 | import SessionUser from './SessionUser';
|
---|
6 | import Buttons from './Buttons';
|
---|
7 | import AbsoluteLoader from '../../Loaders/AbsoluteLoader';
|
---|
8 | import { IconButton, Slide } from '@mui/material';
|
---|
9 | import Radio from '@mui/material/Radio';
|
---|
10 | import RadioGroup from '@mui/material/RadioGroup';
|
---|
11 | import FormControlLabel from '@mui/material/FormControlLabel';
|
---|
12 | import {
|
---|
13 | Wrapper,
|
---|
14 | ButtonWrapper,
|
---|
15 | ModalContainer,
|
---|
16 | CloseIcon,
|
---|
17 | KeyValueWrapper,
|
---|
18 | Key,
|
---|
19 | Value,
|
---|
20 | PaymentMethodWrapper,
|
---|
21 | PayWithText,
|
---|
22 | PaymentMethodsWrapper,
|
---|
23 | PayButtonWrapper,
|
---|
24 | ModalPayButton,
|
---|
25 | CardDetails,
|
---|
26 | DateAndCCVWrapper,
|
---|
27 | ModalInput,
|
---|
28 | CreditCard,
|
---|
29 | ModalInputCardNumber,
|
---|
30 | } from './styles';
|
---|
31 | import Modal from '@mui/material/Modal';
|
---|
32 | import Backdrop from '@mui/material/Backdrop';
|
---|
33 |
|
---|
34 | import {
|
---|
35 | roles,
|
---|
36 | sessionStatus as enumsSessionStatus,
|
---|
37 | } from '../../../config/enums';
|
---|
38 | import theme from '../../../theme';
|
---|
39 | import { UserContext } from '../../../context/UserContext';
|
---|
40 | import useUserStartSession from '../../../hooks/useUserStartSession';
|
---|
41 | import useForm from '../../../hooks/useForm';
|
---|
42 | import useUserFinishedSession from '../../../hooks/useUserFinishedSession';
|
---|
43 | import useUserPayForSession from '../../../hooks/useUserPayForSession';
|
---|
44 | import useGetSessionOverInfo from '../../../hooks/useGetSessionOverInfo';
|
---|
45 | import useGetData from '../../../hooks/useGetData';
|
---|
46 |
|
---|
47 | import { convertMinutesToString } from '../../../utils/convertMinToString';
|
---|
48 |
|
---|
49 | const normalizeSesionData = session => ({
|
---|
50 | plate: session?.plate?.plate ?? '',
|
---|
51 | zone: session?.parkingZone?.pzName ?? ''
|
---|
52 | });
|
---|
53 |
|
---|
54 | const defaultTime = 15000;
|
---|
55 | const Session = () => {
|
---|
56 | // const [timer, setTimer] = useState(10000);
|
---|
57 | // let timer = 10000;
|
---|
58 | // const timerInterval = setInterval(() => {
|
---|
59 | // console.log('VIKTOR', timer);
|
---|
60 | // // setTimer(defaultTime);
|
---|
61 | // timer = 15000;
|
---|
62 | // }, timer);
|
---|
63 | // useEffect(() => {
|
---|
64 | // return () => {
|
---|
65 | // clearInterval(timerInterval);
|
---|
66 | // }
|
---|
67 | // })
|
---|
68 | const { data: fetchedSelectZones, isLoading: isLoadingSelectZones } =
|
---|
69 | useGetData({ url: '/parkingZone/parkingZoneNames' });
|
---|
70 | const { user } = useContext(UserContext);
|
---|
71 | const [isModalOpen, setModalOpen] = useState(false);
|
---|
72 | const [paymentMethod, setPaymentMethod] = useState('');
|
---|
73 | const [cardNumber, setCardNumber] = useState('');
|
---|
74 | const [cardExpDate, setCardExpDate] = useState('');
|
---|
75 | const [cardCCV, setCardCCV] = useState('');
|
---|
76 | const { data: session, isLoading: isLoadingSession, setData: setSession } = useGetData({
|
---|
77 | url: '/parkingSession',
|
---|
78 | });
|
---|
79 | console.log('SESSION', session);
|
---|
80 | const {
|
---|
81 | data: userSessionInfo,
|
---|
82 | onFormChange: onFormChangeUserSessionInfo,
|
---|
83 | setNewData: setNewUserSessionData,
|
---|
84 | } = useForm({
|
---|
85 | plate: 'NONE',
|
---|
86 | zone: 'NONE',
|
---|
87 | });
|
---|
88 | const { userFinishedSession } = useUserFinishedSession();
|
---|
89 | const timerRef = useRef(0);
|
---|
90 | const { userStartSession } = useUserStartSession();
|
---|
91 | const { userPayForSession, isLoading: isLoadingPayForSession } =
|
---|
92 | useUserPayForSession();
|
---|
93 | const {
|
---|
94 | getSessionInfoOver,
|
---|
95 | isLoading: isLoadingSessionInfoOver,
|
---|
96 | totalPrice,
|
---|
97 | } = useGetSessionOverInfo();
|
---|
98 | const cardNumberHandler = (e) => {
|
---|
99 | const newVal = e.target.value.replace(/\s+/g, '');
|
---|
100 | let parts = [];
|
---|
101 | for (let i = 0; i < newVal.length; i += 4) {
|
---|
102 | parts.push(newVal.substring(i, i + 4));
|
---|
103 | }
|
---|
104 | console.log(parts);
|
---|
105 | if (parts.length) {
|
---|
106 | setCardNumber(parts.join(' '));
|
---|
107 | } else {
|
---|
108 | setCardNumber(newVal);
|
---|
109 | }
|
---|
110 | };
|
---|
111 |
|
---|
112 | const cardExpDateHandler = (e) => {
|
---|
113 | const newVal = e.target.value.replace(/[^0-9]/, '');
|
---|
114 | let first = newVal.substring(0, 2);
|
---|
115 | let second = newVal.substring(2, 4);
|
---|
116 | if (second !== '') {
|
---|
117 | setCardExpDate([first, second].join('/'));
|
---|
118 | } else {
|
---|
119 | setCardExpDate(newVal);
|
---|
120 | }
|
---|
121 | };
|
---|
122 |
|
---|
123 | const handleStartSession = () => {
|
---|
124 | userStartSession({ sessionData: userSessionInfo, setSession });
|
---|
125 | };
|
---|
126 |
|
---|
127 | const handleEndSession = () => {
|
---|
128 | userFinishedSession({ setSession });
|
---|
129 | };
|
---|
130 |
|
---|
131 | const handlePayForSession = () => {
|
---|
132 | if (paymentMethod) {
|
---|
133 | if (
|
---|
134 | paymentMethod === 'card' &&
|
---|
135 | (cardNumber === '' || cardCCV === '' || cardExpDate === '')
|
---|
136 | ) {
|
---|
137 | return;
|
---|
138 | }
|
---|
139 | let paymentCredentials = null;
|
---|
140 | if (paymentMethod === 'card') {
|
---|
141 | paymentCredentials = {
|
---|
142 | cardNumber: cardNumber,
|
---|
143 | cardExpDate: cardExpDate,
|
---|
144 | cardCCV: cardCCV,
|
---|
145 | };
|
---|
146 | }
|
---|
147 | userPayForSession({
|
---|
148 | method: paymentMethod,
|
---|
149 | paymentCredentials,
|
---|
150 | });
|
---|
151 | }
|
---|
152 | };
|
---|
153 |
|
---|
154 | const checkForDoubleClick = (e) => {
|
---|
155 | timerRef.current++;
|
---|
156 | setTimeout(() => {
|
---|
157 | if (timerRef.current !== 0) {
|
---|
158 | timerRef.current = 0;
|
---|
159 | }
|
---|
160 | }, 500);
|
---|
161 | if (timerRef.current >= 2) {
|
---|
162 | timerRef.current = 0;
|
---|
163 | if (!session) {
|
---|
164 | handleStartSession();
|
---|
165 | } else if (
|
---|
166 | session.status === enumsSessionStatus.active ||
|
---|
167 | session.status === enumsSessionStatus.idle
|
---|
168 | ) {
|
---|
169 | handleEndSession();
|
---|
170 | }
|
---|
171 | }
|
---|
172 | };
|
---|
173 |
|
---|
174 | const handlePayButton = () => {
|
---|
175 | setModalOpen(true);
|
---|
176 | if (totalPrice) return; // don't send request if they are already set
|
---|
177 | getSessionInfoOver();
|
---|
178 | };
|
---|
179 |
|
---|
180 | useEffect(() => {
|
---|
181 | if(session) {
|
---|
182 | setNewUserSessionData(normalizeSesionData(session));
|
---|
183 | }
|
---|
184 | }, [session])
|
---|
185 |
|
---|
186 | const totalTime = useMemo(() => {
|
---|
187 | if(session?.timeEnd && session?.timeStart) {
|
---|
188 | const start = moment(session.timeStart);
|
---|
189 | const end = moment(session.timeEnd);
|
---|
190 | const diffMin = Math.round(end.diff(start) / 60000);
|
---|
191 | return convertMinutesToString(diffMin);
|
---|
192 | }
|
---|
193 | return null;
|
---|
194 | }, [session])
|
---|
195 |
|
---|
196 | return (
|
---|
197 | <>
|
---|
198 | <Modal
|
---|
199 | open={isModalOpen}
|
---|
200 | onClose={() => {
|
---|
201 | setModalOpen(false);
|
---|
202 | }}
|
---|
203 | closeAfterTransition
|
---|
204 | BackdropComponent={Backdrop}
|
---|
205 | BackdropProps={{
|
---|
206 | timeout: 500,
|
---|
207 | }}
|
---|
208 | style={{
|
---|
209 | display: 'flex',
|
---|
210 | alignItems: 'center',
|
---|
211 | justifyContent: 'center',
|
---|
212 | }}
|
---|
213 | >
|
---|
214 | <Slide in={isModalOpen}>
|
---|
215 | <ModalContainer>
|
---|
216 | <IconButton
|
---|
217 | style={{
|
---|
218 | marginLeft: 295,
|
---|
219 | }}
|
---|
220 | onClick={() => {
|
---|
221 | setModalOpen(false);
|
---|
222 | }}
|
---|
223 | >
|
---|
224 | <CloseIcon />
|
---|
225 | </IconButton>
|
---|
226 | {isLoadingSessionInfoOver ? ( // TODO FETCH SESSION DATA
|
---|
227 | <AbsoluteLoader
|
---|
228 | containerStyle={{
|
---|
229 | width: '200px',
|
---|
230 | height: '200px',
|
---|
231 | margin: 'auto',
|
---|
232 | marginTop: '50px',
|
---|
233 | }}
|
---|
234 | />
|
---|
235 | ) : (
|
---|
236 | <>
|
---|
237 | <KeyValueWrapper>
|
---|
238 | <Key>Време:</Key>
|
---|
239 | <Value>{totalTime}</Value>
|
---|
240 | </KeyValueWrapper>
|
---|
241 | <KeyValueWrapper>
|
---|
242 | <Key>Вкупна сума:</Key>
|
---|
243 | <Value>{totalPrice} ден.</Value>
|
---|
244 | </KeyValueWrapper>
|
---|
245 | <PaymentMethodWrapper>
|
---|
246 | <PayWithText>Плати со:</PayWithText>
|
---|
247 | <PaymentMethodsWrapper>
|
---|
248 | <RadioGroup
|
---|
249 | aria-label='payment-methods'
|
---|
250 | name='payment-method'
|
---|
251 | value={paymentMethod}
|
---|
252 | onChange={(e) =>
|
---|
253 | setPaymentMethod(e.target.value)
|
---|
254 | }
|
---|
255 | >
|
---|
256 | <FormControlLabel
|
---|
257 | value='mobile'
|
---|
258 | control={
|
---|
259 | <Radio
|
---|
260 | sx={{
|
---|
261 | color: theme.palette
|
---|
262 | .primary.main,
|
---|
263 | '&.Mui-checked': {
|
---|
264 | color: theme
|
---|
265 | .palette
|
---|
266 | .primary
|
---|
267 | .main,
|
---|
268 | },
|
---|
269 | }}
|
---|
270 | />
|
---|
271 | }
|
---|
272 | label='Мобилен'
|
---|
273 | labelPlacement='start'
|
---|
274 | />
|
---|
275 | <FormControlLabel
|
---|
276 | value='card'
|
---|
277 | control={
|
---|
278 | <Radio
|
---|
279 | sx={{
|
---|
280 | color: theme.palette
|
---|
281 | .primary.main,
|
---|
282 | '&.Mui-checked': {
|
---|
283 | color: theme
|
---|
284 | .palette
|
---|
285 | .primary
|
---|
286 | .main,
|
---|
287 | },
|
---|
288 | }}
|
---|
289 | />
|
---|
290 | }
|
---|
291 | label='Картичка'
|
---|
292 | labelPlacement='start'
|
---|
293 | />
|
---|
294 | </RadioGroup>
|
---|
295 | </PaymentMethodsWrapper>
|
---|
296 | </PaymentMethodWrapper>
|
---|
297 | {paymentMethod === 'card' ? (
|
---|
298 | <CardDetails>
|
---|
299 | <ModalInputCardNumber
|
---|
300 | InputProps={{
|
---|
301 | startAdornment: <CreditCard />,
|
---|
302 | }}
|
---|
303 | onChange={cardNumberHandler}
|
---|
304 | value={cardNumber}
|
---|
305 | />
|
---|
306 | <DateAndCCVWrapper>
|
---|
307 | <ModalInput
|
---|
308 | InputProps={{
|
---|
309 | placeholder: 'Exp: 11/21',
|
---|
310 | }}
|
---|
311 | style={{
|
---|
312 | width: '45%',
|
---|
313 | }}
|
---|
314 | onChange={cardExpDateHandler}
|
---|
315 | value={cardExpDate}
|
---|
316 | />
|
---|
317 | <ModalInput
|
---|
318 | InputProps={{
|
---|
319 | placeholder: 'CCV',
|
---|
320 | }}
|
---|
321 | style={{ width: '35%' }}
|
---|
322 | value={cardCCV}
|
---|
323 | onChange={(e) =>
|
---|
324 | setCardCCV(e.target.value)
|
---|
325 | }
|
---|
326 | />
|
---|
327 | </DateAndCCVWrapper>
|
---|
328 | </CardDetails>
|
---|
329 | ) : null}
|
---|
330 | <PayButtonWrapper>
|
---|
331 | {isLoadingPayForSession ? (
|
---|
332 | <AbsoluteLoader
|
---|
333 | containerStyle={{
|
---|
334 | width: '51px',
|
---|
335 | height: '51px',
|
---|
336 | margin: 'auto',
|
---|
337 | }}
|
---|
338 | />
|
---|
339 | ) : (
|
---|
340 | <ModalPayButton
|
---|
341 | onClick={handlePayForSession}
|
---|
342 | >
|
---|
343 | Плати
|
---|
344 | </ModalPayButton>
|
---|
345 | )}
|
---|
346 | </PayButtonWrapper>
|
---|
347 | </>
|
---|
348 | )}
|
---|
349 | </ModalContainer>
|
---|
350 | </Slide>
|
---|
351 | </Modal>
|
---|
352 | {!isLoadingSession && (
|
---|
353 | <Wrapper>
|
---|
354 | {user.role === roles.user ? (
|
---|
355 | <SessionUser
|
---|
356 | sessionStatus={session?.status ?? null}
|
---|
357 | sessionInfo={normalizeSesionData(session)}
|
---|
358 | zones={fetchedSelectZones ?? []}
|
---|
359 | data={userSessionInfo}
|
---|
360 | onFormChange={onFormChangeUserSessionInfo}
|
---|
361 | setNewData={setNewUserSessionData}
|
---|
362 | />
|
---|
363 | ) : (
|
---|
364 | <SessionGuest
|
---|
365 | sessionStatus={session?.status ?? null}
|
---|
366 | sessionInfo={normalizeSesionData(session)}
|
---|
367 | zones={fetchedSelectZones ?? []}
|
---|
368 | data={userSessionInfo}
|
---|
369 | onFormChange={onFormChangeUserSessionInfo}
|
---|
370 | setNewData={setNewUserSessionData}
|
---|
371 | />
|
---|
372 | )}
|
---|
373 | <ButtonWrapper>
|
---|
374 | <Buttons
|
---|
375 | status={session?.status ?? null}
|
---|
376 | handlePayButton={handlePayButton}
|
---|
377 | onClick={checkForDoubleClick}
|
---|
378 | />
|
---|
379 | </ButtonWrapper>
|
---|
380 | </Wrapper>
|
---|
381 | )}
|
---|
382 | </>
|
---|
383 | );
|
---|
384 | };
|
---|
385 |
|
---|
386 | export default Session;
|
---|