feat: add stub fetch admin (#44)
This commit is contained in:
parent
7c157574c8
commit
0b2dae79ac
@ -24,6 +24,6 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
config: {
|
||||
'dry-wash-pl.api': '/api',
|
||||
'dry-wash.api': '/api',
|
||||
},
|
||||
};
|
||||
|
@ -16,6 +16,8 @@
|
||||
"dry-wash.landing.social-proof-section.heading": "We are being chosen",
|
||||
"dry-wash.arm.master.add": "Add",
|
||||
"dry-wash.arm.order.title": "Orders",
|
||||
"dry-wash.arm.order.table.empty": "Table empty",
|
||||
"dry-wash.arm.order.error.title": "Error loading data",
|
||||
"dry-wash.arm.order.status.progress": "In Progress",
|
||||
"dry-wash.arm.order.status.complete": "Completed",
|
||||
"dry-wash.arm.order.status.pending": "Pending",
|
||||
@ -30,6 +32,8 @@
|
||||
"dry-wash.arm.order.table.header.location": "Location",
|
||||
"dry-wash.arm.master.title": "Masters",
|
||||
"dry-wash.arm.master.table.header.name": "Name",
|
||||
"dry-wash.arm.master.table.empty": "Table empty",
|
||||
"dry-wash.arm.master.error.title": "Error loading data",
|
||||
"dry-wash.arm.master.table.header.currentJob": "Current Job",
|
||||
"dry-wash.arm.master.table.header.phone": "Phone",
|
||||
"dry-wash.arm.master.table.header.actions": "Actions",
|
||||
|
@ -13,7 +13,11 @@
|
||||
"dry-wash.arm.order.table.header.status": "Статус",
|
||||
"dry-wash.arm.order.table.header.telephone": "Телефон",
|
||||
"dry-wash.arm.order.table.header.location": "Расположение",
|
||||
"dry-wash.arm.order.table.empty": "Список пуст",
|
||||
"dry-wash.arm.order.error.title": "Ошибка при загрузке данных",
|
||||
"dry-wash.arm.master.title": "Мастера",
|
||||
"dry-wash.arm.master.table.empty": "Список пуст",
|
||||
"dry-wash.arm.master.error.title": "Ошибка при загрузке данных",
|
||||
"dry-wash.arm.master.table.header.name": "Имя",
|
||||
"dry-wash.arm.master.table.header.currentJob": "Актуальная занятость",
|
||||
"dry-wash.arm.master.table.header.phone": "Телефон",
|
||||
|
34
src/api/arm.ts
Normal file
34
src/api/arm.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { getConfigValue } from '@brojs/cli';
|
||||
|
||||
enum ArmEndpoints {
|
||||
ORDERS = '/arm/orders',
|
||||
MASTERS = '/arm/masters',
|
||||
}
|
||||
|
||||
const armService = () => {
|
||||
const endpoint = getConfigValue('dry-wash.api');
|
||||
|
||||
const fetchOrders = async () => {
|
||||
const response = await fetch(`${endpoint}${ArmEndpoints.ORDERS}`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch orders: ${response.status}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
};
|
||||
|
||||
const fetchMasters = async () => {
|
||||
const response = await fetch(`${endpoint}${ArmEndpoints.MASTERS}`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch masters: ${response.status}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
};
|
||||
|
||||
return { fetchOrders, fetchMasters };
|
||||
};
|
||||
|
||||
export { armService, ArmEndpoints };
|
@ -4,6 +4,19 @@ import { Badge, Link, Stack, Td, Tr } from '@chakra-ui/react';
|
||||
import MasterActionsMenu from '../MasterActionsMenu';
|
||||
import { getTimeSlot } from '../../lib/date-helpers';
|
||||
|
||||
export interface Schedule {
|
||||
id: string;
|
||||
startWashTime: string;
|
||||
endWashTime: string;
|
||||
}
|
||||
|
||||
export type MasterProps = {
|
||||
id: string;
|
||||
name: string;
|
||||
schedule: Schedule[];
|
||||
phone: string;
|
||||
};
|
||||
|
||||
const MasterItem = ({ name, schedule, phone }) => {
|
||||
return (
|
||||
<Tr>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Heading,
|
||||
@ -10,12 +10,17 @@ import {
|
||||
Button,
|
||||
useDisclosure,
|
||||
Flex,
|
||||
useToast,
|
||||
Td,
|
||||
Text,
|
||||
Spinner,
|
||||
} from '@chakra-ui/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import MasterItem from '../MasterItem';
|
||||
import MasterDrawer from '../MasterDrawer';
|
||||
import data from '../../../stubs/json/arm-masters/success.json';
|
||||
import { armService } from '../../api/arm';
|
||||
import { MasterProps } from '../MasterItem/MasterItem';
|
||||
|
||||
const TABLE_HEADERS = [
|
||||
'name' as const,
|
||||
@ -26,11 +31,41 @@ const TABLE_HEADERS = [
|
||||
|
||||
const Masters = () => {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
|
||||
const toast = useToast();
|
||||
const { t } = useTranslation('~', {
|
||||
keyPrefix: 'dry-wash.arm.master',
|
||||
});
|
||||
|
||||
const [masters, setMasters] = useState<MasterProps[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const { fetchMasters } = armService();
|
||||
|
||||
useEffect(() => {
|
||||
const loadMasters = async () => {
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const data = await fetchMasters();
|
||||
setMasters(data.body);
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
toast({
|
||||
title: t('error.title'),
|
||||
status: 'error',
|
||||
duration: 5000,
|
||||
isClosable: true,
|
||||
position: 'bottom-right',
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
loadMasters();
|
||||
}, [toast, t]);
|
||||
|
||||
return (
|
||||
<Box p='8'>
|
||||
<Flex justifyContent='space-between' alignItems='center' mb='5'>
|
||||
@ -48,9 +83,25 @@ const Masters = () => {
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{data.body.map((master, index) => (
|
||||
<MasterItem key={index} {...master} />
|
||||
))}
|
||||
{loading && (
|
||||
<Tr>
|
||||
<Td colSpan={TABLE_HEADERS.length} textAlign='center' py='8'>
|
||||
<Spinner size='lg' />
|
||||
</Td>
|
||||
</Tr>
|
||||
)}
|
||||
{!loading && masters.length === 0 && !error && (
|
||||
<Tr>
|
||||
<Td colSpan={TABLE_HEADERS.length}>
|
||||
<Text>{t('table.empty')}</Text>
|
||||
</Td>
|
||||
</Tr>
|
||||
)}
|
||||
{!loading &&
|
||||
!error &&
|
||||
masters.map((master, index) => (
|
||||
<MasterItem key={index} {...master} />
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
<MasterDrawer isOpen={isOpen} onClose={onClose} />
|
||||
|
@ -1,24 +1,68 @@
|
||||
import React from 'react';
|
||||
import { Box, Heading, Table, Thead, Tbody, Tr, Th } from '@chakra-ui/react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Heading,
|
||||
Table,
|
||||
Thead,
|
||||
Tbody,
|
||||
Tr,
|
||||
Th,
|
||||
Spinner,
|
||||
Text,
|
||||
Td,
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import OrderItem from '../OrderItem';
|
||||
import { OrderProps } from '../OrderItem/OrderItem';
|
||||
import data from '../../../stubs/json/arm-orders/success.json';
|
||||
import { armService } from '../../api/arm';
|
||||
|
||||
const TABLE_HEADERS = [
|
||||
'carNumber' as const,
|
||||
'washingTime' as const,
|
||||
'orderDate' as const,
|
||||
'status' as const,
|
||||
'telephone' as const,
|
||||
'location' as const,
|
||||
];
|
||||
|
||||
const Orders = () => {
|
||||
const { t } = useTranslation('~', {
|
||||
keyPrefix: 'dry-wash.arm.order',
|
||||
});
|
||||
|
||||
const TABLE_HEADERS = [
|
||||
'carNumber' as const,
|
||||
'washingTime' as const,
|
||||
'orderDate' as const,
|
||||
'status' as const,
|
||||
'telephone' as const,
|
||||
'location' as const,
|
||||
];
|
||||
const { fetchOrders } = armService();
|
||||
|
||||
const toast = useToast();
|
||||
|
||||
const [orders, setOrders] = useState<OrderProps[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const loadOrders = async () => {
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const data = await fetchOrders();
|
||||
setOrders(data.body);
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
toast({
|
||||
title: t('error.title'),
|
||||
status: 'error',
|
||||
duration: 5000,
|
||||
isClosable: true,
|
||||
position: 'bottom-right',
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
loadOrders();
|
||||
}, [toast, t]);
|
||||
|
||||
return (
|
||||
<Box p='8'>
|
||||
@ -34,13 +78,29 @@ const Orders = () => {
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{data.body.map((order, index) => (
|
||||
<OrderItem
|
||||
key={index}
|
||||
{...order}
|
||||
status={order.status as OrderProps['status']}
|
||||
/>
|
||||
))}
|
||||
{loading && (
|
||||
<Tr>
|
||||
<Td colSpan={TABLE_HEADERS.length} textAlign='center' py='8'>
|
||||
<Spinner size='lg' />
|
||||
</Td>
|
||||
</Tr>
|
||||
)}
|
||||
{!loading && orders.length === 0 && !error && (
|
||||
<Tr>
|
||||
<Td colSpan={TABLE_HEADERS.length}>
|
||||
<Text>{t('table.empty')}</Text>
|
||||
</Td>
|
||||
</Tr>
|
||||
)}
|
||||
{!loading &&
|
||||
!error &&
|
||||
orders.map((order, index) => (
|
||||
<OrderItem
|
||||
key={index}
|
||||
{...order}
|
||||
status={order.status as OrderProps['status']}
|
||||
/>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
</Box>
|
||||
|
@ -6,7 +6,10 @@ const STUBS = require('./admin').STUBS;
|
||||
|
||||
const commonError = { success: false, message: 'Что-то пошло не так' };
|
||||
|
||||
const sleep = (duration = 300) => (req, res, next) => setTimeout(next, duration);
|
||||
const sleep =
|
||||
(duration = 1000) =>
|
||||
(req, res, next) =>
|
||||
setTimeout(next, duration);
|
||||
|
||||
router.use(sleep());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user