diff --git a/package.json b/package.json index 40f4adb..7727cff 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ }, "dependencies": { "@radix-ui/react-label": "^2.1.2", + "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-toast": "^1.2.6", "@tanstack/react-query": "^5.62.11", @@ -52,7 +53,6 @@ "globals": "^15.14.0", "husky": "^9.1.7", "lint-staged": "^15.3.0", - "msw": "^2.7.0", "postcss": "^8.4.49", "prettier": "^3.4.2", "tailwindcss": "^3.4.17", diff --git a/public/mockServiceWorker.js b/public/mockServiceWorker.js deleted file mode 100644 index df7fdd3..0000000 --- a/public/mockServiceWorker.js +++ /dev/null @@ -1,306 +0,0 @@ -/* tslint:disable */ - -/** - * Mock Service Worker. - * @see https://github.com/mswjs/msw - * - Please do NOT modify this file. - * - Please do NOT serve this file on production. - */ - -const PACKAGE_VERSION = '2.7.0'; -const INTEGRITY_CHECKSUM = '00729d72e3b82faf54ca8b9621dbb96f'; -const IS_MOCKED_RESPONSE = Symbol('isMockedResponse'); -const activeClientIds = new Set(); - -self.addEventListener('install', function () { - self.skipWaiting(); -}); - -self.addEventListener('activate', function (event) { - event.waitUntil(self.clients.claim()); -}); - -self.addEventListener('message', async function (event) { - const clientId = event.source.id; - - if (!clientId || !self.clients) { - return; - } - - const client = await self.clients.get(clientId); - - if (!client) { - return; - } - - const allClients = await self.clients.matchAll({ - type: 'window', - }); - - switch (event.data) { - case 'KEEPALIVE_REQUEST': { - sendToClient(client, { - type: 'KEEPALIVE_RESPONSE', - }); - break; - } - - case 'INTEGRITY_CHECK_REQUEST': { - sendToClient(client, { - type: 'INTEGRITY_CHECK_RESPONSE', - payload: { - packageVersion: PACKAGE_VERSION, - checksum: INTEGRITY_CHECKSUM, - }, - }); - break; - } - - case 'MOCK_ACTIVATE': { - activeClientIds.add(clientId); - - sendToClient(client, { - type: 'MOCKING_ENABLED', - payload: { - client: { - id: client.id, - frameType: client.frameType, - }, - }, - }); - break; - } - - case 'MOCK_DEACTIVATE': { - activeClientIds.delete(clientId); - break; - } - - case 'CLIENT_CLOSED': { - activeClientIds.delete(clientId); - - const remainingClients = allClients.filter((client) => { - return client.id !== clientId; - }); - - // Unregister itself when there are no more clients - if (remainingClients.length === 0) { - self.registration.unregister(); - } - - break; - } - } -}); - -self.addEventListener('fetch', function (event) { - const { request } = event; - - // Bypass navigation requests. - if (request.mode === 'navigate') { - return; - } - - // Opening the DevTools triggers the "only-if-cached" request - // that cannot be handled by the worker. Bypass such requests. - if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { - return; - } - - // Bypass all requests when there are no active clients. - // Prevents the self-unregistered worked from handling requests - // after it's been deleted (still remains active until the next reload). - if (activeClientIds.size === 0) { - return; - } - - // Generate unique request ID. - const requestId = crypto.randomUUID(); - event.respondWith(handleRequest(event, requestId)); -}); - -async function handleRequest(event, requestId) { - const client = await resolveMainClient(event); - const response = await getResponse(event, client, requestId); - - // Send back the response clone for the "response:*" life-cycle events. - // Ensure MSW is active and ready to handle the message, otherwise - // this message will pend indefinitely. - if (client && activeClientIds.has(client.id)) { - (async function () { - const responseClone = response.clone(); - - sendToClient( - client, - { - type: 'RESPONSE', - payload: { - requestId, - isMockedResponse: IS_MOCKED_RESPONSE in response, - type: responseClone.type, - status: responseClone.status, - statusText: responseClone.statusText, - body: responseClone.body, - headers: Object.fromEntries(responseClone.headers.entries()), - }, - }, - [responseClone.body], - ); - })(); - } - - return response; -} - -// Resolve the main client for the given event. -// Client that issues a request doesn't necessarily equal the client -// that registered the worker. It's with the latter the worker should -// communicate with during the response resolving phase. -async function resolveMainClient(event) { - const client = await self.clients.get(event.clientId); - - if (activeClientIds.has(event.clientId)) { - return client; - } - - if (client?.frameType === 'top-level') { - return client; - } - - const allClients = await self.clients.matchAll({ - type: 'window', - }); - - return allClients - .filter((client) => { - // Get only those clients that are currently visible. - return client.visibilityState === 'visible'; - }) - .find((client) => { - // Find the client ID that's recorded in the - // set of clients that have registered the worker. - return activeClientIds.has(client.id); - }); -} - -async function getResponse(event, client, requestId) { - const { request } = event; - - // Clone the request because it might've been already used - // (i.e. its body has been read and sent to the client). - const requestClone = request.clone(); - - function passthrough() { - // Cast the request headers to a new Headers instance - // so the headers can be manipulated with. - const headers = new Headers(requestClone.headers); - - // Remove the "accept" header value that marked this request as passthrough. - // This prevents request alteration and also keeps it compliant with the - // user-defined CORS policies. - const acceptHeader = headers.get('accept'); - if (acceptHeader) { - const values = acceptHeader.split(',').map((value) => value.trim()); - const filteredValues = values.filter( - (value) => value !== 'msw/passthrough', - ); - - if (filteredValues.length > 0) { - headers.set('accept', filteredValues.join(', ')); - } else { - headers.delete('accept'); - } - } - - return fetch(requestClone, { headers }); - } - - // Bypass mocking when the client is not active. - if (!client) { - return passthrough(); - } - - // Bypass initial page load requests (i.e. static assets). - // The absence of the immediate/parent client in the map of the active clients - // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet - // and is not ready to handle requests. - if (!activeClientIds.has(client.id)) { - return passthrough(); - } - - // Notify the client that a request has been intercepted. - const requestBuffer = await request.arrayBuffer(); - const clientMessage = await sendToClient( - client, - { - type: 'REQUEST', - payload: { - id: requestId, - url: request.url, - mode: request.mode, - method: request.method, - headers: Object.fromEntries(request.headers.entries()), - cache: request.cache, - credentials: request.credentials, - destination: request.destination, - integrity: request.integrity, - redirect: request.redirect, - referrer: request.referrer, - referrerPolicy: request.referrerPolicy, - body: requestBuffer, - keepalive: request.keepalive, - }, - }, - [requestBuffer], - ); - - switch (clientMessage.type) { - case 'MOCK_RESPONSE': { - return respondWithMock(clientMessage.data); - } - - case 'PASSTHROUGH': { - return passthrough(); - } - } - - return passthrough(); -} - -function sendToClient(client, message, transferrables = []) { - return new Promise((resolve, reject) => { - const channel = new MessageChannel(); - - channel.port1.onmessage = (event) => { - if (event.data && event.data.error) { - return reject(event.data.error); - } - - resolve(event.data); - }; - - client.postMessage( - message, - [channel.port2].concat(transferrables.filter(Boolean)), - ); - }); -} - -async function respondWithMock(response) { - // Setting response status code to 0 is a no-op. - // However, when responding with a "Response.error()", the produced Response - // instance will have status code set to 0. Since it's not possible to create - // a Response instance with status code 0, handle that use-case separately. - if (response.status === 0) { - return Response.error(); - } - - const mockedResponse = new Response(response.body, response); - - Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, { - value: true, - enumerable: true, - }); - - return mockedResponse; -} diff --git a/src/App.tsx b/src/App.tsx index 206ff49..11b49e4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,11 +3,6 @@ import { RouterProvider } from 'react-router-dom'; import { router } from './router'; import { Toaster } from '@components/ui/toaster'; -// if (process.env.NODE_ENV === 'development') { -// const { worker } = await import('@mocks/browser'); -// worker.start(); -// } - const queryClient = new QueryClient(); function App() { return ( diff --git a/src/components/template/ApiKeys/Issued.tsx b/src/components/template/ApiKeys/Issued.tsx deleted file mode 100644 index 8f63896..0000000 --- a/src/components/template/ApiKeys/Issued.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { Button } from '@components/ui/button'; - -const Issued = () => { - return ( -
-

- 20241231-1234567890 -

- -
- -
-

- 생성일시 : 2024-12-31 14:41:28 -

-

- 만료일시 : 2025-03-31 14:41:28 -

-
- -
-

- 한 계정당 키는 한 개만 발급 가능합니다 -

-

- 키의 유효기간은 3개월입니다 -

-

- 갱신하면 새로운 키가 발급되어 기존의 키는 사용할 수 없습니다 -

-

- 갱신은 만료기한 일주일전부터 가능합니다 -

-
- -
- - -
- ); -}; - -export default Issued; diff --git a/src/components/template/ApiKeys/NotIssued.tsx b/src/components/template/ApiKeys/NotIssued.tsx deleted file mode 100644 index 13dbf22..0000000 --- a/src/components/template/ApiKeys/NotIssued.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { Button } from '@components/ui/button'; - -const NotIssued = () => { - return ( -
-

- 키 발급하기 -

- -
-

- 한 계정당 키는 한개만 발급가능합니다 -

-

- 키의 유효기간은 3개월입니다 -

-
- - -
- ); -}; - -export default NotIssued; diff --git a/src/components/template/IconComponnt.tsx b/src/components/template/IconComponnt.tsx new file mode 100644 index 0000000..9713394 --- /dev/null +++ b/src/components/template/IconComponnt.tsx @@ -0,0 +1,8 @@ +import * as LucideIcons from 'lucide-react'; + +const IconComponnt = ({ icon }: { icon: keyof typeof LucideIcons }) => { + const LucideIcon = LucideIcons[icon] as LucideIcons.LucideIcon; + return ; +}; + +export default IconComponnt; diff --git a/src/components/template/Key/Info.tsx b/src/components/template/Key/Info.tsx new file mode 100644 index 0000000..5276dab --- /dev/null +++ b/src/components/template/Key/Info.tsx @@ -0,0 +1,23 @@ +import { Link } from 'react-router-dom'; + +const ApiKeyInfo = () => { + return ( +
+

+ 한 계정당 키는 한개만 발급가능합니다 +

+

+ 갱신하면 새로운 키가 발급되어 기존의 키는 사용할 수 없습니다 +

+ + API 사용방법 + +
+ ); +}; + +export default ApiKeyInfo; diff --git a/src/components/template/Key/Issued.tsx b/src/components/template/Key/Issued.tsx new file mode 100644 index 0000000..cfca75a --- /dev/null +++ b/src/components/template/Key/Issued.tsx @@ -0,0 +1,59 @@ +import { Button } from '@components/ui/button'; +import Info from './Info'; +import Separator from './Separator'; +import { createToastSuccess } from '@lib/toast'; +import { useKeys } from '@hooks/api/useKeys'; +import { useAuthStore } from '@store/authStore'; +import { useState } from 'react'; + +const Issued = ({ issuedApiKey }: { issuedApiKey: string }) => { + const [apiKey, setApiKey] = useState(issuedApiKey); + const { mutate: renewKey } = useKeys(); + const { auth } = useAuthStore(); + + const handleCopy = () => { + const apiKey = document.getElementById('api-key')!.textContent!; + navigator.clipboard.writeText(apiKey).then(() => { + createToastSuccess('', 'API 키를 복사하였습니다.'); + }); + }; + + const handleRenew = () => { + renewKey(auth!.accessToken, { + onSuccess: ({ data }) => { + setApiKey(data.apiKey); + createToastSuccess('', 'API 키가 성공적으로 갱신되었습니다.'); + }, + }); + }; + + return ( +
+

+ {apiKey} +

+ +

+ 복사하기 +

+ + + + + + + + +
+ ); +}; + +export default Issued; diff --git a/src/components/template/Key/NotIssued.tsx b/src/components/template/Key/NotIssued.tsx new file mode 100644 index 0000000..fd6268d --- /dev/null +++ b/src/components/template/Key/NotIssued.tsx @@ -0,0 +1,40 @@ +import { Button } from '@components/ui/button'; +import Info from './Info'; +import { useAuthStore } from '@store/authStore'; +import { useKeys } from '@hooks/api/useKeys'; +import { createToastSuccess } from '@lib/toast'; + +const NotIssued = ({ + onIssueSuccess, +}: { + onIssueSuccess: (value: string) => void; +}) => { + const { auth } = useAuthStore(); + const { mutate: renewKey } = useKeys(); + + const handleIssue = () => { + if (!auth) return; + renewKey(auth.accessToken, { + onSuccess: ({ data }) => { + createToastSuccess('', 'API 키가 성공적으로 발급되었습니다.'); + onIssueSuccess(data.apiKey); + }, + }); + }; + + return ( +
+

+ 키 발급하기 +

+ + + + +
+ ); +}; + +export default NotIssued; diff --git a/src/components/template/Key/Separator.tsx b/src/components/template/Key/Separator.tsx new file mode 100644 index 0000000..5d4c278 --- /dev/null +++ b/src/components/template/Key/Separator.tsx @@ -0,0 +1,7 @@ +const Separator = () => { + return ( +
+ ); +}; + +export default Separator; diff --git a/src/components/template/Layout.tsx b/src/components/template/Layout.tsx index 7110d66..14f6e3b 100644 --- a/src/components/template/Layout.tsx +++ b/src/components/template/Layout.tsx @@ -3,9 +3,9 @@ import SideBar from './SideBar'; const Layout = () => { return ( -
+
-
+
diff --git a/src/components/template/SideBar/SideBarItem.tsx b/src/components/template/SideBar/SideBarItem.tsx index 2b3ec00..0ecdcd0 100644 --- a/src/components/template/SideBar/SideBarItem.tsx +++ b/src/components/template/SideBar/SideBarItem.tsx @@ -1,10 +1,8 @@ -import * as LucideIcons from 'lucide-react'; import { useNavigate } from 'react-router-dom'; import type { SideBarItemProps } from '@type/sidebar'; - +import IconComponnt from '@components/template/IconComponnt'; const SideBarItem = ({ icon, name, link, isActive }: SideBarItemProps) => { const navigate = useNavigate(); - const IconComponent = LucideIcons[icon] as LucideIcons.LucideIcon; return (
  • { }`} onClick={() => navigate(link)} > - +

    {name}

  • ); diff --git a/src/components/template/SideBar/index.tsx b/src/components/template/SideBar/index.tsx index 6d95949..7d182b6 100644 --- a/src/components/template/SideBar/index.tsx +++ b/src/components/template/SideBar/index.tsx @@ -1,18 +1,20 @@ import { sideBarItems } from '@constants/sidebar.ts'; import SideBarItem from './SideBarItem.tsx'; import { useLocation } from 'react-router-dom'; - +import { useAuthStore } from '@store/authStore'; +import IconComponnt from '../IconComponnt.tsx'; const SideBar = () => { const { pathname } = useLocation(); + const { auth, logout } = useAuthStore(); return ( ); diff --git a/src/components/template/Transactions/StatusBadge.tsx b/src/components/template/Transactions/StatusBadge.tsx new file mode 100644 index 0000000..3e0d6e4 --- /dev/null +++ b/src/components/template/Transactions/StatusBadge.tsx @@ -0,0 +1,34 @@ +import React from 'react'; + +interface StatusBadgeProps { + status: string; +} + +const StatusBadge: React.FC = ({ status }) => { + let badgeClass = ''; + let textColor = ''; + + switch (status) { + case 'APPROVED': + badgeClass = 'bg-primary text-white'; + textColor = 'text-white'; + break; + case 'CANCELED': + badgeClass = 'bg-red-200 text-white'; + textColor = 'text-red-800'; + break; + default: + badgeClass = 'bg-gray-200 text-gray-800'; + textColor = 'text-gray-800'; + } + + return ( + + {status} + + ); +}; + +export default StatusBadge; diff --git a/src/components/template/Transactions/index.tsx b/src/components/template/Transactions/index.tsx index 5febcff..871e473 100644 --- a/src/components/template/Transactions/index.tsx +++ b/src/components/template/Transactions/index.tsx @@ -6,78 +6,70 @@ import { TableHeader, TableRow, } from '@components/ui/table'; -import { - Pagination, - PaginationContent, - PaginationEllipsis, - PaginationItem, - PaginationLink, - PaginationNext, - PaginationPrevious, -} from '@components/ui/pagination'; -import type { Transaction } from '@type/transaction'; +import type { FlattenedPayment, Payment } from '@type/transaction'; import { transactionHeaders } from '@constants/transaction'; import { convertCurrencyFormat, convertDateFormat } from '@lib/fommater'; +import { useMemo } from 'react'; +import StatusBadge from './StatusBadge'; + +const Transactions = ({ data }: { data: Payment[] }) => { + const result = useMemo( + () => + data.flatMap((payment) => + payment.transactions.map((transaction) => ({ + paymentKey: transaction.paymentKey, + completedAt: transaction.completedAt, + orderName: payment.orderName, + cardNumber: payment.cardNumber, + amount: transaction.amount, + status: transaction.status, + })), + ), + [data], + ); -const index = ({ data }: { data: Transaction[] }) => { return ( <> {transactionHeaders.map((header) => ( - + {header} ))} - {data.map((transaction: Transaction) => ( - - {transaction.id} - {convertDateFormat(transaction.createdAt)} - - - - - {convertCurrencyFormat(transaction.amount)} + {result.map((payment: FlattenedPayment, index: number) => ( + + + {payment.paymentKey} + + + {convertDateFormat(payment.completedAt)} + + + {payment.orderName} + + + {payment.cardNumber} + + + {convertCurrencyFormat(payment.amount)} + + + - {transaction.reason} ))}
    - - - - - console.log('previous')} /> - - - - 1 - - - - console.log('2')}>2 - - - - 3 - - - - - - - - - - - ); }; -export default index; +export default Transactions; diff --git a/src/components/template/auth/ProtectedRoute.tsx b/src/components/template/auth/ProtectedRoute.tsx new file mode 100644 index 0000000..9922b28 --- /dev/null +++ b/src/components/template/auth/ProtectedRoute.tsx @@ -0,0 +1,17 @@ +import { useAuthStore } from '@store/authStore'; +import { Navigate, useLocation } from 'react-router-dom'; +import { ROUTES } from '@constants/routes'; +interface ProtectedRouteProps { + children: React.ReactNode; +} + +export const ProtectedRoute = ({ children }: ProtectedRouteProps) => { + const { auth } = useAuthStore(); + const location = useLocation(); + + if (!auth) { + return ; + } + + return <>{children}; +}; diff --git a/src/components/ui/select.tsx b/src/components/ui/select.tsx new file mode 100644 index 0000000..56ffca7 --- /dev/null +++ b/src/components/ui/select.tsx @@ -0,0 +1,157 @@ +import * as React from 'react'; +import * as SelectPrimitive from '@radix-ui/react-select'; +import { Check, ChevronDown, ChevronUp } from 'lucide-react'; + +import { cn } from '@lib/utils'; + +const Select = SelectPrimitive.Root; + +const SelectGroup = SelectPrimitive.Group; + +const SelectValue = SelectPrimitive.Value; + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1 dark:border-zinc-800 dark:ring-offset-zinc-950 dark:data-[placeholder]:text-zinc-400 dark:focus:ring-zinc-300', + className, + )} + {...props} + > + {children} + + + + +)); +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName; + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = 'popper', ...props }, ref) => ( + + + + + {children} + + + + +)); +SelectContent.displayName = SelectPrimitive.Content.displayName; + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectLabel.displayName = SelectPrimitive.Label.displayName; + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)); +SelectItem.displayName = SelectPrimitive.Item.displayName; + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectSeparator.displayName = SelectPrimitive.Separator.displayName; + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +}; diff --git a/src/constants/apiEndpoints.ts b/src/constants/apiEndpoints.ts index b11634b..6a72e3c 100644 --- a/src/constants/apiEndpoints.ts +++ b/src/constants/apiEndpoints.ts @@ -1,7 +1,4 @@ -const BASE_URL = 'api/backoffice/v1'; - -const getPaymentsEndpoint = (paymentKey: string) => - `${BASE_URL}/payments/${paymentKey}`; +const BASE_URL = 'https://backoffice.pay-200.com/api/backoffice/v1'; const getTransactionEndpoint = (paymentKey: string) => `${BASE_URL}/payments/${paymentKey}/transactions`; @@ -10,8 +7,11 @@ export const API_ENDPOINTS = { LOGIN: `${BASE_URL}/sign-in`, SIGNUP: `${BASE_URL}/sign-up`, PAYMENTS: { - PAYMENTS: getPaymentsEndpoint, + PAYMENTS: `${BASE_URL}/payments`, TRANSACTIONS: getTransactionEndpoint, }, - KEY: `${BASE_URL}/key`, + MANAGEMENT: { + KEYS: `${BASE_URL}/keys`, + ID: `${BASE_URL}/my-key`, + }, } as const; diff --git a/src/constants/routes.ts b/src/constants/routes.ts new file mode 100644 index 0000000..901549c --- /dev/null +++ b/src/constants/routes.ts @@ -0,0 +1,7 @@ +export const ROUTES = { + MAIN: '/', + LOGIN: '/login', + SIGNUP: '/signup', + TRANSACTIONS: '/transactions', + KEY_MANAGEMENT: '/key-management', +}; diff --git a/src/constants/sidebar.ts b/src/constants/sidebar.ts index 446df56..15f811c 100644 --- a/src/constants/sidebar.ts +++ b/src/constants/sidebar.ts @@ -1,4 +1,5 @@ import * as LucideIcons from 'lucide-react'; +import { ROUTES } from '@constants/routes'; export const sideBarItems: { name: string; @@ -8,11 +9,11 @@ export const sideBarItems: { { name: '거래내역', icon: 'FileText', - link: '/transactions', + link: ROUTES.TRANSACTIONS, }, { name: '키 관리', icon: 'KeyRound', - link: '/api-keys', + link: ROUTES.KEY_MANAGEMENT, }, ]; diff --git a/src/constants/transaction.ts b/src/constants/transaction.ts index 9344ebc..0f1a2e1 100644 --- a/src/constants/transaction.ts +++ b/src/constants/transaction.ts @@ -1,9 +1,8 @@ export const transactionHeaders = [ '거래번호', '거래일시', - '이름', - '거래상점', '거래품목', + '카드번호', '가격', '거래상태', ]; diff --git a/src/hooks/useAuth.ts b/src/hooks/api/useAuth.ts similarity index 74% rename from src/hooks/useAuth.ts rename to src/hooks/api/useAuth.ts index 7c41061..70917ee 100644 --- a/src/hooks/useAuth.ts +++ b/src/hooks/api/useAuth.ts @@ -3,20 +3,25 @@ import { apiClient } from '@lib/api/apiClient'; import { API_ENDPOINTS } from '@constants/apiEndpoints'; import type { LoginReq, LoginRes, SignupReq } from '@type/auth'; import { createToastSuccess, createToastError } from '@lib/toast'; -import { useNavigate } from 'react-router-dom'; +import { useNavigate, useLocation } from 'react-router-dom'; import { useAuthStore } from '@store/authStore'; +import { ROUTES } from '@constants/routes'; export const useLogin = () => { const navigate = useNavigate(); const setAuth = useAuthStore((state) => state.setAuth); + const location = useLocation(); return useMutation({ mutationFn: (data: LoginReq) => apiClient.post(API_ENDPOINTS.LOGIN, data), onSuccess: (response: LoginRes) => { + sessionStorage.setItem('auth', JSON.stringify(response.data)); setAuth(response.data); - createToastSuccess('로그인 성공', '메인 페이지로 이동합니다'); - navigate('/'); + createToastSuccess('', '로그인되었습니다'); + + const from = location.state?.from?.pathname || '/'; + navigate(from); }, onError: createToastError('로그인 실패'), }); @@ -29,7 +34,7 @@ export const useSignup = () => { mutationFn: (data: SignupReq) => apiClient.post(API_ENDPOINTS.SIGNUP, data), onSuccess: () => { createToastSuccess('회원가입 성공', '로그인 페이지로 이동합니다'); - navigate('/login'); + navigate(ROUTES.LOGIN); }, onError: createToastError('회원가입 실패'), }); diff --git a/src/hooks/api/useKeys.ts b/src/hooks/api/useKeys.ts new file mode 100644 index 0000000..8865f5b --- /dev/null +++ b/src/hooks/api/useKeys.ts @@ -0,0 +1,28 @@ +import { useMutation, useQuery } from '@tanstack/react-query'; +import { apiClient } from '@lib/api/apiClient'; +import { API_ENDPOINTS } from '@constants/apiEndpoints'; +import type { KeyReq, KeyRes } from '@type/key'; + +export const useKeys = () => { + return useMutation({ + mutationFn: (accessToken: string) => { + return apiClient.post( + API_ENDPOINTS.MANAGEMENT.KEYS, + {}, + { + Authorization: `Bearer ${accessToken}`, + }, + ); + }, + }); +}; + +export const useKeysId = (accessToken: string) => { + return useQuery({ + queryKey: ['get-key'], + queryFn: () => + apiClient.get(API_ENDPOINTS.MANAGEMENT.ID, { + Authorization: `Bearer ${accessToken}`, + }), + }); +}; diff --git a/src/hooks/api/useTransaction.ts b/src/hooks/api/useTransaction.ts new file mode 100644 index 0000000..c24b035 --- /dev/null +++ b/src/hooks/api/useTransaction.ts @@ -0,0 +1,50 @@ +import { keepPreviousData, useQuery } from '@tanstack/react-query'; +import { apiClient } from '@lib/api/apiClient'; +import { API_ENDPOINTS } from '@constants/apiEndpoints'; +import type { PaymentResponse } from '@type/transaction'; + +interface PaymentFilters { + paymentKey?: string; + startDate?: string; + endDate?: string; + status?: string; +} + +export const usePayments = ( + accessToken: string, + page: number = 0, + filters: PaymentFilters = {}, +) => { + return useQuery({ + queryKey: ['get-payments', page, filters], + queryFn: () => { + const params = new URLSearchParams({ + page: String(page), + limit: '10', + ...(filters.paymentKey && { paymentKey: filters.paymentKey }), + ...(filters.startDate && { startDate: filters.startDate }), + ...(filters.endDate && { endDate: filters.endDate }), + // ...(filters.status && { status: filters.status }), + }); + + return apiClient.get( + `${API_ENDPOINTS.PAYMENTS.PAYMENTS}?${params.toString()}`, + { + Authorization: `Bearer ${accessToken}`, + }, + ); + }, + placeholderData: keepPreviousData, + }); +}; + +export const useTransactions = (accessToken: string, paymentKey: string) => { + return useQuery({ + queryKey: ['get-transactions', paymentKey], + queryFn: () => { + return apiClient.get(API_ENDPOINTS.PAYMENTS.TRANSACTIONS(paymentKey), { + Authorization: `Bearer ${accessToken}`, + }); + }, + }); +}; diff --git a/src/hooks/useKey.ts b/src/hooks/useKey.ts deleted file mode 100644 index 3d0f2be..0000000 --- a/src/hooks/useKey.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { useMutation } from '@tanstack/react-query'; -import { apiClient } from '@lib/api/apiClient'; -import { API_ENDPOINTS } from '@constants/apiEndpoints'; -import type { KeyReq } from '@type/key'; - -export const useKey = () => { - return useMutation({ - mutationFn: (data: KeyReq) => apiClient.post(API_ENDPOINTS.KEY, data), - }); -}; diff --git a/src/hooks/useTransaction.ts b/src/hooks/useTransaction.ts deleted file mode 100644 index 133fff8..0000000 --- a/src/hooks/useTransaction.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { useQuery } from '@tanstack/react-query'; -import { apiClient } from '@lib/api/apiClient'; -import { API_ENDPOINTS } from '@constants/apiEndpoints'; -import type { TransactionResponse } from '@type/transaction'; - -export const usePayments = () => { - return useQuery({ - queryKey: ['get-payments'], - queryFn: () => - apiClient.get(API_ENDPOINTS.PAYMENTS.PAYMENTS('payment-key')), - }); -}; - -export const useTransactions = () => { - return useQuery({ - queryKey: ['get-transactions'], - queryFn: () => - apiClient.get(API_ENDPOINTS.PAYMENTS.TRANSACTIONS('payment-key')), - }); -}; diff --git a/src/lib/api/apiClient.ts b/src/lib/api/apiClient.ts index f47b7d4..bbe4152 100644 --- a/src/lib/api/apiClient.ts +++ b/src/lib/api/apiClient.ts @@ -2,8 +2,7 @@ import ky from 'ky'; import { handleError } from './errorHandler'; const instance = ky.create({ - prefixUrl: '/api', - credentials: 'include', + // credentials: 'include', headers: { 'Content-Type': 'application/json', }, diff --git a/src/mocks/browser.ts b/src/mocks/browser.ts deleted file mode 100644 index 0a56427..0000000 --- a/src/mocks/browser.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { setupWorker } from 'msw/browser'; -import { handlers } from './handlers'; - -export const worker = setupWorker(...handlers); diff --git a/src/mocks/data/transactions.ts b/src/mocks/data/transactions.ts deleted file mode 100644 index f949ce9..0000000 --- a/src/mocks/data/transactions.ts +++ /dev/null @@ -1,102 +0,0 @@ -export const MOCK_PAYMENT = { - id: 9007199254740991, - paymentKey: 'payment_key_1', - amount: 35000, - status: 'APPROVED', - reason: '정상 승인', - createdAt: '2025-02-11T11:07:49.412Z', - updatedAt: '2025-02-11T11:07:49.413Z', -} as const; - -export const MOCK_TRANSACTIONS = [ - { - id: 9007199254740991, - paymentKey: 'payment_key_1', - amount: 35000, - status: 'APPROVED', - reason: '정상 승인', - createdAt: '2025-02-11T11:07:49.412Z', - updatedAt: '2025-02-11T11:07:49.413Z', - }, - { - id: 9007199254740990, - paymentKey: 'payment_key_2', - amount: 89000, - status: 'FAILED', - reason: '한도 초과', - createdAt: '2025-02-11T10:55:23.412Z', - updatedAt: '2025-02-11T10:55:23.413Z', - }, - { - id: 9007199254740989, - paymentKey: 'payment_key_3', - amount: 15000, - status: 'APPROVED', - reason: '정상 승인', - createdAt: '2025-02-11T10:43:12.412Z', - updatedAt: '2025-02-11T10:43:12.413Z', - }, - { - id: 9007199254740988, - paymentKey: 'payment_key_4', - amount: 156000, - status: 'APPROVED', - reason: '정상 승인', - createdAt: '2025-02-11T10:22:49.412Z', - updatedAt: '2025-02-11T10:22:49.413Z', - }, - { - id: 9007199254740987, - paymentKey: 'payment_key_5', - amount: 8900, - status: 'FAILED', - reason: '잔액 부족', - createdAt: '2025-02-11T10:15:33.412Z', - updatedAt: '2025-02-11T10:15:33.413Z', - }, - { - id: 9007199254740986, - paymentKey: 'payment_key_6', - amount: 67000, - status: 'APPROVED', - reason: '정상 승인', - createdAt: '2025-02-11T09:55:49.412Z', - updatedAt: '2025-02-11T09:55:49.413Z', - }, - { - id: 9007199254740985, - paymentKey: 'payment_key_7', - amount: 299000, - status: 'FAILED', - reason: '한도 초과', - createdAt: '2025-02-11T09:44:21.412Z', - updatedAt: '2025-02-11T09:44:21.413Z', - }, - { - id: 9007199254740984, - paymentKey: 'payment_key_8', - amount: 12900, - status: 'APPROVED', - reason: '정상 승인', - createdAt: '2025-02-11T09:33:15.412Z', - updatedAt: '2025-02-11T09:33:15.413Z', - }, - { - id: 9007199254740983, - paymentKey: 'payment_key_9', - amount: 45600, - status: 'APPROVED', - reason: '정상 승인', - createdAt: '2025-02-11T09:22:49.412Z', - updatedAt: '2025-02-11T09:22:49.413Z', - }, - { - id: 9007199254740982, - paymentKey: 'payment_key_10', - amount: 78000, - status: 'FAILED', - reason: '카드 정보 불일치', - createdAt: '2025-02-11T09:11:33.412Z', - updatedAt: '2025-02-11T09:11:33.413Z', - }, -] as const; diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts deleted file mode 100644 index 90d0019..0000000 --- a/src/mocks/handlers.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { authHandler } from './handlers/auth'; -import { transactionHandler } from './handlers/transaction'; -import { keyHandler } from './handlers/key'; - -export const handlers = [...authHandler, ...transactionHandler, ...keyHandler]; diff --git a/src/mocks/handlers/auth.ts b/src/mocks/handlers/auth.ts deleted file mode 100644 index a01898c..0000000 --- a/src/mocks/handlers/auth.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { http, HttpResponse } from 'msw'; -import { API_ENDPOINTS } from '@constants/apiEndpoints'; - -export const authHandler = [ - http.post(API_ENDPOINTS.LOGIN, () => { - return HttpResponse.json({ - ok: true, - data: { - id: 'user-123', - name: 'John Doe', - token: 'sample-token-123', - }, - }); - }), - - http.post(API_ENDPOINTS.SIGNUP, () => { - return HttpResponse.json({ - ok: true, - data: { - id: 'user-123', - }, - }); - }), -]; diff --git a/src/mocks/handlers/key.ts b/src/mocks/handlers/key.ts deleted file mode 100644 index 7243979..0000000 --- a/src/mocks/handlers/key.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { http, HttpResponse } from 'msw'; -import { API_ENDPOINTS } from '@constants/apiEndpoints'; - -export const keyHandler = [ - http.post(API_ENDPOINTS.KEY, () => { - return HttpResponse.json({ - ok: true, - data: { - key: 'payment-key-123', - }, - }); - }), -]; diff --git a/src/mocks/handlers/transaction.ts b/src/mocks/handlers/transaction.ts deleted file mode 100644 index 0c7d09f..0000000 --- a/src/mocks/handlers/transaction.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { http, HttpResponse } from 'msw'; -import { API_ENDPOINTS } from '@constants/apiEndpoints'; -import { MOCK_PAYMENT, MOCK_TRANSACTIONS } from '@mocks/data/transactions'; - -export const transactionHandler = [ - http.get(API_ENDPOINTS.PAYMENTS.PAYMENTS('payment-key'), () => { - return HttpResponse.json({ - ok: true, - data: MOCK_PAYMENT, - }); - }), - - http.get(API_ENDPOINTS.PAYMENTS.TRANSACTIONS('payment-key'), () => { - return HttpResponse.json({ - ok: true, - data: { - transactions: MOCK_TRANSACTIONS, - }, - }); - }), -]; diff --git a/src/mocks/server.ts b/src/mocks/server.ts deleted file mode 100644 index e52fee0..0000000 --- a/src/mocks/server.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { setupServer } from 'msw/node'; -import { handlers } from './handlers'; - -export const server = setupServer(...handlers); diff --git a/src/pages/ApiKeysPage.tsx b/src/pages/ApiKeysPage.tsx deleted file mode 100644 index 4f29e46..0000000 --- a/src/pages/ApiKeysPage.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import Issued from '@components/template/ApiKeys/Issued'; -import NotIssued from '@components/template/ApiKeys/NotIssued'; - -const KEY_ISSUED = true; - -const ApiKeysPage = () => { - return KEY_ISSUED ? : ; -}; - -export default ApiKeysPage; diff --git a/src/pages/KeyManagementPage.tsx b/src/pages/KeyManagementPage.tsx new file mode 100644 index 0000000..a29f0f7 --- /dev/null +++ b/src/pages/KeyManagementPage.tsx @@ -0,0 +1,32 @@ +import Error from '@components/template/Error'; +import Issued from '@components/template/Key/Issued'; +import NotIssued from '@components/template/Key/NotIssued'; +import Loader from '@components/template/Loader'; +import { useKeysId } from '@hooks/api/useKeys'; +import { useAuthStore } from '@store/authStore'; +import { useState, useEffect } from 'react'; + +const ApiKeysPage = () => { + const { auth } = useAuthStore(); + const { data, isLoading, isError } = useKeysId(auth!.accessToken); + const [issuedApiKey, setIssuedApiKey] = useState(null); + + useEffect(() => { + const accessToken = data?.data.apiKey; + if (accessToken) setIssuedApiKey(accessToken); + }, [data]); + + if (isLoading) return ; + else if (isError) return ; + return issuedApiKey ? ( + + ) : ( + { + setIssuedApiKey(newApiKey); + }} + /> + ); +}; + +export default ApiKeysPage; diff --git a/src/pages/LoginPage.tsx b/src/pages/LoginPage.tsx index f2cd0b9..324e559 100644 --- a/src/pages/LoginPage.tsx +++ b/src/pages/LoginPage.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import { Button } from '@components/ui/button'; import { Input } from '@components/ui/input'; -import { useLogin } from '@hooks/useAuth'; +import { useLogin } from '@hooks/api/useAuth'; import { ZodError } from 'zod'; import { formatZodErrors } from '@lib/zod'; import type { ZodFormErrors } from '@type/zod'; @@ -15,15 +15,15 @@ const LoginPage = () => { const [password, setPassword] = useState(''); const [errors, setErrors] = useState({}); - const handleLogin = () => { + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + try { loginSchema.parse({ email, password }); setErrors({}); const credentials = { email, password }; login(credentials); - // TODO: zustand로 인증 상태관리 (useLogin 훅에서 처리) - // TODO: 메인페이지로 리다이렉트 (useLogin 훅에서 처리) } catch (error) { if (error instanceof ZodError) { const formattedErrors = formatZodErrors(error); @@ -34,32 +34,34 @@ const LoginPage = () => { return ( -
    - - setEmail(e.target.value)} - /> - {errors.email && ( -

    {errors.email}

    - )} -
    -
    - - setPassword(e.target.value)} - /> - {errors.password && ( -

    {errors.password}

    - )} -
    - +
    +
    + + setEmail(e.target.value)} + /> + {errors.email && ( +

    {errors.email}

    + )} +
    +
    + + setPassword(e.target.value)} + /> + {errors.password && ( +

    {errors.password}

    + )} +
    + +
    ); }; diff --git a/src/pages/MainPage.tsx b/src/pages/MainPage.tsx index f5d66c6..466f710 100644 --- a/src/pages/MainPage.tsx +++ b/src/pages/MainPage.tsx @@ -1,7 +1,8 @@ import { Navigate } from 'react-router-dom'; +import { ROUTES } from '@constants/routes'; const MainPage = () => { - return ; + return ; }; export default MainPage; diff --git a/src/pages/SignupPage.tsx b/src/pages/SignupPage.tsx index 0c9c3bf..29635ee 100644 --- a/src/pages/SignupPage.tsx +++ b/src/pages/SignupPage.tsx @@ -5,7 +5,7 @@ import { ZodError } from 'zod'; import { formatZodErrors } from '@lib/zod'; import type { ZodFormErrors } from '@type/zod'; import { signupSchema } from '@schema/auth'; -import { useSignup } from '@hooks/useAuth'; +import { useSignup } from '@hooks/api/useAuth'; import AuthLayout from '@components/template/auth/AuthLayout'; const SignupPage = () => { @@ -27,7 +27,9 @@ const SignupPage = () => { })); }; - const handleSignup = () => { + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + try { signupSchema.parse(formData); setErrors({}); @@ -48,63 +50,67 @@ const SignupPage = () => { return ( -
    - - - {errors.email && ( -

    {errors.email}

    - )} -
    +
    +
    + + + {errors.email && ( +

    {errors.email}

    + )} +
    -
    - - - {errors.password && ( -

    {errors.password}

    - )} -
    +
    + + + {errors.password && ( +

    {errors.password}

    + )} +
    -
    - - - {errors.passwordConfirm && ( -

    {errors.passwordConfirm}

    - )} -
    +
    + + + {errors.passwordConfirm && ( +

    + {errors.passwordConfirm} +

    + )} +
    -
    - - - {errors.name && ( -

    {errors.name}

    - )} -
    +
    + + + {errors.name && ( +

    {errors.name}

    + )} +
    - + +
    ); }; diff --git a/src/pages/TransactionsPage.tsx b/src/pages/TransactionsPage.tsx index edd1c82..a78470c 100644 --- a/src/pages/TransactionsPage.tsx +++ b/src/pages/TransactionsPage.tsx @@ -1,17 +1,114 @@ import Loader from '@components/template/Loader'; -import { useTransactions } from '@hooks/useTransaction'; +import { usePayments } from '@hooks/api/useTransaction'; import Transactions from '@components/template/Transactions'; import Error from '@components/template/Error'; import { useAuthStore } from '@store/authStore'; +import { useState, useEffect } from 'react'; +import type { Payment } from '@type/transaction'; +import { Button } from '@components/ui/button'; +import { Input } from '@components/ui/input'; + +const initialSearchState = { + paymentKey: '', + startDate: '', + endDate: '', + status: '', +}; + const TransactionsPage = () => { - const { data, isLoading, isError } = useTransactions(); const { auth } = useAuthStore(); - console.log(auth); + const accessToken = auth!.accessToken; + + const [page, setPage] = useState(0); + const [payments, setPayments] = useState([]); + const [filters, setFilters] = useState(initialSearchState); + const [searchInput, setSearchInput] = useState(initialSearchState); + + const { data, isLoading, isError } = usePayments(accessToken, page, filters); + + const handleLoadMore = () => { + setPage((prevPage) => prevPage + 1); + }; + + const handleSearch = (e: React.FormEvent) => { + e.preventDefault(); + setPage(0); + setFilters(searchInput); + }; + + useEffect(() => { + if (Array.isArray(data?.data?.payments)) { + if (page === 0) { + // 첫 페이지일 경우 데이터 초기화 + setPayments(data.data.payments); + } else { + // 그 외의 경우 데이터 추가 + setPayments((prevPayments) => [...prevPayments, ...data.data.payments]); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [data]); if (isLoading) return ; else if (isError) return ; else { - return ; + return ( + <> +
    +
      +
    • + + setSearchInput((prev) => ({ + ...prev, + paymentKey: e.target.value, + })) + } + /> +
    • + +
    • + + setSearchInput((prev) => ({ + ...prev, + startDate: e.target.value, + endDate: e.target.value, + })) + } + /> +
    • + +
    • + +
    • +
    +
    + + {payments.length > 0 ? ( + <> + + {Array.isArray(data?.data?.payments) && + data.data.payments.length > 0 && ( + + )} + + ) : ( +
    + 데이터가 없습니다 +
    + )} + + ); } }; diff --git a/src/router.tsx b/src/router.tsx index 721da36..67ba931 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -1,6 +1,8 @@ import Layout from '@components/template/Layout'; import { lazy } from 'react'; import { createBrowserRouter } from 'react-router-dom'; +import { ProtectedRoute } from '@components/template/auth/ProtectedRoute'; +import { ROUTES } from '@constants/routes'; const MainPage = lazy(() => import('@pages/MainPage').then((module) => ({ default: module.default })), @@ -13,8 +15,10 @@ const TransactionsPage = lazy(() => default: module.default, })), ); -const ApiKeysPage = lazy(() => - import('@pages/ApiKeysPage').then((module) => ({ default: module.default })), +const KeyManagementPage = lazy(() => + import('@pages/KeyManagementPage').then((module) => ({ + default: module.default, + })), ); const SignupPage = lazy(() => import('@pages/SignupPage').then((module) => ({ default: module.default })), @@ -22,28 +26,40 @@ const SignupPage = lazy(() => const routes = [ { - path: '/login', + path: ROUTES.LOGIN, element: , }, { - path: '/signup', + path: ROUTES.SIGNUP, element: , }, { - path: '/', + path: ROUTES.MAIN, element: , children: [ { - path: '/', - element: , + path: ROUTES.MAIN, + element: ( + + + + ), }, { - path: '/transactions', - element: , + path: ROUTES.TRANSACTIONS, + element: ( + + + + ), }, { - path: '/api-keys', - element: , + path: ROUTES.KEY_MANAGEMENT, + element: ( + + + + ), }, ], }, diff --git a/src/store/authStore.ts b/src/store/authStore.ts index 0f235f8..8b8d27e 100644 --- a/src/store/authStore.ts +++ b/src/store/authStore.ts @@ -1,7 +1,30 @@ import { create } from 'zustand'; import type { AuthState } from '@type/zustand'; +import type { NavigateFunction } from 'react-router-dom'; + +const getStoredAuth = () => { + const storedAuth = sessionStorage.getItem('auth'); + return storedAuth ? JSON.parse(storedAuth) : null; +}; export const useAuthStore = create((set) => ({ auth: null, setAuth: (auth) => set({ auth }), + navigate: null as NavigateFunction | null, + logout: () => { + sessionStorage.removeItem('auth'); + set({ auth: null }); + + const state = useAuthStore.getState(); + if (state.navigate) state.navigate('/login'); + }, })); + +const initializeAuth = () => { + const auth = getStoredAuth(); + if (auth) { + useAuthStore.getState().setAuth(auth); + } +}; + +initializeAuth(); diff --git a/src/types/auth.ts b/src/types/auth.ts index a87105e..2fcab6c 100644 --- a/src/types/auth.ts +++ b/src/types/auth.ts @@ -5,8 +5,8 @@ export type LoginReq = { export type Auth = { id: string; - token: string; name: string; + accessToken: string; }; export type LoginRes = { diff --git a/src/types/key.ts b/src/types/key.ts index cd83032..526919d 100644 --- a/src/types/key.ts +++ b/src/types/key.ts @@ -1,3 +1,8 @@ -export type KeyReq = { - id: string; +export type KeyReq = Record; + +export type KeyRes = { + ok: boolean; + data: { + apiKey: string; + }; }; diff --git a/src/types/transaction.ts b/src/types/transaction.ts index ccf8f0b..415cce2 100644 --- a/src/types/transaction.ts +++ b/src/types/transaction.ts @@ -1,15 +1,32 @@ -export type Transaction = { - id: number; +export interface Payment { paymentKey: string; - amount: number; - status: string; - reason: string; - createdAt: string; - updatedAt: string; -}; + cardNumber: string; + accountId: string; + transactions: { + id: string; + paymentKey: string; + amount: number; + status: string; + reason: string; + requestedAt: string; + completedAt: string; + }[]; + paymentType: string; + orderId: string; + orderName: string; +} -export interface TransactionResponse { +export interface PaymentResponse { data: { - transactions: Transaction[]; + payments: Payment[]; }; } + +export interface FlattenedPayment { + paymentKey: string; + completedAt: string; + orderName: string; + cardNumber: string; + amount: number; + status: string; +} diff --git a/src/types/zustand.ts b/src/types/zustand.ts index 8d86ef0..31e5de9 100644 --- a/src/types/zustand.ts +++ b/src/types/zustand.ts @@ -1,6 +1,9 @@ import type { Auth } from '@type/auth'; +import type { NavigateFunction } from 'react-router-dom'; -export type AuthState = { +export interface AuthState { auth: Auth | null; setAuth: (auth: Auth) => void; -}; + logout: () => void; + navigate: NavigateFunction | null; +} diff --git a/vite.config.ts b/vite.config.ts index 2c480a6..9caa3b1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -19,16 +19,4 @@ export default defineConfig({ '@store': path.resolve(__dirname, './src/store'), }, }, - - server: { - proxy: { - '/api': { - target: 'https://backoffice.pay-200.com', - changeOrigin: true, - rewrite: (path) => path.replace(/^\/api/, ''), - secure: false, - ws: true, - }, - }, - }, }); diff --git a/yarn.lock b/yarn.lock index 13cb43e..2552951 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,28 +7,6 @@ resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== -"@bundled-es-modules/cookie@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz#b41376af6a06b3e32a15241d927b840a9b4de507" - integrity sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw== - dependencies: - cookie "^0.7.2" - -"@bundled-es-modules/statuses@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz#761d10f44e51a94902c4da48675b71a76cc98872" - integrity sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg== - dependencies: - statuses "^2.0.1" - -"@bundled-es-modules/tough-cookie@^0.1.6": - version "0.1.6" - resolved "https://registry.yarnpkg.com/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz#fa9cd3cedfeecd6783e8b0d378b4a99e52bde5d3" - integrity sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw== - dependencies: - "@types/tough-cookie" "^4.0.5" - tough-cookie "^4.1.4" - "@esbuild/aix-ppc64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" @@ -337,6 +315,33 @@ "@eslint/core" "^0.10.0" levn "^0.4.1" +"@floating-ui/core@^1.6.0": + version "1.6.9" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.9.tgz#64d1da251433019dafa091de9b2886ff35ec14e6" + integrity sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw== + dependencies: + "@floating-ui/utils" "^0.2.9" + +"@floating-ui/dom@^1.0.0": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.13.tgz#a8a938532aea27a95121ec16e667a7cbe8c59e34" + integrity sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w== + dependencies: + "@floating-ui/core" "^1.6.0" + "@floating-ui/utils" "^0.2.9" + +"@floating-ui/react-dom@^2.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31" + integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A== + dependencies: + "@floating-ui/dom" "^1.0.0" + +"@floating-ui/utils@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429" + integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg== + "@humanfs/core@^0.19.1": version "0.19.1" resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" @@ -365,38 +370,6 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b" integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== -"@inquirer/confirm@^5.0.0": - version "5.1.5" - resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-5.1.5.tgz#0e6bf86794f69f849667ee38815608d6cd5917ba" - integrity sha512-ZB2Cz8KeMINUvoeDi7IrvghaVkYT2RB0Zb31EaLWOE87u276w4wnApv0SH2qWaJ3r0VSUa3BIuz7qAV2ZvsZlg== - dependencies: - "@inquirer/core" "^10.1.6" - "@inquirer/type" "^3.0.4" - -"@inquirer/core@^10.1.6": - version "10.1.6" - resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-10.1.6.tgz#2a92a219cb48c81453e145a5040d0e04f7df1aa2" - integrity sha512-Bwh/Zk6URrHwZnSSzAZAKH7YgGYi0xICIBDFOqBQoXNNAzBHw/bgXgLmChfp+GyR3PnChcTbiCTZGC6YJNJkMA== - dependencies: - "@inquirer/figures" "^1.0.10" - "@inquirer/type" "^3.0.4" - ansi-escapes "^4.3.2" - cli-width "^4.1.0" - mute-stream "^2.0.0" - signal-exit "^4.1.0" - wrap-ansi "^6.2.0" - yoctocolors-cjs "^2.1.2" - -"@inquirer/figures@^1.0.10": - version "1.0.10" - resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.10.tgz#e3676a51c9c51aaabcd6ba18a28e82b98417db37" - integrity sha512-Ey6176gZmeqZuY/W/nZiUyvmb1/qInjcpiZjXWi6nON+nxJpD1bxtSoBxNliGISae32n6OwbY+TSXPZ1CfS4bw== - -"@inquirer/type@^3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-3.0.4.tgz#fa5f9e91a0abf3c9e93d3e1990ecb891d8195cf2" - integrity sha512-2MNFrDY8jkFYc9Il9DgLsHhMzuHnOYM1+CUYVWbzu9oT0hC7V7EcYvdCKeoll/Fcci04A+ERZ9wcc7cQ8lTkIA== - "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -441,18 +414,6 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@mswjs/interceptors@^0.37.0": - version "0.37.6" - resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.37.6.tgz#2635319b7a81934e1ef1b5593ef7910347e2b761" - integrity sha512-wK+5pLK5XFmgtH3aQ2YVvA3HohS3xqV/OxuVOdNx9Wpnz7VE/fnC+e1A7ln6LFYeck7gOJ/dsZV6OLplOtAJ2w== - dependencies: - "@open-draft/deferred-promise" "^2.2.0" - "@open-draft/logger" "^0.3.0" - "@open-draft/until" "^2.0.0" - is-node-process "^1.2.0" - outvariant "^1.4.3" - strict-event-emitter "^0.5.1" - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -474,24 +435,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@open-draft/deferred-promise@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" - integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA== - -"@open-draft/logger@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@open-draft/logger/-/logger-0.3.0.tgz#2b3ab1242b360aa0adb28b85f5d7da1c133a0954" - integrity sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ== - dependencies: - is-node-process "^1.2.0" - outvariant "^1.4.0" - -"@open-draft/until@^2.0.0", "@open-draft/until@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-2.1.0.tgz#0acf32f470af2ceaf47f095cdecd40d68666efda" - integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== - "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -502,11 +445,23 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== +"@radix-ui/number@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.1.0.tgz#1e95610461a09cdf8bb05c152e76ca1278d5da46" + integrity sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ== + "@radix-ui/primitive@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.1.tgz#fc169732d755c7fbad33ba8d0cd7fd10c90dc8e3" integrity sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA== +"@radix-ui/react-arrow@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.2.tgz#30c0d574d7bb10eed55cd7007b92d38b03c6b2ab" + integrity sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg== + dependencies: + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-collection@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.2.tgz#b45eccca1cb902fd078b237316bd9fa81e621e15" @@ -527,6 +482,11 @@ resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a" integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q== +"@radix-ui/react-direction@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc" + integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg== + "@radix-ui/react-dismissable-layer@1.1.5": version "1.1.5" resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz#96dde2be078c694a621e55e047406c58cd5fe774" @@ -538,6 +498,27 @@ "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-escape-keydown" "1.1.0" +"@radix-ui/react-focus-guards@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe" + integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg== + +"@radix-ui/react-focus-scope@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz#c0a4519cd95c772606a82fc5b96226cd7fdd2602" + integrity sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA== + dependencies: + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + +"@radix-ui/react-id@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" + integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-label@^2.1.2": version "2.1.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-2.1.2.tgz#994a5d815c2ff46e151410ae4e301f1b639f9971" @@ -545,6 +526,22 @@ dependencies: "@radix-ui/react-primitive" "2.0.2" +"@radix-ui/react-popper@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.2.tgz#d2e1ee5a9b24419c5936a1b7f6f472b7b412b029" + integrity sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA== + dependencies: + "@floating-ui/react-dom" "^2.0.0" + "@radix-ui/react-arrow" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-rect" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + "@radix-ui/rect" "1.1.0" + "@radix-ui/react-portal@1.1.4": version "1.1.4" resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.4.tgz#ff5401ff63c8a825c46eea96d3aef66074b8c0c8" @@ -568,6 +565,33 @@ dependencies: "@radix-ui/react-slot" "1.1.2" +"@radix-ui/react-select@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-select/-/react-select-2.1.6.tgz#79c07cac4de0188e6f7afb2720a87a0405d88849" + integrity sha512-T6ajELxRvTuAMWH0YmRJ1qez+x4/7Nq7QIx7zJ0VK3qaEWdnWpNbEDnmWldG1zBDwqrLy5aLMUWcoGirVj5kMg== + dependencies: + "@radix-ui/number" "1.1.0" + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-collection" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-focus-guards" "1.1.1" + "@radix-ui/react-focus-scope" "1.1.2" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.2" + "@radix-ui/react-portal" "1.1.4" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-previous" "1.1.0" + "@radix-ui/react-visually-hidden" "1.1.2" + aria-hidden "^1.2.4" + react-remove-scroll "^2.6.3" + "@radix-ui/react-slot@1.1.2", "@radix-ui/react-slot@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.2.tgz#daffff7b2bfe99ade63b5168407680b93c00e1c6" @@ -617,6 +641,25 @@ resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== +"@radix-ui/react-use-previous@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz#d4dd37b05520f1d996a384eb469320c2ada8377c" + integrity sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og== + +"@radix-ui/react-use-rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88" + integrity sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ== + dependencies: + "@radix-ui/rect" "1.1.0" + +"@radix-ui/react-use-size@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b" + integrity sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-visually-hidden@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.2.tgz#8f6025507eb5d8b4b3215ebfd2c71a6632323a62" @@ -624,6 +667,11 @@ dependencies: "@radix-ui/react-primitive" "2.0.2" +"@radix-ui/rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438" + integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg== + "@rollup/rollup-android-arm-eabi@4.34.6": version "4.34.6" resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.6.tgz#9b726b4dcafb9332991e9ca49d54bafc71d9d87f" @@ -852,16 +900,6 @@ "@types/prop-types" "*" csstype "^3.0.2" -"@types/statuses@^2.0.4": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@types/statuses/-/statuses-2.0.5.tgz#f61ab46d5352fd73c863a1ea4e1cef3b0b51ae63" - integrity sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A== - -"@types/tough-cookie@^4.0.5": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" - integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== - "@typescript-eslint/eslint-plugin@8.23.0": version "8.23.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz#7745f4e3e4a7ae5f6f73fefcd856fd6a074189b7" @@ -1029,13 +1067,6 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-escapes@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - ansi-escapes@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.0.0.tgz#00fc19f491bbb18e1d481b97868204f92109bfe7" @@ -1088,6 +1119,13 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +aria-hidden@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522" + integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A== + dependencies: + tslib "^2.0.0" + assertion-error@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" @@ -1233,20 +1271,6 @@ cli-truncate@^4.0.0: slice-ansi "^5.0.0" string-width "^7.0.0" -cli-width@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" - integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - clsx@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" @@ -1284,11 +1308,6 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -cookie@^0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" - integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== - cookie@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-1.0.2.tgz#27360701532116bd3f1f9416929d176afe1e4610" @@ -1330,6 +1349,11 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +detect-node-es@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" + integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== + didyoumean@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" @@ -1435,7 +1459,7 @@ esbuild@^0.24.2: "@esbuild/win32-ia32" "0.24.2" "@esbuild/win32-x64" "0.24.2" -escalade@^3.1.1, escalade@^3.2.0: +escalade@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== @@ -1687,16 +1711,16 @@ function-bind@^1.1.2: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - get-east-asian-width@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz#21b4071ee58ed04ee0db653371b55b4299875389" integrity sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ== +get-nonce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== + get-stream@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" @@ -1743,11 +1767,6 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -graphql@^16.8.1: - version "16.10.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.10.0.tgz#24c01ae0af6b11ea87bf55694429198aaa8e220c" - integrity sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ== - has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" @@ -1760,11 +1779,6 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" -headers-polyfill@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-4.0.3.tgz#922a0155de30ecc1f785bcf04be77844ca95ad07" - integrity sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ== - human-signals@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" @@ -1836,11 +1850,6 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-node-process@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134" - integrity sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw== - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -2059,35 +2068,6 @@ ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -msw@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/msw/-/msw-2.7.0.tgz#d13ff87f7e018fc4c359800ff72ba5017033fb56" - integrity sha512-BIodwZ19RWfCbYTxWTUfTXc+sg4OwjCAgxU1ZsgmggX/7S3LdUifsbUPJs61j0rWb19CZRGY5if77duhc0uXzw== - dependencies: - "@bundled-es-modules/cookie" "^2.0.1" - "@bundled-es-modules/statuses" "^1.0.1" - "@bundled-es-modules/tough-cookie" "^0.1.6" - "@inquirer/confirm" "^5.0.0" - "@mswjs/interceptors" "^0.37.0" - "@open-draft/deferred-promise" "^2.2.0" - "@open-draft/until" "^2.1.0" - "@types/cookie" "^0.6.0" - "@types/statuses" "^2.0.4" - graphql "^16.8.1" - headers-polyfill "^4.0.2" - is-node-process "^1.2.0" - outvariant "^1.4.3" - path-to-regexp "^6.3.0" - picocolors "^1.1.1" - strict-event-emitter "^0.5.1" - type-fest "^4.26.1" - yargs "^17.7.2" - -mute-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-2.0.0.tgz#a5446fc0c512b71c83c44d908d5c7b7b4c493b2b" - integrity sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA== - mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -2165,11 +2145,6 @@ optionator@^0.9.3: type-check "^0.4.0" word-wrap "^1.2.5" -outvariant@^1.4.0, outvariant@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.3.tgz#221c1bfc093e8fec7075497e7799fdbf43d14873" - integrity sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA== - p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" @@ -2224,11 +2199,6 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4" - integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== - pathe@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" @@ -2334,23 +2304,11 @@ prettier@^3.4.2: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.0.tgz#50325a28887c6dfdf2ca3f8eaba02b66a8429ca7" integrity sha512-quyMrVt6svPS7CjQ9gKb3GLEX/rl3BCL2oa/QkNcXv4YNVBC9olt3s+H7ukto06q7B1Qz46PbrKLO34PR6vXcA== -psl@^1.1.33: - version "1.15.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" - integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== - dependencies: - punycode "^2.3.1" - -punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: +punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -querystringify@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -2364,6 +2322,25 @@ react-dom@^18.3.1: loose-envify "^1.1.0" scheduler "^0.23.2" +react-remove-scroll-bar@^2.3.7: + version "2.3.8" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" + integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== + dependencies: + react-style-singleton "^2.2.2" + tslib "^2.0.0" + +react-remove-scroll@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz#df02cde56d5f2731e058531f8ffd7f9adec91ac2" + integrity sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ== + dependencies: + react-remove-scroll-bar "^2.3.7" + react-style-singleton "^2.2.3" + tslib "^2.1.0" + use-callback-ref "^1.3.3" + use-sidecar "^1.1.3" + react-router-dom@^7.1.1: version "7.1.5" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-7.1.5.tgz#6b706a5503c01d99c1af69336a7de2e21cadd339" @@ -2381,6 +2358,14 @@ react-router@7.1.5: set-cookie-parser "^2.6.0" turbo-stream "2.4.0" +react-style-singleton@^2.2.2, react-style-singleton@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388" + integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ== + dependencies: + get-nonce "^1.0.0" + tslib "^2.0.0" + react@^18.3.1: version "18.3.1" resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" @@ -2402,16 +2387,6 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -2544,27 +2519,18 @@ stackback@0.0.2: resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== -statuses@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - std-env@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5" integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w== -strict-event-emitter@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" - integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== - string-argv@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0: + name string-width-cjs version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -2592,6 +2558,7 @@ string-width@^7.0.0: strip-ansi "^7.1.0" "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: + name strip-ansi-cjs version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -2727,16 +2694,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -tough-cookie@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" - integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== - dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.2.0" - url-parse "^1.5.3" - ts-api-utils@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.0.1.tgz#660729385b625b939aaa58054f45c058f33f10cd" @@ -2747,7 +2704,7 @@ ts-interface-checker@^0.1.9: resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== -tslib@^2.6.2: +tslib@^2.0.0, tslib@^2.1.0, tslib@^2.6.2: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -2764,16 +2721,6 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^4.26.1: - version "4.34.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.34.1.tgz#406a9c573cc51c3fbfee3c85742cf85c52860076" - integrity sha512-6kSc32kT0rbwxD6QL1CYe8IqdzN/J/ILMrNK+HMQCKH3insCDRY/3ITb0vcBss0a3t72fzh2YSzj8ko1HgwT3g== - typescript-eslint@^8.18.2: version "8.23.0" resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.23.0.tgz#796deb48f040146b68fcc8cb07db68b87219a8d2" @@ -2793,11 +2740,6 @@ undici-types@~6.20.0: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== -universalify@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" - integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== - update-browserslist-db@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz#97e9c96ab0ae7bcac08e9ae5151d26e6bc6b5580" @@ -2813,13 +2755,20 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url-parse@^1.5.3: - version "1.5.10" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== +use-callback-ref@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" + integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== + dependencies: + tslib "^2.0.0" + +use-sidecar@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb" + integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ== dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" + detect-node-es "^1.1.0" + tslib "^2.0.0" util-deprecate@^1.0.2: version "1.0.2" @@ -2905,7 +2854,7 @@ word-wrap@^1.2.5: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -2914,15 +2863,6 @@ word-wrap@^1.2.5: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -2941,44 +2881,16 @@ wrap-ansi@^9.0.0: string-width "^7.0.0" strip-ansi "^7.1.0" -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - yaml@^2.3.4, yaml@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.0.tgz#aef9bb617a64c937a9a748803786ad8d3ffe1e98" integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA== -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.7.2: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -yoctocolors-cjs@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz#f4b905a840a37506813a7acaa28febe97767a242" - integrity sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA== - zod@^3.24.1: version "3.24.1" resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.1.tgz#27445c912738c8ad1e9de1bea0359fa44d9d35ee"