[bc20307] | 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;
|
---|