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}
- )}
-
-
+
);
};
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}
- )}
-
+
);
};
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 (
+ <>
+
+
+ {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"