From b1eccce358c4a3baee730ffa64d9adddb01adacb Mon Sep 17 00:00:00 2001 From: Spytex Date: Fri, 21 Jul 2023 01:14:44 +0300 Subject: [PATCH] Updated API and Dashboard UI. --- public/photos/95753337.jpg | Bin 26406 -> 0 bytes public/photos/95753393.jpg | Bin 26406 -> 0 bytes .../screens/dashboard/Dashboard.tsx | 32 +++++-- src/components/ui/wagon/WagonItem.tsx | 10 +- src/enums/httpMethod.enum.ts | 11 +++ src/interfaces/middleware.interface.ts | 6 ++ src/pages/api/keys.ts | 65 +++++++++---- src/pages/api/photo.ts | 89 +++++++++++------- .../{wagons.ts => wagons/[VagonNumber].ts} | 6 -- src/pages/api/wagons/index.ts | 31 ++++++ src/types/middleware.type.ts | 6 ++ 11 files changed, 190 insertions(+), 66 deletions(-) delete mode 100644 public/photos/95753337.jpg delete mode 100644 public/photos/95753393.jpg create mode 100644 src/enums/httpMethod.enum.ts create mode 100644 src/interfaces/middleware.interface.ts rename src/pages/api/{wagons.ts => wagons/[VagonNumber].ts} (85%) create mode 100644 src/pages/api/wagons/index.ts create mode 100644 src/types/middleware.type.ts diff --git a/public/photos/95753337.jpg b/public/photos/95753337.jpg deleted file mode 100644 index 67b6222ad7c7ca68b700deb437d123f59fc6db87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26406 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 diff --git a/public/photos/95753393.jpg b/public/photos/95753393.jpg deleted file mode 100644 index 67b6222ad7c7ca68b700deb437d123f59fc6db87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26406 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 diff --git a/src/components/screens/dashboard/Dashboard.tsx b/src/components/screens/dashboard/Dashboard.tsx index 9ada980..6baf5f1 100644 --- a/src/components/screens/dashboard/Dashboard.tsx +++ b/src/components/screens/dashboard/Dashboard.tsx @@ -1,7 +1,7 @@ import { FC, useEffect, useState } from 'react'; import Layout from '@/components/layout/Layout'; -import { Box, Button, Center, Container, Divider, Flex, IconButton, Text, VStack } from '@chakra-ui/react'; -import { DeleteIcon } from '@chakra-ui/icons'; +import { Box, Button, Center, Container, Divider, Flex, IconButton, Input, InputGroup, InputRightAddon, Text, VStack, useClipboard } from '@chakra-ui/react'; +import { DeleteIcon, CopyIcon, CheckIcon } from '@chakra-ui/icons'; import { KeyService } from "@/service/key.service"; const Dashboard: FC = () => { @@ -38,11 +38,11 @@ const Dashboard: FC = () => {
- - + + {apiKeys.map((apiKey, index) => ( - - {apiKey} + + } @@ -59,4 +59,24 @@ const Dashboard: FC = () => { ); }; + +const InputWithClipboard: FC<{ apiKey: string }> = ({ apiKey }) => { + const { onCopy, hasCopied } = useClipboard(apiKey); + + return ( + + + + : } + aria-label={hasCopied ? "Copied" : "Copy"} + /> + + + ); +}; + + export default Dashboard; diff --git a/src/components/ui/wagon/WagonItem.tsx b/src/components/ui/wagon/WagonItem.tsx index cd5e22b..5cb8830 100644 --- a/src/components/ui/wagon/WagonItem.tsx +++ b/src/components/ui/wagon/WagonItem.tsx @@ -1,6 +1,6 @@ import { FC, useRef, useState } from "react"; import { IWagonDataSingle } from "@/interfaces/wagon.interface"; -import { Box, Button, Center, Flex, Link, Text, useToast, VStack } from "@chakra-ui/react"; +import { Box, Button, Center, Flex, Link, Text, useToast, VStack, useColorMode, useColorModeValue } from "@chakra-ui/react"; import { PhotoService } from "@/service/photo.service"; import QRCode from "qrcode.react"; import Barcode from "react-barcode"; @@ -10,6 +10,10 @@ export const WagonItem: FC = ({ Wagon }) => { const toast = useToast(); const [showQRCode, setShowQRCode] = useState(false); const [showBarcode, setShowBarcode] = useState(false); + const { colorMode } = useColorMode(); + const bgColor = useColorModeValue('#FFFFFF', '#1a202c'); + const lineColor = useColorModeValue('#000000', '#FFFFFF'); + const handleFileInputChange = () => { if (fileInputRef.current) { @@ -92,12 +96,12 @@ export const WagonItem: FC = ({ Wagon }) => { {showQRCode && (
- +
)} {showBarcode && (
- +
)} diff --git a/src/enums/httpMethod.enum.ts b/src/enums/httpMethod.enum.ts new file mode 100644 index 0000000..9d14372 --- /dev/null +++ b/src/enums/httpMethod.enum.ts @@ -0,0 +1,11 @@ +export enum HttpMethod { + GET = "GET", + POST = "POST", + PUT = "PUT", + DELETE = "DELETE", + HEAD = "HEAD", + CONNECT = "CONNECT", + OPTIONS = "OPTIONS", + TRACE = "TRACE", + PATCH = "PATCH", +} diff --git a/src/interfaces/middleware.interface.ts b/src/interfaces/middleware.interface.ts new file mode 100644 index 0000000..218894b --- /dev/null +++ b/src/interfaces/middleware.interface.ts @@ -0,0 +1,6 @@ +import { NextApiRequest, NextApiResponse } from 'next'; + +export interface IMiddlewareOptions { + req: NextApiRequest; + res: NextApiResponse; +} diff --git a/src/pages/api/keys.ts b/src/pages/api/keys.ts index 30d7f1f..f6abb61 100644 --- a/src/pages/api/keys.ts +++ b/src/pages/api/keys.ts @@ -1,34 +1,67 @@ import { NextApiRequest, NextApiResponse } from 'next'; import { v4 as uuidv4 } from 'uuid'; import { createClient } from '@node-redis/client'; +import { HttpMethod } from '@/enums/httpMethod.enum'; +import { IMiddlewareOptions } from '@/interfaces/middleware.interface'; +import { Middlewares } from '@/types/middleware.type'; const client = createClient(); const redisKey = 'apiKeys'; +const middlewares: Middlewares = { + [HttpMethod.GET]: getKeys, + [HttpMethod.POST]: postKey, + [HttpMethod.DELETE]: deleteKey, +} + + + +async function getKeys(options: IMiddlewareOptions) { + const { res } = options; + const elements = await client.sMembers(redisKey); + res.status(200).json(elements); +} + +async function postKey(options: IMiddlewareOptions) { + const { res } = options; + await client.sAdd(redisKey, uuidv4()); + res.status(200).end(); +} + +async function deleteKey(options: IMiddlewareOptions) { + const { res, req } = options; + const { apiKey } = req.query; + if (typeof apiKey === 'string') { + await client.sRem(redisKey, apiKey); + res.status(200).end(); + } else { + res.status(400).json({ message: 'Invalid request' }); + } +} + export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (!client.isOpen) { await client.connect(); } - if (req.method === 'POST') { - await client.sAdd(redisKey, uuidv4()); - res.status(200).end(); + const method = req.method as HttpMethod; - } else if (req.method === 'GET') { - const elements = await client.sMembers(redisKey); - res.status(200).json(elements); - } else if (req.method === 'DELETE') { - const { apiKey } = req.query; - if (typeof apiKey === 'string') { - await client.sRem(redisKey, apiKey); - res.status(200).end(); - - } else { - res.status(400).json({ message: 'Invalid request' }); - } - } else { + if (!Object.keys(middlewares).includes(method)) { res.setHeader('Allow', ['POST', 'GET', 'DELETE']); res.status(405).end(`Method ${req.method} Not Allowed`); } + + const middleware = middlewares[method]; + + if (!middleware) { + return res.status(500).end() + } + + try { + await middleware({ req, res }); + } catch (error) { + console.error(JSON.stringify(error)); + return res.status(500).end(); + } } diff --git a/src/pages/api/photo.ts b/src/pages/api/photo.ts index af6142b..5478aa0 100644 --- a/src/pages/api/photo.ts +++ b/src/pages/api/photo.ts @@ -1,34 +1,38 @@ -import { NextApiHandler, NextApiRequest } from "next"; +import { NextApiRequest, NextApiResponse } from "next"; import formidable from "formidable"; import path from "path"; import fs from "fs/promises"; +import { HttpMethod } from '@/enums/httpMethod.enum'; +import { IMiddlewareOptions } from '@/interfaces/middleware.interface'; +import { Middlewares } from '@/types/middleware.type'; -export const config = { - api: { - bodyParser: false, - }, -}; -const readFile = ( +const middlewares: Middlewares = { + [HttpMethod.POST]: postPhoto, + [HttpMethod.DELETE]: deletePhoto, +} + + +const readFile = async ( req: NextApiRequest, saveLocally?: boolean, ): Promise<{ fields: formidable.Fields; files: formidable.Files }> => { - const options: formidable.Options = {}; + const formidableOptions: formidable.Options = {}; if (saveLocally) { - options.uploadDir = path.join(process.cwd(), "/public/photos"); - options.filename = () => { + formidableOptions.uploadDir = path.join(process.cwd(), "/public/photos"); + formidableOptions.filename = () => { return `${req.query.VagonNumber as string}.jpg`; }; } - options.maxFileSize = 4000 * 1024 * 1024; - const form = formidable(options); + formidableOptions.maxFileSize = 4000 * 1024 * 1024; + const form = formidable(formidableOptions); return new Promise((resolve, reject) => { form.parse(req, (err, fields, files) => { if (err) reject(err); resolve({ fields, files }); }); }); -}; +} const deleteFile = async (req: NextApiRequest) => { const { VagonNumber } = req.query; @@ -38,29 +42,44 @@ const deleteFile = async (req: NextApiRequest) => { } catch (error) { throw new Error(`Error deleting file: ${error}`); } -}; +} + + +async function postPhoto(options: IMiddlewareOptions) { + const { res, req } = options; + try { + await fs.readdir(path.join(process.cwd() + "/public", "/photos")); + } catch (error) { + await fs.mkdir(path.join(process.cwd() + "/public", "/photos")); + } + await readFile(req, true); + res.json({ done: "ok" }); +} -const handler: NextApiHandler = async (req, res) => { - const { method } = req; +async function deletePhoto(options: IMiddlewareOptions) { + const { res, req } = options; + await deleteFile(req); + res.status(200).json({ message: "File deleted successfully" }); +} - if (method === "DELETE") { - try { - await deleteFile(req); - res.status(200).json({ message: "File deleted successfully" }); - } catch (error) { - res.status(500).json({ message: error }); - } - } else if (method === "POST") { - try { - await fs.readdir(path.join(process.cwd() + "/public", "/photos")); - } catch (error) { - await fs.mkdir(path.join(process.cwd() + "/public", "/photos")); - } - await readFile(req, true); - res.json({ done: "ok" }); - } else { - res.status(405).json({ message: "Method not supported" }); + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + const method = req.method as HttpMethod; + if (!Object.keys(middlewares).includes(method)) { + res.setHeader('Allow', ['POST', 'GET', 'DELETE']); + res.status(405).end(`Method ${req.method} Not Allowed`); + } + + const middleware = middlewares[method]; + + if (!middleware) { + return res.status(500).end() } -}; -export default handler; + try { + await middleware({ req, res }); + } catch (error) { + console.error(JSON.stringify(error)); + return res.status(500).end(); + } +} diff --git a/src/pages/api/wagons.ts b/src/pages/api/wagons/[VagonNumber].ts similarity index 85% rename from src/pages/api/wagons.ts rename to src/pages/api/wagons/[VagonNumber].ts index 46e2868..157a471 100644 --- a/src/pages/api/wagons.ts +++ b/src/pages/api/wagons/[VagonNumber].ts @@ -1,6 +1,5 @@ import { NextApiRequest, NextApiResponse } from 'next'; import { WagonService } from '@/service/wagon.service'; -import { KeyService } from "@/service/key.service"; import { createClient } from "@node-redis/client"; @@ -24,11 +23,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const wagonNumber = query.VagonNumber as string; - if (!wagonNumber) { - const wagons = await WagonService.getAll(); - return res.status(200).json(wagons); - } - const wagon = await WagonService.getOne(wagonNumber); if (!wagon) { diff --git a/src/pages/api/wagons/index.ts b/src/pages/api/wagons/index.ts new file mode 100644 index 0000000..020f67f --- /dev/null +++ b/src/pages/api/wagons/index.ts @@ -0,0 +1,31 @@ +import { NextApiRequest, NextApiResponse } from 'next'; +import { WagonService } from '@/service/wagon.service'; +import { createClient } from "@node-redis/client"; + + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + try { + const { query } = req; + const apiKey = query.apiKey as string; + const redisKey = 'apiKeys'; + + const client = createClient(); + + if (!client.isOpen) { + await client.connect(); + } + + const validation = await client.sIsMember(redisKey, apiKey); + + if (!apiKey || !validation) { + return res.status(401).json({ error: 'Invalid API key' }); + } + + const wagons = await WagonService.getAll(); + return res.status(200).json(wagons); + + } catch (error) { + console.error('Error retrieving wagon:', error); + return res.status(500).json({ error: 'Internal server error' }); + } +} diff --git a/src/types/middleware.type.ts b/src/types/middleware.type.ts new file mode 100644 index 0000000..cb98f7a --- /dev/null +++ b/src/types/middleware.type.ts @@ -0,0 +1,6 @@ +import { HttpMethod } from "@/enums/httpMethod.enum"; +import { IMiddlewareOptions } from "@/interfaces/middleware.interface"; + +export type Middlewares = Partial< + Record any> +>