diff --git a/auto-bid-admin/src/apis/auth.ts b/auto-bid-admin/src/apis/auth.ts index 028171e..cff5f66 100644 --- a/auto-bid-admin/src/apis/auth.ts +++ b/auto-bid-admin/src/apis/auth.ts @@ -19,6 +19,20 @@ export const login = async (credentials: { username: string; password: string }) } }; +export const checkStatus = async () => { + try { + const { data } = await axios({ + url: 'auth/check-status', + withCredentials: true, + method: 'POST', + }); + + return data as IResponse; + } catch (error) { + handleError(error); + } +}; + export const logout = async () => { try { const { data } = await axios({ diff --git a/auto-bid-admin/src/apis/bid.ts b/auto-bid-admin/src/apis/bid.ts index b951115..f367e72 100644 --- a/auto-bid-admin/src/apis/bid.ts +++ b/auto-bid-admin/src/apis/bid.ts @@ -1,6 +1,6 @@ import { generateNestParams, handleError, handleSuccess } from '.'; import axios from '../lib/axios'; -import { IBid } from '../system/type'; +import { IBid, IWebBid } from '../system/type'; import { removeFalsyValues } from '../utils'; export const getBids = async (params: Record) => { @@ -104,3 +104,17 @@ export const deletesBid = async (bids: IBid[]) => { handleError(error); } }; + +export const getImagesWorking = async (values: (IBid | IWebBid) & { type: string }) => { + try { + const { data } = await axios({ + url: `bids/images-working/${values.type.toLocaleLowerCase().replace('_', '-')}/${values.id}`, + withCredentials: true, + method: 'GET', + }); + + return data; + } catch (error) { + handleError(error); + } +}; diff --git a/auto-bid-admin/src/apis/generate-key.ts b/auto-bid-admin/src/apis/generate-key.ts new file mode 100644 index 0000000..9a1ba73 --- /dev/null +++ b/auto-bid-admin/src/apis/generate-key.ts @@ -0,0 +1,67 @@ +import { generateNestParams, handleError, handleSuccess } from '.'; +import axios from '../lib/axios'; +import { IKey } from '../system/type'; + +export const getKeys = async (params: Record) => { + return await axios({ + url: 'keys', + params: generateNestParams(params), + withCredentials: true, + method: 'GET', + }); +}; + +export const createKey = async () => { + try { + const { data } = await axios({ + url: 'keys', + withCredentials: true, + method: 'POST', + }); + + handleSuccess(data); + + return data; + } catch (error) { + handleError(error); + } +}; + +export const deleteKey = async (key: IKey) => { + try { + const { data } = await axios({ + url: 'keys/' + key.id, + withCredentials: true, + method: 'DELETE', + }); + + handleSuccess(data); + + return data; + } catch (error) { + handleError(error); + } +}; + +export const deletesKey = async (keys: IKey[]) => { + const ids = keys.reduce((prev, cur) => { + prev.push(cur.id); + return prev; + }, [] as number[]); + try { + const { data } = await axios({ + url: 'keys/deletes', + withCredentials: true, + method: 'POST', + data: { + ids, + }, + }); + + handleSuccess(data); + + return data; + } catch (error) { + handleError(error); + } +}; diff --git a/auto-bid-admin/src/components/dashboard/working-page.tsx b/auto-bid-admin/src/components/dashboard/working-page.tsx index fbd2194..a3f0d72 100644 --- a/auto-bid-admin/src/components/dashboard/working-page.tsx +++ b/auto-bid-admin/src/components/dashboard/working-page.tsx @@ -3,6 +3,7 @@ import { useDisclosure } from '@mantine/hooks'; import moment from 'moment'; import { useEffect, useState } from 'react'; import { Socket } from 'socket.io-client'; +import { getImagesWorking } from '../../apis/bid'; import { IBid, IWebBid } from '../../system/type'; import ShowImageModal from './show-image-modal'; @@ -16,19 +17,27 @@ export default function WorkingPage({ data, socket }: IWorkingPageProps) { const [opened, { open, close }] = useDisclosure(false); - const [imageSrc, setImageSrc] = useState(`${import.meta.env.VITE_BASE_URL}bids/status-working/${data.type.replace('_', '-').toLowerCase()}/${data.id}/working`); + const [imageSrc, setImageSrc] = useState(null); - const [lastUpdate, setLastUpdate] = useState(new Date()); + const [lastUpdate, setLastUpdate] = useState(null); function isIBid(obj: IBid | IWebBid): obj is IBid { return 'name' in obj; } + const renderUrl = ({ type, id }: (IBid | IWebBid) & { type: string }, name: string) => { + return `${import.meta.env.VITE_BASE_URL}bids/status-working/${type.replace('_', '-').toLowerCase()}/${id}/${name}`; + }; + + const extractTime = (filename: string) => { + return Number(filename.split('-')[0]) || 0; + }; + useEffect(() => { const updateImage = ({ type, id, filename }: { type: string; filename: string; id: IBid['id'] }) => { if (type == data.type && id == data.id) { - setLastUpdate(new Date()); - setImageSrc(`${import.meta.env.VITE_BASE_URL}bids/status-working/${type.replace('_', '-').toLowerCase()}/${id}/${filename}`); + setLastUpdate(new Date(extractTime(filename))); + setImageSrc(renderUrl(data, filename)); } }; @@ -37,8 +46,23 @@ export default function WorkingPage({ data, socket }: IWorkingPageProps) { return () => { socket.off('working', updateImage); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [socket, data.id, data.type]); + useEffect(() => { + (async () => { + const result = await getImagesWorking(data); + + if (!result || !result.data) return; + + const filename = result.data[0]; + + setImageSrc(renderUrl(data, filename)); + setLastUpdate(new Date(extractTime(filename))); + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + return ( <> @@ -74,7 +98,7 @@ export default function WorkingPage({ data, socket }: IWorkingPageProps) { - + ); } diff --git a/auto-bid-admin/src/components/user-menu.tsx b/auto-bid-admin/src/components/user-menu.tsx index 8ca1640..b986611 100644 --- a/auto-bid-admin/src/components/user-menu.tsx +++ b/auto-bid-admin/src/components/user-menu.tsx @@ -1,13 +1,14 @@ import { Avatar, Button, LoadingOverlay, Menu, Modal, PasswordInput } from '@mantine/core'; import { useForm, zodResolver } from '@mantine/form'; import { useDisclosure } from '@mantine/hooks'; -import { IconLogout, IconSettings, IconUser } from '@tabler/icons-react'; +import { IconKey, IconLogout, IconSettings, IconUser } from '@tabler/icons-react'; +import { useState } from 'react'; import { useNavigate } from 'react-router'; +import { Link } from 'react-router-dom'; import { z } from 'zod'; import { changePassword, logout } from '../apis/auth'; import { useConfirmStore } from '../lib/zustand/use-confirm'; import Links from '../system/links'; -import { useState } from 'react'; const schema = z .object({ @@ -92,6 +93,9 @@ export default function UserMenu() { }> Change password + }> + Keys + diff --git a/auto-bid-admin/src/layouts/private-layout.tsx b/auto-bid-admin/src/layouts/private-layout.tsx index 4ba4cdc..de69815 100644 --- a/auto-bid-admin/src/layouts/private-layout.tsx +++ b/auto-bid-admin/src/layouts/private-layout.tsx @@ -29,7 +29,7 @@ export default function PrivateLayout() { - {Links.MENUS.map((menu, index) => ( + {Links.MENUS.filter((i) => i.show).map((menu, index) => (