feat: add order-view (#9) #51
| @ -38,6 +38,15 @@ | |||||||
|   "dry-wash.order-create.car-body-select.options.sports-car" : "Sports-car", |   "dry-wash.order-create.car-body-select.options.sports-car" : "Sports-car", | ||||||
|   "dry-wash.order-create.car-body-select.options.other": "Other", |   "dry-wash.order-create.car-body-select.options.other": "Other", | ||||||
|   "dry-wash.order-create.form.submit-button.label": "Submit", |   "dry-wash.order-create.form.submit-button.label": "Submit", | ||||||
|  |   "dry-wash.order-view.title": "Your order", | ||||||
|  |   "dry-wash.order-view.error.title": "Error", | ||||||
|  |   "dry-wash.order-view.fetch.error": "Failed to fetch the details of order #{{number}}", | ||||||
|  |   "dry-wash.order-view.details.title": "Order #{{number}}", | ||||||
|  |   "dry-wash.order-view.details.owner": "Owner", | ||||||
|  |   "dry-wash.order-view.details.car": "Car", | ||||||
|  |   "dry-wash.order-view.details.location": "Where", | ||||||
|  |   "dry-wash.order-view.details.datetime-range": "When", | ||||||
|  |   "dry-wash.order-view.details.alert": "The operator will contact you about the payment at the specified phone number", | ||||||
|   "dry-wash.arm.master.add": "Add", |   "dry-wash.arm.master.add": "Add", | ||||||
|   "dry-wash.arm.order.title": "Orders", |   "dry-wash.arm.order.title": "Orders", | ||||||
|   "dry-wash.arm.order.table.empty": "Table empty", |   "dry-wash.arm.order.table.empty": "Table empty", | ||||||
|  | |||||||
| @ -72,6 +72,15 @@ | |||||||
|   "dry-wash.order-create.car-body-select.options.sports-car": "Спорткар", |   "dry-wash.order-create.car-body-select.options.sports-car": "Спорткар", | ||||||
|   "dry-wash.order-create.car-body-select.options.other": "Другой", |   "dry-wash.order-create.car-body-select.options.other": "Другой", | ||||||
|   "dry-wash.order-create.form.submit-button.label": "Отправить", |   "dry-wash.order-create.form.submit-button.label": "Отправить", | ||||||
|  |   "dry-wash.order-view.title": "Ваш заказ", | ||||||
|  |   "dry-wash.order-view.error.title": "Ошибка", | ||||||
|  |   "dry-wash.order-view.fetch.error": "Не удалось загрузить детали заказа №{{number}}", | ||||||
|  |   "dry-wash.order-view.details.title": "Заказ №{{number}}", | ||||||
|  |   "dry-wash.order-view.details.owner": "Владелец", | ||||||
|  |   "dry-wash.order-view.details.car": "Автомобиль", | ||||||
|  |   "dry-wash.order-view.details.location": "Где", | ||||||
|  |   "dry-wash.order-view.details.datetime-range": "Когда", | ||||||
|  |   "dry-wash.order-view.details.alert": "С вами свяжется оператор насчет оплаты по указанному номеру телефона", | ||||||
|   "dry-wash.notFound.title": "Страница не найдена", |   "dry-wash.notFound.title": "Страница не найдена", | ||||||
|   "dry-wash.notFound.description": "К сожалению, запрашиваемая вами страница не существует.", |   "dry-wash.notFound.description": "К сожалению, запрашиваемая вами страница не существует.", | ||||||
|   "dry-wash.notFound.button.back": "Вернуться на главную", |   "dry-wash.notFound.button.back": "Вернуться на главную", | ||||||
|  | |||||||
							
								
								
									
										25
									
								
								src/api/landing.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/api/landing.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | import { getConfigValue } from '@brojs/cli'; | ||||||
|  | 
 | ||||||
|  | import { Order } from '../models/landing'; | ||||||
|  | 
 | ||||||
|  | enum LandingEndpoints { | ||||||
|  |   ORDER_VIEW = '/order' | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const LandingService = () => { | ||||||
|  |   const endpoint = getConfigValue('dry-wash.api'); | ||||||
|  | 
 | ||||||
|  |   const fetchOrder = async (orderId: Order.Id) => { | ||||||
|  |     const response = await fetch(`${endpoint}${LandingEndpoints.ORDER_VIEW}/${orderId}`); | ||||||
|  | 
 | ||||||
|  |     if (!response.ok) { | ||||||
|  |       throw new Error(`Failed to fetch order: ${response.status}`); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return await response.json(); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   return { fetchOrder }; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export { LandingService, LandingEndpoints }; | ||||||
							
								
								
									
										1
									
								
								src/components/order-view/details/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/components/order-view/details/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | export { OrderDetails } from './order-details'; | ||||||
							
								
								
									
										99
									
								
								src/components/order-view/details/order-details.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/components/order-view/details/order-details.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | |||||||
|  | import React, { FC } from 'react'; | ||||||
|  | import { | ||||||
|  |   Alert, | ||||||
|  |   AlertIcon, | ||||||
|  |   Heading, | ||||||
|  |   HStack, | ||||||
|  |   UnorderedList, | ||||||
|  |   VStack, | ||||||
|  |   ListItem, | ||||||
|  |   Text, | ||||||
|  | } from '@chakra-ui/react'; | ||||||
|  | import { useTranslation } from 'react-i18next'; | ||||||
|  | 
 | ||||||
|  | import { Order } from '../../../models/landing'; | ||||||
|  | import { formatDatetime } from '../../../lib'; | ||||||
|  | import { carBodySelectOptions } from '../../order-form/form/car-body/helper'; | ||||||
|  | 
 | ||||||
|  | import { OrderStatus } from './status'; | ||||||
|  | 
 | ||||||
|  | type OrderDetailsProps = Order.View; | ||||||
|  | 
 | ||||||
|  | export const OrderDetails: FC<OrderDetailsProps> = ({ | ||||||
|  |   id, | ||||||
|  |   status, | ||||||
|  |   phone, | ||||||
|  |   carNumber, | ||||||
|  |   carBody, | ||||||
|  |   carColor, | ||||||
|  |   location, | ||||||
|  |   datetimeBegin, | ||||||
|  |   datetimeEnd, | ||||||
|  | }) => { | ||||||
|  |   const { t } = useTranslation('~', { | ||||||
|  |     keyPrefix: 'dry-wash.order-view.details', | ||||||
|  |   }); | ||||||
|  |   const { t: tCarBody } = useTranslation('~', { | ||||||
|  |     keyPrefix: 'dry-wash.order-create.car-body-select.options', | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <VStack p={4} alignItems='flex-start' gap={4}> | ||||||
|  |       <HStack | ||||||
|  |         width='full' | ||||||
|  |         flexWrap='wrap' | ||||||
|  |         justifyContent='space-between' | ||||||
|  |         gap={2} | ||||||
|  |       > | ||||||
|  |         <Heading as='h2' size='lg'> | ||||||
|  |           {t('title', { number: id })} | ||||||
|  |         </Heading> | ||||||
|  |         <OrderStatus value={status} /> | ||||||
|  |       </HStack> | ||||||
|  |       <UnorderedList styleType='none'> | ||||||
|  |         {[ | ||||||
|  |           { | ||||||
|  |             label: t('owner'), | ||||||
|  |             value: phone, | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             label: t('car'), | ||||||
|  |             value: [ | ||||||
|  |               carNumber, | ||||||
|  |               tCarBody( | ||||||
|  |                 `${carBodySelectOptions.find(({ value }) => value === carBody)?.labelTKey}`, | ||||||
|  |               ), | ||||||
|  |               carColor, | ||||||
|  |             ] | ||||||
|  |               .filter((v) => v) | ||||||
|  |               .join(', '), | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             label: t('location'), | ||||||
|  |             value: location, | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             label: t('datetime-range'), | ||||||
|  |             value: [ | ||||||
|  |               formatDatetime(datetimeBegin), | ||||||
|  |               formatDatetime(datetimeEnd), | ||||||
|  |             ].join(' - '), | ||||||
|  |           }, | ||||||
|  |         ].map(({ label, value }, i) => ( | ||||||
|  |           <ListItem key={i}> | ||||||
|  |             {label}:{' '} | ||||||
|  |             <Text as='span' color='primary.500' fontWeight='bold'> | ||||||
|  |               {value} | ||||||
|  |             </Text> | ||||||
|  |           </ListItem> | ||||||
|  |         ))} | ||||||
|  |       </UnorderedList> | ||||||
|  |       <Alert status='info' alignItems='flex-start'> | ||||||
|  |         <AlertIcon /> | ||||||
|  |         {t('alert')} | ||||||
|  |       </Alert> | ||||||
|  |     </VStack> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // todo: add i18n for date & time
 | ||||||
							
								
								
									
										1
									
								
								src/components/order-view/details/status/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/components/order-view/details/status/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | export { OrderStatus } from './order-status'; | ||||||
							
								
								
									
										49
									
								
								src/components/order-view/details/status/order-status.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/components/order-view/details/status/order-status.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | |||||||
|  | import { Tag, TagProps } from '@chakra-ui/react'; | ||||||
|  | import React, { FC } from 'react'; | ||||||
|  | import { useTranslation } from 'react-i18next'; | ||||||
|  | import { TFunction } from 'i18next'; | ||||||
|  | 
 | ||||||
|  | import { Order } from '../../../../models/landing'; | ||||||
|  | 
 | ||||||
|  | const getPropsByStatus = ( | ||||||
|  |   status: Order.Status, | ||||||
|  |   t: TFunction<'~', 'dry-wash.arm.order.status'>, | ||||||
|  | ): TagProps => { | ||||||
|  |   switch (status) { | ||||||
|  |     case 'canceled': | ||||||
|  |       return { | ||||||
|  |         colorScheme: 'red', | ||||||
|  |         children: t('canceled'), | ||||||
|  |       }; | ||||||
|  |     case 'progress': | ||||||
|  |       return { | ||||||
|  |         colorScheme: 'yellow', | ||||||
|  |         children: t('progress'), | ||||||
|  |       }; | ||||||
|  |     case 'pending': | ||||||
|  |       return { | ||||||
|  |         colorScheme: 'yellow', | ||||||
|  |         children: t('pending'), | ||||||
|  |       }; | ||||||
|  |     case 'working': | ||||||
|  |       return { | ||||||
|  |         colorScheme: 'yellow', | ||||||
|  |         children: t('working'), | ||||||
|  |       }; | ||||||
|  |     case 'complete': | ||||||
|  |       return { | ||||||
|  |         colorScheme: 'green', | ||||||
|  |         children: t('complete'), | ||||||
|  |       }; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export const OrderStatus: FC<{ value: Order.Status }> = ({ value }) => { | ||||||
|  |   const { t } = useTranslation('~', { | ||||||
|  |     keyPrefix: 'dry-wash.arm.order.status', | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   const props = getPropsByStatus(value, t); | ||||||
|  | 
 | ||||||
|  |   return <Tag variant='solid' {...props} />; | ||||||
|  | }; | ||||||
							
								
								
									
										1
									
								
								src/components/order-view/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/components/order-view/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | export * from './details'; | ||||||
| @ -10,3 +10,7 @@ export const getTimeSlot = (start: string, end: string) => { | |||||||
|     end: endDay, |     end: endDay, | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  | 
 | ||||||
|  | export const formatDatetime = (datetime: string) => { | ||||||
|  |   return dayjs(datetime).format('HH:mm DD.MM.YYYY'); | ||||||
|  | }; | ||||||
| @ -1 +1,2 @@ | |||||||
|  | export * from './date-helpers'; | ||||||
| export * from './types'; | export * from './types'; | ||||||
| @ -1,2 +1 @@ | |||||||
| export * as mockOrder from './order'; |  | ||||||
| export * as mockReview from './review'; | export * as mockReview from './review'; | ||||||
| @ -1,7 +0,0 @@ | |||||||
| import { Order } from "../../models"; |  | ||||||
| 
 |  | ||||||
| export const orders: Order.View[] = [ |  | ||||||
|   { id: 'id1' }, |  | ||||||
|   { id: 'id2' }, |  | ||||||
|   { id: 'id3' }, |  | ||||||
| ]; |  | ||||||
							
								
								
									
										1
									
								
								src/models/api/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/models/api/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | export * from './order-view'; | ||||||
							
								
								
									
										14
									
								
								src/models/api/order-view.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/models/api/order-view.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | import { Order } from "../landing"; | ||||||
|  | 
 | ||||||
|  | export type FetchOrderQueryResponse = { | ||||||
|  |   id: string; | ||||||
|  |   orderDate: string; | ||||||
|  |   carNumber: string; | ||||||
|  |   carBody: number; | ||||||
|  |   carColor?: string; | ||||||
|  |   startWashTime: string; | ||||||
|  |   endWashTime: string; | ||||||
|  |   status: Order.Status; | ||||||
|  |   phone: string; | ||||||
|  |   location: string; | ||||||
|  | }; | ||||||
| @ -2,6 +2,12 @@ import { Car, Customer, Washing } from "."; | |||||||
| 
 | 
 | ||||||
| export type Id = string; | export type Id = string; | ||||||
| 
 | 
 | ||||||
|  | export type Status = 'pending' | | ||||||
|  |   'progress' | | ||||||
|  |   'working' | | ||||||
|  |   'canceled' | | ||||||
|  |   'complete'; | ||||||
|  | 
 | ||||||
| export type Create = { | export type Create = { | ||||||
|   customer: { |   customer: { | ||||||
|     phone: Customer.PhoneNumber, |     phone: Customer.PhoneNumber, | ||||||
| @ -20,4 +26,13 @@ export type Create = { | |||||||
| 
 | 
 | ||||||
| export type View = { | export type View = { | ||||||
|   id: Id; |   id: Id; | ||||||
|  |   orderDate: string, | ||||||
|  |   status: Status, | ||||||
|  |   phone: Customer.PhoneNumber; | ||||||
|  |   carNumber: Car.RegistrationNumber; | ||||||
|  |   carBody: Car.BodyStyle; | ||||||
|  |   carColor?: Car.Color; | ||||||
|  |   location: Washing.Location; | ||||||
|  |   datetimeBegin: Washing.AvailableBeginDateTime; | ||||||
|  |   datetimeEnd: Washing.AvailableEndDateTime; | ||||||
| }; | }; | ||||||
							
								
								
									
										40
									
								
								src/pages/order-view/helper.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/pages/order-view/helper.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | |||||||
|  | import { useEffect, useState } from 'react'; | ||||||
|  | 
 | ||||||
|  | import { LandingService } from '../../api/landing'; | ||||||
|  | import { Order } from '../../models/landing'; | ||||||
|  | import { FetchOrderQueryResponse } from '../../models/api'; | ||||||
|  | 
 | ||||||
|  | export const useFetchOrderDetails = ({ | ||||||
|  |   orderId, | ||||||
|  | }: { | ||||||
|  |   orderId: Order.View['id']; | ||||||
|  | }) => { | ||||||
|  |   const { fetchOrder } = LandingService(); | ||||||
|  | 
 | ||||||
|  |   const [data, setData] = useState<FetchOrderQueryResponse>(); | ||||||
|  |   const [isLoading, setIsLoading] = useState(false); | ||||||
|  |   const [error, setError] = useState<string | null>(null); | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     const fetchData = async () => { | ||||||
|  |       setIsLoading(true); | ||||||
|  | 
 | ||||||
|  |       try { | ||||||
|  |         const data = await fetchOrder(orderId); | ||||||
|  |         setData(data.body); | ||||||
|  |       } catch (error) { | ||||||
|  |         setError(error.message); | ||||||
|  |       } finally { | ||||||
|  |         setIsLoading(false); | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     fetchData(); | ||||||
|  |   }, []); | ||||||
|  | 
 | ||||||
|  |   return { | ||||||
|  |     isLoading, | ||||||
|  |     data, | ||||||
|  |     error, | ||||||
|  |   }; | ||||||
|  | }; | ||||||
| @ -1,7 +1,75 @@ | |||||||
| import React from "react"; | import React, { FC, useEffect } from 'react'; | ||||||
|  | import { HStack, Spinner, useToast } from '@chakra-ui/react'; | ||||||
|  | import { useTranslation } from 'react-i18next'; | ||||||
|  | import { Container, Heading, VStack } from '@chakra-ui/react'; | ||||||
|  | import { useParams } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| const Page = () => { | import { LandingThemeProvider } from '../../containers'; | ||||||
|   return <h1>Order view</h1>; | import { OrderDetails } from '../../components/order-view'; | ||||||
|  | 
 | ||||||
|  | import { useFetchOrderDetails } from './helper'; | ||||||
|  | 
 | ||||||
|  | const Page: FC = () => { | ||||||
|  |   const { t } = useTranslation('~', { | ||||||
|  |     keyPrefix: 'dry-wash.order-view', | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   const { orderId } = useParams(); | ||||||
|  | 
 | ||||||
|  |   const { isLoading, data, error } = useFetchOrderDetails({ orderId }); | ||||||
|  | 
 | ||||||
|  |   const toast = useToast(); | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (error) { | ||||||
|  |       toast({ | ||||||
|  |         title: t('error.title'), | ||||||
|  |         description: t('fetch.error'), | ||||||
|  |         status: 'error', | ||||||
|  |         duration: 5000, | ||||||
|  |         isClosable: true, | ||||||
|  |         position: 'bottom-right', | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |   }, [error]); | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <LandingThemeProvider> | ||||||
|  |       <Container | ||||||
|  |         w='full' | ||||||
|  |         maxWidth='container.xl' | ||||||
|  |         minH='100vh' | ||||||
|  |         padding={0} | ||||||
|  |         bg='white' | ||||||
|  |         centerContent | ||||||
|  |       > | ||||||
|  |         <VStack w='full' h='full' alignItems='stretch' flexGrow={1}> | ||||||
|  |           <Heading textAlign='center' mt={4}> | ||||||
|  |             {t('title')} | ||||||
|  |           </Heading> | ||||||
|  |           {isLoading ? ( | ||||||
|  |             <HStack width='full' justifyContent='center'> | ||||||
|  |               <Spinner size='lg' /> | ||||||
|  |             </HStack> | ||||||
|  |           ) : ( | ||||||
|  |             data && ( | ||||||
|  |               <OrderDetails | ||||||
|  |                 id={data.id} | ||||||
|  |                 orderDate={data.orderDate} | ||||||
|  |                 status={data.status} | ||||||
|  |                 phone={data.phone} | ||||||
|  |                 carNumber={data.carNumber} | ||||||
|  |                 carBody={data.carBody} | ||||||
|  |                 carColor={data.carColor} | ||||||
|  |                 location={data.location} | ||||||
|  |                 datetimeBegin={data.startWashTime} | ||||||
|  |                 datetimeEnd={data.endWashTime} | ||||||
|  |               /> | ||||||
|  |             ) | ||||||
|  |           )} | ||||||
|  |         </VStack> | ||||||
|  |       </Container> | ||||||
|  |     </LandingThemeProvider> | ||||||
|  |   ); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export default Page; | export default Page; | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ | |||||||
| /* eslint-disable @typescript-eslint/no-require-imports */ | /* eslint-disable @typescript-eslint/no-require-imports */ | ||||||
| const router = require('express').Router(); | const router = require('express').Router(); | ||||||
| 
 | 
 | ||||||
| const STUBS = { masters: 'success', orders: 'success' }; | const STUBS = { masters: 'success', orders: 'success', orderView: 'success' }; | ||||||
| 
 | 
 | ||||||
| router.get('/set/:name/:value', (req, res) => { | router.get('/set/:name/:value', (req, res) => { | ||||||
|   const { name, value } = req.params; |   const { name, value } = req.params; | ||||||
| @ -24,6 +24,11 @@ router.get('/', (req, res) => { | |||||||
|       ${generateRadioInput('orders', 'success')} |       ${generateRadioInput('orders', 'success')} | ||||||
|       ${generateRadioInput('orders', 'error')} |       ${generateRadioInput('orders', 'error')} | ||||||
|     </fieldset> |     </fieldset> | ||||||
|  |     <fieldset>  | ||||||
|  |     <legend>Лендинг - Детали заказа</legend> | ||||||
|  |       ${generateRadioInput('orderView', 'success')} | ||||||
|  |       ${generateRadioInput('orderView', 'error')} | ||||||
|  |     </fieldset> | ||||||
| </div>`); | </div>`); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -33,6 +33,19 @@ router.get('/arm/orders', (req, res) => { | |||||||
|     ); |     ); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | router.get('/order/:orderId', ({ params }, res) => { | ||||||
|  |   const { orderId } = params; | ||||||
|  |   const stubName = `${orderId}-${STUBS.orderView}`; | ||||||
|  | 
 | ||||||
|  |   res | ||||||
|  |     .status(/error/.test(stubName) ? 500 : 200) | ||||||
|  |     .send( | ||||||
|  |       /^error$/.test(stubName) | ||||||
|  |         ? commonError | ||||||
|  |         : require(`../json/landing-order-view/${stubName}.json`), | ||||||
|  |     ); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
| router.use('/admin', require('./admin')); | router.use('/admin', require('./admin')); | ||||||
| 
 | 
 | ||||||
| module.exports = router; | module.exports = router; | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								stubs/json/landing-order-view/1-success.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								stubs/json/landing-order-view/1-success.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | { | ||||||
|  |   "success": true, | ||||||
|  |   "body": { | ||||||
|  |     "id": "order1", | ||||||
|  |     "orderDate": "2024-11-24T08:41:46.366Z", | ||||||
|  |     "status": "progress", | ||||||
|  |     "carNumber": "A123BC", | ||||||
|  |     "carBody": 1, | ||||||
|  |     "startWashTime": "2024-11-24T10:30:00.000Z", | ||||||
|  |     "endWashTime": "2024-11-24T16:30:00.000Z", | ||||||
|  |     "phone": "79001234563", | ||||||
|  |     "location": "55.754364, 48.743295 Университетская улица, 1, Иннополис, Верхнеуслонский район, Республика Татарстан (Татарстан), 420500" | ||||||
|  |   } | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user