diff --git a/app/api/auth/login/route.tsx b/app/api/auth/login/route.tsx index 644f427..3c66c7c 100644 --- a/app/api/auth/login/route.tsx +++ b/app/api/auth/login/route.tsx @@ -1,5 +1,12 @@ import { NextResponse } from "next/server"; import { cookies } from "next/headers"; +import { SignJWT } from "jose"; + +// Secret key for JWT signing (in production, use environment variable) +const JWT_SECRET = new TextEncoder().encode(process.env.JWT_SECRET); + +// Token expiration time (in seconds) +const TOKEN_EXPIRY = 60 * 60 * 12; // 12 hours (in seconds) // This is your POST handler for the login endpoint export async function POST(request: Request) { @@ -15,20 +22,25 @@ export async function POST(request: Request) { // Mock authentication for demonstration purposes: if (email === "admin@example.com" && password === "password123") { - const authToken = "mock-jwt-token-12345"; // Replace with a real, securely generated token + // Create JWT token with expiration + const token = await new SignJWT({ + email, + role: "admin", + iat: Math.floor(Date.now() / 1000), // issued at + }) + .setProtectedHeader({ alg: "HS256" }) + .setIssuedAt() + .setExpirationTime(Math.floor(Date.now() / 1000) + TOKEN_EXPIRY) + .sign(JWT_SECRET); // Set the authentication token as an HTTP-only cookie // HTTP-only cookies are crucial for security as they cannot be accessed by client-side JavaScript, // which mitigates XSS attacks. - ( - await // Set the authentication token as an HTTP-only cookie - // HTTP-only cookies are crucial for security as they cannot be accessed by client-side JavaScript, - // which mitigates XSS attacks. - cookies() - ).set("auth_token", authToken, { + const cookieStore = await cookies(); + cookieStore.set("auth_token", token, { httpOnly: true, // IMPORTANT: Makes the cookie inaccessible to client-side scripts secure: process.env.NODE_ENV === "production", // Use secure in production (HTTPS) - maxAge: 60 * 60 * 24 * 7, // 1 week + maxAge: TOKEN_EXPIRY, // 24 hours path: "/", // Available across the entire site sameSite: "lax", // Protects against CSRF }); diff --git a/app/api/auth/status/route.ts b/app/api/auth/status/route.ts new file mode 100644 index 0000000..1ea1fdc --- /dev/null +++ b/app/api/auth/status/route.ts @@ -0,0 +1,76 @@ +import { NextResponse } from "next/server"; +import { cookies } from "next/headers"; +import { + validateToken, + isTokenExpired, + getTimeUntilExpiration, +} from "@/app/utils/auth"; + +export async function GET() { + try { + const cookieStore = await cookies(); + const token = cookieStore.get("auth_token")?.value; + + if (!token) { + return NextResponse.json( + { + isAuthenticated: false, + message: "No authentication token found", + }, + { status: 401 } + ); + } + + // Validate the token + const payload = await validateToken(token); + + if (!payload) { + return NextResponse.json( + { + isAuthenticated: false, + message: "Invalid authentication token", + }, + { status: 401 } + ); + } + + if (isTokenExpired(payload)) { + // Clear the expired cookie + cookieStore.delete("auth_token"); + + return NextResponse.json( + { + isAuthenticated: false, + message: "Authentication token has expired", + }, + { status: 401 } + ); + } + + // Token is valid and not expired + const timeUntilExpiration = getTimeUntilExpiration(payload); + + return NextResponse.json({ + isAuthenticated: true, + user: { + email: payload.email, + role: payload.role, + }, + tokenInfo: { + issuedAt: new Date(payload.iat * 1000).toISOString(), + expiresAt: new Date(payload.exp * 1000).toISOString(), + timeUntilExpiration: timeUntilExpiration, // in seconds + expiresInHours: Math.floor(timeUntilExpiration / 3600), + }, + }); + } catch (error) { + console.error("Auth status check error:", error); + return NextResponse.json( + { + isAuthenticated: false, + message: "Internal server error", + }, + { status: 500 } + ); + } +} diff --git a/app/api/dashboard/admin/mockData.ts b/app/api/dashboard/admin/mockData.ts new file mode 100644 index 0000000..2771499 --- /dev/null +++ b/app/api/dashboard/admin/mockData.ts @@ -0,0 +1,35 @@ +export const users = [ + { + merchantId: 100987998, + id: "bc6a8a55-13bc-4538-8255-cd0cec3bb4e9", + name: "Jacob", + username: "lspaddy", + firstName: "Paddy", + lastName: "Man", + email: "patrick@omegasys.eu", + phone: "", + jobTitle: "", + enabled: true, + authorities: [ + "ROLE_IIN", + "ROLE_FIRST_APPROVER", + "ROLE_RULES_ADMIN", + "ROLE_TRANSACTION_VIEWER", + "ROLE_IIN_ADMIN", + "ROLE_USER_PSP_ACCOUNT", + ], + allowedMerchantIds: [100987998], + created: "2025-05-04T15:32:48.432Z", + disabledBy: null, + disabledDate: null, + disabledReason: null, + incidentNotes: false, + lastLogin: "", + lastMandatoryUpdated: "2025-05-04T15:32:48.332Z", + marketingNewsletter: false, + releaseNotes: false, + requiredActions: ["CONFIGURE_TOTP", "UPDATE_PASSWORD"], + twoFactorCondition: "required", + twoFactorCredentials: [], + }, +]; diff --git a/app/api/dashboard/admin/users/[id]/route.ts b/app/api/dashboard/admin/users/[id]/route.ts new file mode 100644 index 0000000..abf2c5d --- /dev/null +++ b/app/api/dashboard/admin/users/[id]/route.ts @@ -0,0 +1,34 @@ +import { NextRequest, NextResponse } from "next/server"; +import { users } from "../../mockData"; + +export async function PUT( + request: NextRequest, + { params }: { params: { id: string } } +) { + const { id } = params; + + if (!id) { + return NextResponse.json({ error: "User ID is required" }, { status: 400 }); + } + + const body = await request.json(); + const { firstName, lastName, email, phone, role } = body; + + // Find the user by id + const userIndex = users.findIndex((u) => u.id === id); + if (userIndex === -1) { + return NextResponse.json({ error: "User not found" }, { status: 404 }); + } + + // Update the user fields + users[userIndex] = { + ...users[userIndex], + firstName: firstName ?? users[userIndex].firstName, + lastName: lastName ?? users[userIndex].lastName, + email: email ?? users[userIndex].email, + phone: phone ?? users[userIndex].phone, + authorities: role ? [role] : users[userIndex].authorities, + }; + + return NextResponse.json(users[userIndex], { status: 200 }); +} diff --git a/app/api/dashboard/admin/users/route.ts b/app/api/dashboard/admin/users/route.ts index 4f57d83..3dedddb 100644 --- a/app/api/dashboard/admin/users/route.ts +++ b/app/api/dashboard/admin/users/route.ts @@ -1,41 +1,6 @@ // app/api/dashboard/admin/users/route.ts import { NextRequest, NextResponse } from "next/server"; - -const users = [ - { - merchantId: 100987998, - id: "bc6a8a55-13bc-4538-8255-cd0cec3bb4e9", - name: "Jacob", - username: "lspaddy", - firstName: "Paddy", - lastName: "Man", - email: "patrick@omegasys.eu", - phone: "", - jobTitle: "", - enabled: true, - authorities: [ - "ROLE_IIN", - "ROLE_FIRST_APPROVER", - "ROLE_RULES_ADMIN", - "ROLE_TRANSACTION_VIEWER", - "ROLE_IIN_ADMIN", - "ROLE_USER_PSP_ACCOUNT", - ], - allowedMerchantIds: [100987998], - created: "2025-05-04T15:32:48.432Z", - disabledBy: null, - disabledDate: null, - disabledReason: null, - incidentNotes: false, - lastLogin: "", - lastMandatoryUpdated: "2025-05-04T15:32:48.332Z", - marketingNewsletter: false, - releaseNotes: false, - requiredActions: ["CONFIGURE_TOTP", "UPDATE_PASSWORD"], - twoFactorCondition: "required", - twoFactorCredentials: [], - }, -]; +import { users } from "../mockData"; export async function GET() { return NextResponse.json(users); @@ -76,4 +41,4 @@ export async function POST(request: NextRequest) { users.push(newUser); return NextResponse.json(users, { status: 201 }); -} \ No newline at end of file +} diff --git a/app/api/dashboard/approve/mockData.ts b/app/api/dashboard/approve/mockData.ts new file mode 100644 index 0000000..8805e9a --- /dev/null +++ b/app/api/dashboard/approve/mockData.ts @@ -0,0 +1,119 @@ +import { TableColumn } from "@/app/features/Pages/Approve/Approve"; + +type UserRow = { + id: number; + merchantId: string; + txId: string; + userEmail: string; + kycStatus: string; +}; + +export const approveRows: UserRow[] = [ + { + id: 17, + merchantId: "100987998", + txId: "1049078821", + userEmail: "dhkheni1@yopmail.com", + kycStatus: "N/A", + }, + { + id: 12, + merchantId: "100987998", + txId: "1049078822", + userEmail: "dhkheni2@yopmail.com", + kycStatus: "Pending", + }, + { + id: 11, + merchantId: "100232399", + txId: "1049078822", + userEmail: "dhkheni2@yopmail.com", + kycStatus: "Pending", + }, + { + id: 10, + merchantId: "100232399", + txId: "1049078822", + userEmail: "dhkheni2@yopmail.com", + kycStatus: "Pending", + }, + { + id: 1, + merchantId: "100232399", + txId: "1049078822", + userEmail: "dhkheni2@yopmail.com", + kycStatus: "Pending", + }, + { + id: 2, + merchantId: "101907999", + txId: "1049078822", + userEmail: "dhkheni2@yopmail.com", + kycStatus: "Pending", + }, + { + id: 3, + merchantId: "101907999", + txId: "1049078822", + userEmail: "dhkheni2@yopmail.com", + kycStatus: "Pending", + }, + { + id: 4, + merchantId: "10552342", + txId: "1049078822", + userEmail: "dhkheni2@yopmail.com", + kycStatus: "Pending", + }, + { + id: 5, + merchantId: "10552342", + txId: "1049078822", + userEmail: "dhkheni2@yopmail.com", + kycStatus: "Pending", + }, + { + id: 6, + merchantId: "10552342", + txId: "1049078822", + userEmail: "dhkheni2@yopmail.com", + kycStatus: "Pending", + }, + { + id: 7, + merchantId: "10552342", + txId: "1049078822", + userEmail: "dhkheni2@yopmail.com", + kycStatus: "Pending", + }, + { + id: 8, + merchantId: "10552342", + txId: "1049078822", + userEmail: "dhkheni2@yopmail.com", + kycStatus: "Pending", + }, +]; + +export const approveColumns: TableColumn[] = [ + { field: "merchantId", headerName: "Merchant ID" }, + { field: "txId", headerName: "Transaction ID" }, + { field: "userEmail", headerName: "User Email" }, + { field: "kycStatus", headerName: "KYC Status" }, +]; + +export const approveActions = [ + { value: "approve", label: "Approve" }, + { value: "reject", label: "Reject" }, + { value: "forceSuccessful", label: "Force Successful" }, + { value: "forceFiled", label: "Force Field" }, + { value: "forceInconsistent", label: "Force Inconsistent" }, + { value: "forceStatus", label: "Force Status" }, + { value: "partialCapture", label: "Partial Capture" }, + { value: "capture", label: "Capture" }, + { value: "extendedAuth", label: "Extended uth" }, + { value: "partialRefund", label: "Partial Refund" }, + { value: "refund", label: "Refund" }, + { value: "void", label: "Void" }, + { value: "registerCorrection", label: "Register Correction" }, +]; diff --git a/app/api/dashboard/approve/route.ts b/app/api/dashboard/approve/route.ts new file mode 100644 index 0000000..440fa17 --- /dev/null +++ b/app/api/dashboard/approve/route.ts @@ -0,0 +1,20 @@ +import { NextRequest, NextResponse } from "next/server"; +import { approveRows, approveColumns, approveActions } from "./mockData"; + +export async function GET(request: NextRequest) { + const { searchParams } = new URL(request.url); + const merchantId = searchParams.get("merchantId"); + let filteredApproveRows = [...approveRows]; + + if (merchantId) { + filteredApproveRows = filteredApproveRows.filter((tx) => + tx.merchantId.toString().includes(merchantId), + ); + } + + return NextResponse.json({ + rows: filteredApproveRows, + columns: approveColumns, + actions: approveActions, + }); +} diff --git a/app/api/dashboard/audits/route.ts b/app/api/dashboard/audits/route.ts index c73fba3..adab442 100644 --- a/app/api/dashboard/audits/route.ts +++ b/app/api/dashboard/audits/route.ts @@ -1,6 +1,5 @@ import { NextRequest, NextResponse } from "next/server"; import { AuditColumns, AuditData, AuditSearchLabels } from "./mockData"; -import { formatToDateTimeString } from "@/app/utils/formatDate"; export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url); @@ -9,13 +8,16 @@ export async function GET(request: NextRequest) { const affectedUserId = searchParams.get("affectedUserId"); const adminId = searchParams.get("adminId"); const adminUsername = searchParams.get("adminUsername"); - const timeStampOfTheAction = searchParams.get("dateTime"); + + const dateTimeStart = searchParams.get("dateTime_start"); + const dateTimeEnd = searchParams.get("dateTime_end"); let filteredRows = [...AuditData]; if (actionType) { filteredRows = filteredRows.filter( - (tx) => tx.actionType.toLocaleLowerCase() === actionType.toLocaleLowerCase(), + (tx) => + tx.actionType.toLocaleLowerCase() === actionType.toLocaleLowerCase(), ); } @@ -26,9 +28,7 @@ export async function GET(request: NextRequest) { } if (adminId) { - filteredRows = filteredRows.filter( - (tx) => tx.adminId === adminId, - ); + filteredRows = filteredRows.filter((tx) => tx.adminId === adminId); } if (adminUsername) { filteredRows = filteredRows.filter( @@ -36,12 +36,30 @@ export async function GET(request: NextRequest) { ); } - if (timeStampOfTheAction) { - filteredRows = filteredRows.filter( - (tx) => - tx.timeStampOfTheAction.split(" ")[0] === - formatToDateTimeString(timeStampOfTheAction).split(" ")[0], - ); + if (dateTimeStart && dateTimeEnd) { + const start = new Date(dateTimeStart); + const end = new Date(dateTimeEnd); + + // Validate the date range to ensure it’s correct + if (isNaN(start.getTime()) || isNaN(end.getTime())) { + return NextResponse.json( + { + error: "Invalid date range", + }, + { status: 400 }, + ); + } + + filteredRows = filteredRows.filter((tx) => { + const txDate = new Date(tx.timeStampOfTheAction); + + // Validate if the timestamp is a valid date + if (isNaN(txDate.getTime())) { + return false; // Skip invalid dates + } + + return txDate >= start && txDate <= end; + }); } return NextResponse.json({ diff --git a/app/api/dashboard/transactions/all/mockData.ts b/app/api/dashboard/transactions/all/mockData.ts new file mode 100644 index 0000000..5997ea2 --- /dev/null +++ b/app/api/dashboard/transactions/all/mockData.ts @@ -0,0 +1,265 @@ +import { GridColDef } from "@mui/x-data-grid"; + +export const allTransactionDummyData = [ + { + id: 1, + userId: 17, + merchandId: 100987998, + transactionId: 1049131973, + depositMethod: "Card", + status: "Completed", + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], + amount: 4000, + currency: "EUR", + dateTime: "2025-06-18 10:10:30", + errorInfo: "-", + fraudScore: "frad score 1234", + }, + { + id: 2, + userId: 17, + merchandId: 100987998, + transactionId: 1049131973, + depositMethod: "Card", + status: "Completed", + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], + amount: 4000, + currency: "EUR", + dateTime: "2025-06-18 10:10:30", + errorInfo: "-", + fraudScore: "frad score 1234", + }, + { + id: 3, + userId: 17, + merchandId: 100987997, + transactionId: 1049131973, + depositMethod: "Card", + status: "Completed", + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], + amount: 4000, + currency: "EUR", + dateTime: "2025-06-18 10:10:30", + errorInfo: "-", + fraudScore: "frad score 1234", + }, + { + id: 4, + userId: 19, + merchandId: 100987997, + transactionId: 1049136973, + depositMethod: "Card", + status: "Completed", + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], + amount: 4000, + currency: "EUR", + dateTime: "2025-06-18 10:10:30", + errorInfo: "-", + fraudScore: "frad score 1234", + }, + { + id: 5, + userId: 19, + merchandId: 100987998, + transactionId: 1049131973, + depositMethod: "Card", + status: "Completed", + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], + amount: 4000, + currency: "EUR", + dateTime: "2025-06-18 10:10:30", + errorInfo: "-", + fraudScore: "frad score 1234", + }, + { + id: 6, + userId: 27, + merchandId: 100987997, + transactionId: 1049131973, + depositMethod: "Card", + status: "Pending", + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], + amount: 4000, + currency: "EUR", + dateTime: "2025-06-18 10:10:30", + errorInfo: "-", + fraudScore: "frad score 1234", + }, + { + id: 7, + userId: 175, + merchandId: 100987938, + transactionId: 1049136973, + depositMethod: "Card", + status: "Pending", + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], + amount: 4000, + currency: "EUR", + dateTime: "2025-06-18 10:10:30", + errorInfo: "-", + fraudScore: "frad score 1234", + }, + { + id: 8, + userId: 172, + merchandId: 100987938, + transactionId: 1049131973, + depositMethod: "Card", + status: "Pending", + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], + amount: 4000, + currency: "EUR", + dateTime: "2025-06-12 10:10:30", + errorInfo: "-", + fraudScore: "frad score 1234", + }, + { + id: 9, + userId: 174, + merchandId: 100987938, + transactionId: 1049131973, + depositMethod: "Bank Transfer", + status: "Inprogress", + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], + amount: 4000, + currency: "EUR", + dateTime: "2025-06-17 10:10:30", + errorInfo: "-", + fraudScore: "frad score 1234", + }, + { + id: 10, + userId: 7, + merchandId: 100987998, + transactionId: 1049131973, + depositMethod: "Bank Transfer", + status: "Inprogress", + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], + amount: 4000, + currency: "EUR", + dateTime: "2025-06-17 10:10:30", + errorInfo: "-", + fraudScore: "frad score 1234", + }, + { + id: 11, + userId: 1, + merchandId: 100987998, + transactionId: 1049131973, + depositMethod: "Bank Transfer", + status: "Error", + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], + amount: 4000, + currency: "EUR", + dateTime: "2025-06-17 10:10:30", + errorInfo: "-", + fraudScore: "frad score 1234", + }, +]; + +export const allTransactionsColumns: GridColDef[] = [ + { field: "userId", headerName: "User ID", width: 130 }, + { field: "merchandId", headerName: "Merchant ID", width: 130 }, + { field: "transactionId", headerName: "Transaction ID", width: 130 }, + { field: "depositMethod", headerName: "Deposit Method", width: 130 }, + { field: "status", headerName: "Status", width: 130 }, + // { field: "actions", headerName: "Actions", width: 150 }, + { field: "amount", headerName: "Amount", width: 130 }, + { field: "currency", headerName: "Currency", width: 130 }, + { field: "dateTime", headerName: "Date / Time", width: 130 }, + { field: "errorInfo", headerName: "Error Info", width: 130 }, + { field: "fraudScore", headerName: "Fraud Score", width: 130 }, +]; + +export const allTransactionsExtraColumns: GridColDef[] = [ + { field: "currency", headerName: "Currency", width: 130 }, + { field: "errorInfo", headerName: "Error Info", width: 130 }, + { field: "fraudScore", headerName: "Fraud Score", width: 130 }, +]; + +export const extraColumns = ["currency", "errorInfo", "fraudScore"] + + +export const allTransactionsSearchLabels = [ + { label: "User", field: "userId", type: "text" }, + { label: "Transaction ID", field: "transactionId", type: "text" }, + { + label: "Transaction Reference ID", + field: "transactionReferenceId", + type: "text", + }, + { + label: "Currency", + field: "currency", + type: "select", + options: ["USD", "EUR", "GBP"], + }, + { + label: "Status", + field: "status", + type: "select", + options: ["Pending", "Inprogress", "Completed", "Failed"], + }, + { + label: "Payment Method", + field: "depositMethod", + type: "select", + options: ["Card", "Bank Transfer"], + }, + { label: "Date / Time", field: "dateTime", type: "date" }, +]; diff --git a/app/api/dashboard/transactions/all/route.ts b/app/api/dashboard/transactions/all/route.ts new file mode 100644 index 0000000..0c41870 --- /dev/null +++ b/app/api/dashboard/transactions/all/route.ts @@ -0,0 +1,79 @@ +import { NextRequest, NextResponse } from "next/server"; +import { allTransactionDummyData, allTransactionsColumns, allTransactionsSearchLabels, extraColumns } from "./mockData"; + +// import { formatToDateTimeString } from "@/app/utils/formatDate"; + +export async function GET(request: NextRequest) { + const { searchParams } = new URL(request.url); + + const status = searchParams.get("status"); + const userId = searchParams.get("userId"); + const depositMethod = searchParams.get("depositMethod"); + const merchandId = searchParams.get("merchandId"); + const transactionId = searchParams.get("transactionId"); + // const dateTime = searchParams.get("dateTime"); + + const dateTimeStart = searchParams.get("dateTime_start"); + const dateTimeEnd = searchParams.get("dateTime_end"); + + let filteredTransactions = [...allTransactionDummyData]; + + if (userId) { + filteredTransactions = filteredTransactions.filter( + (tx) => tx.userId.toString() === userId, + ); + } + + if (status) { + filteredTransactions = filteredTransactions.filter( + (tx) => tx.status.toLowerCase() === status.toLowerCase(), + ); + } + + if (depositMethod) { + filteredTransactions = filteredTransactions.filter( + (tx) => tx.depositMethod.toLowerCase() === depositMethod.toLowerCase(), + ); + } + if (merchandId) { + filteredTransactions = filteredTransactions.filter( + (tx) => tx.merchandId.toString() === merchandId, + ); + } + if (transactionId) { + filteredTransactions = filteredTransactions.filter( + (tx) => tx.transactionId.toString() === transactionId, + ); + } + + if (dateTimeStart && dateTimeEnd) { + const start = new Date(dateTimeStart); + const end = new Date(dateTimeEnd); + + if (isNaN(start.getTime()) || isNaN(end.getTime())) { + return NextResponse.json( + { + error: "Invalid date range", + }, + { status: 400 }, + ); + } + + filteredTransactions = filteredTransactions.filter((tx) => { + const txDate = new Date(tx.dateTime); + + if (isNaN(txDate.getTime())) { + return false; + } + + return txDate >= start && txDate <= end; + }); + } + + return NextResponse.json({ + tableRows: filteredTransactions, + tableSearchLabels: allTransactionsSearchLabels, + tableColumns: allTransactionsColumns, + extraColumns: extraColumns, + }); +} diff --git a/app/api/dashboard/transactions/deposits/mockData.ts b/app/api/dashboard/transactions/deposits/mockData.ts index 98a37ba..720122f 100644 --- a/app/api/dashboard/transactions/deposits/mockData.ts +++ b/app/api/dashboard/transactions/deposits/mockData.ts @@ -8,12 +8,12 @@ export const depositTransactionDummyData = [ transactionId: 1049131973, depositMethod: "Card", status: "Completed", - options: [ - { value: "Pending", label: "Pending" }, - { value: "Completed", label: "Completed" }, - { value: "Inprogress", label: "Inprogress" }, - { value: "Error", label: "Error" }, - ], + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], amount: 4000, currency: "EUR", dateTime: "2025-06-18 10:10:30", @@ -27,12 +27,12 @@ export const depositTransactionDummyData = [ transactionId: 1049131973, depositMethod: "Card", status: "Completed", - options: [ - { value: "Pending", label: "Pending" }, - { value: "Completed", label: "Completed" }, - { value: "Inprogress", label: "Inprogress" }, - { value: "Error", label: "Error" }, - ], + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], amount: 4000, currency: "EUR", dateTime: "2025-06-18 10:10:30", @@ -46,12 +46,12 @@ export const depositTransactionDummyData = [ transactionId: 1049131973, depositMethod: "Card", status: "Completed", - options: [ - { value: "Pending", label: "Pending" }, - { value: "Completed", label: "Completed" }, - { value: "Inprogress", label: "Inprogress" }, - { value: "Error", label: "Error" }, - ], + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], amount: 4000, currency: "EUR", dateTime: "2025-06-18 10:10:30", @@ -65,12 +65,12 @@ export const depositTransactionDummyData = [ transactionId: 1049136973, depositMethod: "Card", status: "Completed", - options: [ - { value: "Pending", label: "Pending" }, - { value: "Completed", label: "Completed" }, - { value: "Inprogress", label: "Inprogress" }, - { value: "Error", label: "Error" }, - ], + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], amount: 4000, currency: "EUR", dateTime: "2025-06-18 10:10:30", @@ -84,12 +84,12 @@ export const depositTransactionDummyData = [ transactionId: 1049131973, depositMethod: "Card", status: "Completed", - options: [ - { value: "Pending", label: "Pending" }, - { value: "Completed", label: "Completed" }, - { value: "Inprogress", label: "Inprogress" }, - { value: "Error", label: "Error" }, - ], + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], amount: 4000, currency: "EUR", dateTime: "2025-06-18 10:10:30", @@ -103,12 +103,12 @@ export const depositTransactionDummyData = [ transactionId: 1049131973, depositMethod: "Card", status: "Pending", - options: [ - { value: "Pending", label: "Pending" }, - { value: "Completed", label: "Completed" }, - { value: "Inprogress", label: "Inprogress" }, - { value: "Error", label: "Error" }, - ], + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], amount: 4000, currency: "EUR", dateTime: "2025-06-18 10:10:30", @@ -122,12 +122,12 @@ export const depositTransactionDummyData = [ transactionId: 1049136973, depositMethod: "Card", status: "Pending", - options: [ - { value: "Pending", label: "Pending" }, - { value: "Completed", label: "Completed" }, - { value: "Inprogress", label: "Inprogress" }, - { value: "Error", label: "Error" }, - ], + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], amount: 4000, currency: "EUR", dateTime: "2025-06-18 10:10:30", @@ -141,12 +141,12 @@ export const depositTransactionDummyData = [ transactionId: 1049131973, depositMethod: "Card", status: "Pending", - options: [ - { value: "Pending", label: "Pending" }, - { value: "Completed", label: "Completed" }, - { value: "Inprogress", label: "Inprogress" }, - { value: "Error", label: "Error" }, - ], + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], amount: 4000, currency: "EUR", dateTime: "2025-06-12 10:10:30", @@ -160,12 +160,12 @@ export const depositTransactionDummyData = [ transactionId: 1049131973, depositMethod: "Bank Transfer", status: "Inprogress", - options: [ - { value: "Pending", label: "Pending" }, - { value: "Completed", label: "Completed" }, - { value: "Inprogress", label: "Inprogress" }, - { value: "Error", label: "Error" }, - ], + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], amount: 4000, currency: "EUR", dateTime: "2025-06-17 10:10:30", @@ -179,12 +179,12 @@ export const depositTransactionDummyData = [ transactionId: 1049131973, depositMethod: "Bank Transfer", status: "Inprogress", - options: [ - { value: "Pending", label: "Pending" }, - { value: "Completed", label: "Completed" }, - { value: "Inprogress", label: "Inprogress" }, - { value: "Error", label: "Error" }, - ], + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], amount: 4000, currency: "EUR", dateTime: "2025-06-17 10:10:30", @@ -198,12 +198,12 @@ export const depositTransactionDummyData = [ transactionId: 1049131973, depositMethod: "Bank Transfer", status: "Error", - options: [ - { value: "Pending", label: "Pending" }, - { value: "Completed", label: "Completed" }, - { value: "Inprogress", label: "Inprogress" }, - { value: "Error", label: "Error" }, - ], + // options: [ + // { value: "Pending", label: "Pending" }, + // { value: "Completed", label: "Completed" }, + // { value: "Inprogress", label: "Inprogress" }, + // { value: "Error", label: "Error" }, + // ], amount: 4000, currency: "EUR", dateTime: "2025-06-17 10:10:30", @@ -218,7 +218,7 @@ export const depositTransactionsColumns: GridColDef[] = [ { field: "transactionId", headerName: "Transaction ID", width: 130 }, { field: "depositMethod", headerName: "Deposit Method", width: 130 }, { field: "status", headerName: "Status", width: 130 }, - { field: "actions", headerName: "Actions", width: 150 }, + // { field: "actions", headerName: "Actions", width: 150 }, { field: "amount", headerName: "Amount", width: 130 }, { field: "currency", headerName: "Currency", width: 130 }, { field: "dateTime", headerName: "Date / Time", width: 130 }, @@ -226,6 +226,15 @@ export const depositTransactionsColumns: GridColDef[] = [ { field: "fraudScore", headerName: "Fraud Score", width: 130 }, ]; +export const depositTransactionsExtraColumns: GridColDef[] = [ + { field: "currency", headerName: "Currency", width: 130 }, + { field: "errorInfo", headerName: "Error Info", width: 130 }, + { field: "fraudScore", headerName: "Fraud Score", width: 130 }, +]; + +// export const extraColumns = ["currency", "errorInfo", "fraudScore"] + + export const depositTransactionsSearchLabels = [ { label: "User", field: "userId", type: "text" }, { label: "Transaction ID", field: "transactionId", type: "text" }, diff --git a/app/api/dashboard/transactions/deposits/route.ts b/app/api/dashboard/transactions/deposits/route.ts index 91066cf..1b7aea1 100644 --- a/app/api/dashboard/transactions/deposits/route.ts +++ b/app/api/dashboard/transactions/deposits/route.ts @@ -3,8 +3,9 @@ import { depositTransactionDummyData, depositTransactionsColumns, depositTransactionsSearchLabels, + // extraColumns } from "./mockData"; -import { formatToDateTimeString } from "@/app/utils/formatDate"; +// import { formatToDateTimeString } from "@/app/utils/formatDate"; export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url); @@ -14,7 +15,10 @@ export async function GET(request: NextRequest) { const depositMethod = searchParams.get("depositMethod"); const merchandId = searchParams.get("merchandId"); const transactionId = searchParams.get("transactionId"); - const dateTime = searchParams.get("dateTime"); + // const dateTime = searchParams.get("dateTime"); + + const dateTimeStart = searchParams.get("dateTime_start"); + const dateTimeEnd = searchParams.get("dateTime_end"); let filteredTransactions = [...depositTransactionDummyData]; @@ -46,12 +50,28 @@ export async function GET(request: NextRequest) { ); } - if (dateTime) { - filteredTransactions = filteredTransactions.filter( - (tx) => - tx.dateTime.split(" ")[0] === - formatToDateTimeString(dateTime).split(" ")[0], - ); + if (dateTimeStart && dateTimeEnd) { + const start = new Date(dateTimeStart); + const end = new Date(dateTimeEnd); + + if (isNaN(start.getTime()) || isNaN(end.getTime())) { + return NextResponse.json( + { + error: "Invalid date range", + }, + { status: 400 }, + ); + } + + filteredTransactions = filteredTransactions.filter((tx) => { + const txDate = new Date(tx.dateTime); + + if (isNaN(txDate.getTime())) { + return false; + } + + return txDate >= start && txDate <= end; + }); } return NextResponse.json({ diff --git a/app/api/dashboard/transactions/withdrawal/mockData.ts b/app/api/dashboard/transactions/withdrawal/mockData.ts index 3c7918c..538062a 100644 --- a/app/api/dashboard/transactions/withdrawal/mockData.ts +++ b/app/api/dashboard/transactions/withdrawal/mockData.ts @@ -7,6 +7,12 @@ export const withdrawalTransactionDummyData = [ transactionId: 1049131973, withdrawalMethod: "Bank Transfer", status: "Error", + options: [ + { value: "Pending", label: "Pending" }, + { value: "Completed", label: "Completed" }, + { value: "Inprogress", label: "Inprogress" }, + { value: "Error", label: "Error" }, + ], amount: 4000, dateTime: "2025-06-17 10:10:30", errorInfo: "-", @@ -20,6 +26,12 @@ export const withdrawalTransactionDummyData = [ transactionId: 1049131973, withdrawalMethod: "Bank Transfer", status: "Error", + options: [ + { value: "Pending", label: "Pending" }, + { value: "Completed", label: "Completed" }, + { value: "Inprogress", label: "Inprogress" }, + { value: "Error", label: "Error" }, + ], amount: 4000, dateTime: "2025-06-17 10:10:30", errorInfo: "-", @@ -32,7 +44,13 @@ export const withdrawalTransactionDummyData = [ userId: 17, transactionId: 1049131973, withdrawalMethod: "Bank Transfer", - status: "Complete", + status: "Completed", + options: [ + { value: "Pending", label: "Pending" }, + { value: "Completed", label: "Completed" }, + { value: "Inprogress", label: "Inprogress" }, + { value: "Error", label: "Error" }, + ], amount: 4000, dateTime: "2025-06-18 10:10:30", errorInfo: "-", @@ -44,6 +62,12 @@ export const withdrawalTransactionDummyData = [ transactionId: 1049136973, withdrawalMethod: "Bank Transfer", status: "Completed", + options: [ + { value: "Pending", label: "Pending" }, + { value: "Completed", label: "Completed" }, + { value: "Inprogress", label: "Inprogress" }, + { value: "Error", label: "Error" }, + ], amount: 4000, dateTime: "2025-06-18 10:10:30", errorInfo: "-", @@ -55,6 +79,12 @@ export const withdrawalTransactionDummyData = [ transactionId: 1049131973, withdrawalMethod: "Bank Transfer", status: "Error", + options: [ + { value: "Pending", label: "Pending" }, + { value: "Completed", label: "Completed" }, + { value: "Inprogress", label: "Inprogress" }, + { value: "Error", label: "Error" }, + ], amount: 4000, dateTime: "2025-06-17 10:10:30", errorInfo: "-", @@ -68,6 +98,12 @@ export const withdrawalTransactionDummyData = [ transactionId: 1049131973, withdrawalMethod: "Bank Transfer", status: "Error", + options: [ + { value: "Pending", label: "Pending" }, + { value: "Completed", label: "Completed" }, + { value: "Inprogress", label: "Inprogress" }, + { value: "Error", label: "Error" }, + ], amount: 4000, dateTime: "2025-06-17 10:10:30", errorInfo: "-", @@ -81,6 +117,12 @@ export const withdrawalTransactionDummyData = [ transactionId: 1049131973, withdrawalMethod: "Bank Transfer", status: "Error", + options: [ + { value: "Pending", label: "Pending" }, + { value: "Completed", label: "Completed" }, + { value: "Inprogress", label: "Inprogress" }, + { value: "Error", label: "Error" }, + ], amount: 4000, dateTime: "2025-06-17 10:10:30", errorInfo: "-", @@ -94,6 +136,12 @@ export const withdrawalTransactionDummyData = [ transactionId: 1049131973, withdrawalMethod: "Card", status: "Pending", + options: [ + { value: "Pending", label: "Pending" }, + { value: "Completed", label: "Completed" }, + { value: "Inprogress", label: "Inprogress" }, + { value: "Error", label: "Error" }, + ], amount: 4000, dateTime: "2025-06-12 10:10:30", errorInfo: "-", @@ -105,6 +153,12 @@ export const withdrawalTransactionDummyData = [ transactionId: 1049131973, withdrawalMethod: "Bank Transfer", status: "Inprogress", + options: [ + { value: "Pending", label: "Pending" }, + { value: "Completed", label: "Completed" }, + { value: "Inprogress", label: "Inprogress" }, + { value: "Error", label: "Error" }, + ], amount: 4000, dateTime: "2025-06-17 10:10:30", errorInfo: "-", @@ -116,6 +170,12 @@ export const withdrawalTransactionDummyData = [ transactionId: 1049131973, withdrawalMethod: "Bank Transfer", status: "Error", + options: [ + { value: "Pending", label: "Pending" }, + { value: "Completed", label: "Completed" }, + { value: "Inprogress", label: "Inprogress" }, + { value: "Error", label: "Error" }, + ], amount: 4000, dateTime: "2025-06-17 10:10:30", errorInfo: "-", @@ -129,6 +189,12 @@ export const withdrawalTransactionDummyData = [ transactionId: 1049131973, withdrawalMethod: "Bank Transfer", status: "Error", + options: [ + { value: "Pending", label: "Pending" }, + { value: "Completed", label: "Completed" }, + { value: "Inprogress", label: "Inprogress" }, + { value: "Error", label: "Error" }, + ], amount: 4000, dateTime: "2025-06-17 10:10:30", errorInfo: "-", @@ -143,6 +209,7 @@ export const withdrawalTransactionsColumns: GridColDef[] = [ { field: "transactionId", headerName: "Transaction ID", width: 130 }, { field: "withdrawalMethod", headerName: "Withdrawal Method", width: 130 }, { field: "status", headerName: "Status", width: 130 }, + { field: "actions", headerName: "Actions", width: 150 }, { field: "amount", headerName: "Amount", width: 130 }, { field: "dateTime", headerName: "Date / Time", width: 130 }, { field: "errorInfo", headerName: "Error Info", width: 130 }, diff --git a/app/api/dashboard/transactions/withdrawal/route.ts b/app/api/dashboard/transactions/withdrawal/route.ts index 885b0fd..967dc5a 100644 --- a/app/api/dashboard/transactions/withdrawal/route.ts +++ b/app/api/dashboard/transactions/withdrawal/route.ts @@ -4,16 +4,17 @@ import { withdrawalTransactionsColumns, withdrawalTransactionsSearchLabels, } from "./mockData"; -import { formatToDateTimeString } from "@/app/utils/formatDate"; export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url); const userId = searchParams.get("userId"); const status = searchParams.get("status"); - const dateTime = searchParams.get("dateTime"); const withdrawalMethod = searchParams.get("withdrawalMethod"); + const dateTimeStart = searchParams.get("dateTime_start"); + const dateTimeEnd = searchParams.get("dateTime_end"); + let filteredTransactions = [...withdrawalTransactionDummyData]; if (userId) { @@ -28,6 +29,30 @@ export async function GET(request: NextRequest) { ); } + if (dateTimeStart && dateTimeEnd) { + const start = new Date(dateTimeStart); + const end = new Date(dateTimeEnd); + + if (isNaN(start.getTime()) || isNaN(end.getTime())) { + return NextResponse.json( + { + error: "Invalid date range", + }, + { status: 400 }, + ); + } + + filteredTransactions = filteredTransactions.filter((tx) => { + const txDate = new Date(tx.dateTime); + + if (isNaN(txDate.getTime())) { + return false; + } + + return txDate >= start && txDate <= end; + }); + } + if (withdrawalMethod) { filteredTransactions = filteredTransactions.filter( (tx) => @@ -35,14 +60,6 @@ export async function GET(request: NextRequest) { ); } - if (dateTime) { - filteredTransactions = filteredTransactions.filter( - (tx) => - tx.dateTime.split(" ")[0] === - formatToDateTimeString(dateTime).split(" ")[0], - ); - } - return NextResponse.json({ tableRows: filteredTransactions, tableSearchLabels: withdrawalTransactionsSearchLabels, diff --git a/app/components/TestTokenExpiration.tsx b/app/components/TestTokenExpiration.tsx new file mode 100644 index 0000000..f4e67c9 --- /dev/null +++ b/app/components/TestTokenExpiration.tsx @@ -0,0 +1,42 @@ +"use client"; + +import React from "react"; +import { useDispatch } from "react-redux"; +import { Button, Box, Typography, Stack } from "@mui/material"; +import { AppDispatch } from "@/app/redux/types"; +import { autoLogout, refreshAuthStatus } from "@/app/redux/auth/authSlice"; + +export default function TestTokenExpiration() { + const dispatch = useDispatch(); + + const handleTestExpiration = () => { + dispatch(autoLogout("Manual test expiration")); + }; + + const handleRefreshAuth = () => { + dispatch(refreshAuthStatus()); + }; + + return ( + + + Test Token Expiration + + + Test authentication functionality and token management. + + + + + + + ); +} diff --git a/app/components/TokenExpirationInfo.tsx b/app/components/TokenExpirationInfo.tsx new file mode 100644 index 0000000..ed1d101 --- /dev/null +++ b/app/components/TokenExpirationInfo.tsx @@ -0,0 +1,54 @@ +"use client"; + +import React, { useEffect, useState } from "react"; +import { useSelector } from "react-redux"; +import { + selectExpiresInHours, + selectTimeUntilExpiration, +} from "@/app/redux/auth/selectors"; +import { Alert, AlertTitle, Box, Typography } from "@mui/material"; + +export default function TokenExpirationInfo() { + const expiresInHours = useSelector(selectExpiresInHours); + const timeUntilExpiration = useSelector(selectTimeUntilExpiration); + const [showWarning, setShowWarning] = useState(false); + + useEffect(() => { + // Show warning when token expires in less than 1 hour + if (expiresInHours > 0 && expiresInHours <= 1) { + setShowWarning(true); + } else { + setShowWarning(false); + } + }, [expiresInHours]); + + if (expiresInHours <= 0) { + return null; // Don't show anything if not logged in or no token info + } + + const formatTime = (seconds: number) => { + const hours = Math.floor(seconds / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + + if (hours > 0) { + return `${hours}h ${minutes}m`; + } + return `${minutes}m`; + }; + + return ( + + {showWarning ? ( + + Session Expiring Soon + Your session will expire in {formatTime(timeUntilExpiration)}. Please + save your work and log in again if needed. + + ) : ( + + Session expires in {formatTime(timeUntilExpiration)} + + )} + + ); +} diff --git a/app/components/searchFilter/SearchFilters.scss b/app/components/searchFilter/SearchFilters.scss new file mode 100644 index 0000000..97bf691 --- /dev/null +++ b/app/components/searchFilter/SearchFilters.scss @@ -0,0 +1,43 @@ +.search-filters { + display: flex; + flex-wrap: wrap; + align-items: center; + padding: 16px; +} + +.chip { + display: inline-flex; + align-items: center; + background-color: #e0e0e0; + border-radius: 16px; + padding: 4px 8px; + margin: 4px; + font-size: 14px; +} + +.chip-label { + margin-right: 8px; +} + +.chip-label.bold { + font-weight: bold; +} + +.chip-delete { + background: none; + border: none; + cursor: pointer; + font-size: 16px; + line-height: 1; + color: #333; +} + +.clear-all { + margin-left: 8px; + text-decoration: underline; + background: none; + border: none; + color: black; + cursor: pointer; + font-size: 14px; +} diff --git a/app/components/searchFilter/SearchFilters.tsx b/app/components/searchFilter/SearchFilters.tsx index bacce04..1305579 100644 --- a/app/components/searchFilter/SearchFilters.tsx +++ b/app/components/searchFilter/SearchFilters.tsx @@ -1,6 +1,7 @@ -import React from 'react'; -import { Box, Chip, Typography, Button } from '@mui/material'; -import { useRouter, useSearchParams } from 'next/navigation'; +"use client"; +import React from "react"; +import { useRouter, useSearchParams } from "next/navigation"; +import "./SearchFilters.scss"; interface SearchFiltersProps { filters: Record; @@ -8,57 +9,72 @@ interface SearchFiltersProps { const SearchFilters = ({ filters }: SearchFiltersProps) => { const router = useRouter(); + const searchParams = useSearchParams(); + const filterLabels: Record = { userId: "User", state: "State", - startDate: "Start Date", - // Add others here + dateRange: "Date Range", }; - const searchParams = useSearchParams() - const handleDeleteFilter = (key: string) => { + + const handleDeleteFilter = (key: string) => { const params = new URLSearchParams(searchParams.toString()); - params.delete(key); + if (key === "dateRange") { + params.delete("dateTime_start"); + params.delete("dateTime_end"); + } else { + params.delete(key); + } router.push(`?${params.toString()}`); }; - const onClearAll = () => { router.push("?"); - } + }; const renderChip = (label: string, value: string, key: string) => ( - - {label}: {value} - - } - onDelete={() => handleDeleteFilter(key)} - sx={{ mr: 1, mb: 1 }} - /> +
+ + {label}: {value} + + +
); + const formatDate = (dateStr: string) => + new Date(dateStr).toISOString().split("T")[0]; + + const hasDateRange = filters.dateTime_start && filters.dateTime_end; + + const allFilters = [ + ...Object.entries(filters).filter( + ([key]) => key !== "dateTime_start" && key !== "dateTime_end", + ), + ...(hasDateRange + ? [ + [ + "dateRange", + `${formatDate(filters.dateTime_start)} - ${formatDate(filters.dateTime_end)}`, + ] as [string, string], + ] + : []), + ]; + return ( - - {Object.entries(filters).map(([key, value]) => - value ? renderChip(filterLabels[key] ?? key, value, key) : null +
+ {allFilters.map(([key, value]) => + value ? renderChip(filterLabels[key] ?? key, value, key) : null, )} {Object.values(filters).some(Boolean) && ( - + )} - +
); }; - export default SearchFilters; diff --git a/app/dashboard/approve/page.tsx b/app/dashboard/approve/page.tsx index dd6dcd4..0f4aae0 100644 --- a/app/dashboard/approve/page.tsx +++ b/app/dashboard/approve/page.tsx @@ -1,12 +1,28 @@ -"use client"; +import { + ApproveTable, +} from "@/app/features/Pages/Approve/Approve"; +import { getApproves } from "@/app/services/approve"; -import { Approve } from "@/app/features/Pages/Approve/Approve"; -export default function ApprovePage() { +export default async function Approve({ + searchParams, +}: { + searchParams: Promise>; +}) { + // Await searchParams before processing + const params = await searchParams; + // Create a safe query string by filtering only string values + const safeParams: Record = {}; + for (const [key, value] of Object.entries(params)) { + if (typeof value === "string") { + safeParams[key] = value; + } + } + const query = new URLSearchParams(safeParams).toString(); + const data = await getApproves({ query }); + return ( -
- {/* This page will now be rendered on the client-side */} - -
+ ); -} +}; + diff --git a/app/dashboard/layout.tsx b/app/dashboard/layout.tsx index 51ee09c..1d64ff7 100644 --- a/app/dashboard/layout.tsx +++ b/app/dashboard/layout.tsx @@ -1,21 +1,18 @@ "use client"; -import React, { useEffect } from "react"; +import React from "react"; import { LayoutWrapper } from "../features/dashboard/layout/layoutWrapper"; import { MainContent } from "../features/dashboard/layout/mainContent"; import SideBar from "../features/dashboard/sidebar/Sidebar"; import Header from "../features/dashboard/header/Header"; +import { useTokenExpiration } from "../hooks/useTokenExpiration"; +import TokenExpirationInfo from "../components/TokenExpirationInfo"; const DashboardLayout: React.FC<{ children: React.ReactNode }> = ({ children, }) => { - useEffect(() => { - // if (process.env.NODE_ENV === "development") { - import("../../mock/browser").then(({ worker }) => { - worker.start(); - }); - // } - }, []); + // Monitor token expiration and auto-logout + useTokenExpiration(); return ( @@ -23,6 +20,7 @@ const DashboardLayout: React.FC<{ children: React.ReactNode }> = ({
+ {children}
diff --git a/app/dashboard/transactions/all/page.tsx b/app/dashboard/transactions/all/page.tsx new file mode 100644 index 0000000..17e12eb --- /dev/null +++ b/app/dashboard/transactions/all/page.tsx @@ -0,0 +1,23 @@ +import DataTable from "@/app/features/DataTable/DataTable"; +import { getTransactions } from "@/app/services/transactions"; + +export default async function AllTransactionPage({ + searchParams, +}: { + searchParams: Promise>; +}) { + // Await searchParams before processing + const params = await searchParams; + // Create a safe query string by filtering only string values + const safeParams: Record = {}; + for (const [key, value] of Object.entries(params)) { + if (typeof value === "string") { + safeParams[key] = value; + } + } + const query = new URLSearchParams(safeParams).toString(); + const transactionType = "all"; + const data = await getTransactions({ transactionType, query }); + + return ; +} diff --git a/app/features/AdvancedSearch/AdvancedSearch.tsx b/app/features/AdvancedSearch/AdvancedSearch.tsx index d082fb9..8e6c823 100644 --- a/app/features/AdvancedSearch/AdvancedSearch.tsx +++ b/app/features/AdvancedSearch/AdvancedSearch.tsx @@ -1,3 +1,4 @@ +"use client"; import { Box, TextField, @@ -39,11 +40,12 @@ export default function AdvancedSearch({ labels }: { labels: ISearchLabel[] }) { }); router.push(`?${updatedParams.toString()}`); }, 500), - [router] + [router], ); const handleFieldChange = (field: string, value: string) => { const updatedValues = { ...formValues, [field]: value }; + console.log(updatedValues); setFormValues(updatedValues); updateURL(updatedValues); }; @@ -158,20 +160,50 @@ export default function AdvancedSearch({ labels }: { labels: ISearchLabel[] }) { )} {type === "date" && ( - - handleFieldChange( - field, - newValue?.toISOString() || "" - ) - } - slotProps={{ - textField: { fullWidth: true, size: "small" }, - }} - /> + + { + if (!newValue) + return handleFieldChange(`${field}_start`, ""); + const start = new Date(newValue); + start.setHours(0, 0, 0, 0); // force start of day + handleFieldChange( + `${field}_start`, + start.toISOString(), + ); + }} + slotProps={{ + textField: { fullWidth: true, size: "small" }, + }} + /> + { + if (!newValue) + return handleFieldChange(`${field}_end`, ""); + const end = new Date(newValue); + end.setHours(23, 59, 59, 999); // force end of day + handleFieldChange( + `${field}_end`, + end.toISOString(), + ); + }} + slotProps={{ + textField: { fullWidth: true, size: "small" }, + }} + /> + )}
))} diff --git a/app/features/DataTable/DataTable.tsx b/app/features/DataTable/DataTable.tsx index 1279c6d..5dfdb81 100644 --- a/app/features/DataTable/DataTable.tsx +++ b/app/features/DataTable/DataTable.tsx @@ -15,31 +15,40 @@ import { Stack, Paper, TextField, + Box, + IconButton, } from "@mui/material"; import FileUploadIcon from "@mui/icons-material/FileUpload"; +import OpenInNewIcon from "@mui/icons-material/OpenInNew"; import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid"; import AdvancedSearch from "../AdvancedSearch/AdvancedSearch"; import SearchFilters from "@/app/components/searchFilter/SearchFilters"; import { exportData } from "@/app/utils/exportData"; +import StatusChangeDialog from "./StatusChangeDialog"; import { IDataTable } from "./types"; - interface IDataTableProps { data: IDataTable; } export type TWithId = { id: number }; -const DataTable = ( - data: IDataTableProps, -) => { - const { tableRows, tableColumns, tableSearchLabels } = data.data; + +const DataTable = ({ + data, +}: IDataTableProps) => { + const { tableRows, tableColumns, tableSearchLabels, extraColumns } = data; const router = useRouter(); const searchParams = useSearchParams(); + const [rows, setRows] = useState(tableRows); const [open, setOpen] = useState(false); const [fileType, setFileType] = useState<"csv" | "xls" | "xlsx">("csv"); const [onlyCurrentTable, setOnlyCurrentTable] = useState(false); - const [rows, setRows] = useState(tableRows); + const [modalOpen, setModalOpen] = useState(false); + const [selectedRowId, setSelectedRowId] = useState(null); + const [newStatus, setNewStatus] = useState(""); + const [reason, setReason] = useState(""); + const [showExtraColumns, setShowExtraColumns] = useState(false); const filters = Object.fromEntries(searchParams.entries()); @@ -51,13 +60,105 @@ const DataTable = ( }; const handleStatusChange = (id: number, newStatus: string) => { - setRows( - rows.map((row) => (row.id === id ? { ...row, status: newStatus } : row)), + setSelectedRowId(id); + setNewStatus(newStatus); + setModalOpen(true); + }; + + const handleStatusSave = () => { + console.log( + `Status changed for row with ID ${selectedRowId}. New status: ${newStatus}. Reason: ${reason}`, ); + + setRows( + rows.map((row) => + row.id === selectedRowId ? { ...row, status: newStatus } : row, + ), + ); + setModalOpen(false); + setReason(""); }; const getColumnsWithDropdown = (columns: TColumn[]): GridColDef[] => { - return columns?.map((col) => { + return columns.map((col) => { + if (col.field === "status") { + return { + ...col, + renderCell: (params: GridRenderCellParams) => { + const value = params.value?.toLowerCase(); + let bgColor = "#e0e0e0"; + let textColor = "#000"; + + switch (value) { + case "completed": + bgColor = "#d0f0c0"; + textColor = "#1b5e20"; + break; + case "pending": + bgColor = "#fff4cc"; + textColor = "#9e7700"; + break; + case "inprogress": + bgColor = "#cce5ff"; + textColor = "#004085"; + break; + case "error": + bgColor = "#ffcdd2"; + textColor = "#c62828"; + break; + } + + return ( + + {params.value} + + ); + }, + }; + } + + if (col.field === "userId") { + return { + ...col, + renderCell: (params: GridRenderCellParams) => ( + + {params.value} + e.stopPropagation()} + sx={{ p: 0.5 }} + > + + + + ), + }; + } + if (col.field === "actions") { return { ...col, @@ -100,13 +201,22 @@ const DataTable = ( }); }; + let filteredColumns = tableColumns; + if (extraColumns && extraColumns.length > 0) { + filteredColumns = showExtraColumns + ? tableColumns + : tableColumns.filter((col) => !extraColumns.includes(col.field)); + } + return ( - + ( > Export + {extraColumns && extraColumns.length > 0 && ( + + )} - { - if (params.field !== "actions") { - handleClickField(params.field, params.value as string); - } - }} + + + { + if (params.field !== "actions") { + handleClickField(params.field, params.value as string); + } + }} + /> + + + + setModalOpen(false)} + handleSave={handleStatusSave} /> - {/* Export Dialog */} setOpen(false)}> Export Transactions @@ -170,7 +308,7 @@ const DataTable = ( onChange={(e) => setOnlyCurrentTable(e.target.checked)} /> } - label="Only export the results in the current table" + label="Only export current table" sx={{ mt: 2 }} /> diff --git a/app/features/DataTable/StatusChangeDialog.tsx b/app/features/DataTable/StatusChangeDialog.tsx new file mode 100644 index 0000000..6b3e127 --- /dev/null +++ b/app/features/DataTable/StatusChangeDialog.tsx @@ -0,0 +1,54 @@ +import { + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Button, + TextField, +} from "@mui/material"; + +interface StatusChangeDialogProps { + open: boolean; + newStatus: string; + reason: string; + setReason: React.Dispatch>; + handleClose: () => void; + handleSave: () => void; +} + +const StatusChangeDialog = ({ + open, + newStatus, + reason, + setReason, + handleClose, + handleSave, +}: StatusChangeDialogProps) => { + return ( + + Change Status + + You want to change the status to {newStatus}. Please provide a + reason for the change. + setReason(e.target.value)} + sx={{ mt: 2 }} + /> + + + + + + + ); +}; + +export default StatusChangeDialog; diff --git a/app/features/DataTable/types.ts b/app/features/DataTable/types.ts index fb4c381..a104fa4 100644 --- a/app/features/DataTable/types.ts +++ b/app/features/DataTable/types.ts @@ -9,4 +9,5 @@ export interface IDataTable { tableRows: TRow[]; tableColumns: TColumn[]; tableSearchLabels: ISearchLabel[]; + extraColumns: string[]; } diff --git a/app/features/Pages/Admin/Users/users.tsx b/app/features/Pages/Admin/Users/users.tsx index 8a9d423..0ef78f7 100644 --- a/app/features/Pages/Admin/Users/users.tsx +++ b/app/features/Pages/Admin/Users/users.tsx @@ -2,10 +2,10 @@ import React, { useState } from "react"; import { Card, CardContent, Typography, Stack } from "@mui/material"; import { IUser } from "./interfaces"; -import UserTopBar from "@/app/features/UserRoles/AddUser/AddUser"; -import EditUser from "@/app/features/UserRoles/EditUser/EditUser"; +import UserTopBar from "@/app/features/UserRoles/AddUser/AddUserButton"; import Modal from "@/app/components/Modal/Modal"; import UserRoleCard from "@/app/features/UserRoles/userRoleCard"; +import AddUser from "@/app/features/UserRoles/AddUser/AddUser"; interface UsersProps { users: IUser[]; @@ -25,18 +25,13 @@ const Users: React.FC = ({ users }) => { Merchant ID: {user.merchantId} - {/* You can render more UI here for additional properties */} - {/* Add more chips or UI elements for other data */} @@ -47,7 +42,7 @@ const Users: React.FC = ({ users }) => { onClose={() => setShowAddUser(false)} title="Add User" > - + ); diff --git a/app/features/Pages/Approve/Approve.tsx b/app/features/Pages/Approve/Approve.tsx index 374bb1b..310ea9c 100644 --- a/app/features/Pages/Approve/Approve.tsx +++ b/app/features/Pages/Approve/Approve.tsx @@ -1,4 +1,5 @@ -import React, { useState } from 'react'; +"use client"; +import { useState, useEffect, useMemo } from "react"; import { Box, TextField, @@ -16,63 +17,104 @@ import { InputLabel, Select, FormControl, - SelectChangeEvent -} from '@mui/material'; -import SearchIcon from '@mui/icons-material/Search'; + SelectChangeEvent, + debounce, +} from "@mui/material"; +import SearchIcon from "@mui/icons-material/Search"; +import { useRouter, useSearchParams } from "next/navigation"; -const rows = [ - { - merchantId: '100987998', - txId: '1049078821', - userId: 17, - userEmail: 'dhkheni1@yopmail.com', - kycStatus: 'N/A', - }, - { - merchantId: '100987998', - txId: '1049078821', - userId: 18, - userEmail: 'dhkheni1@yopmail.com', - kycStatus: 'N/A', - }, - { - merchantId: '100987998', - txId: '1049078821', - userId: 19, - userEmail: 'dhkheni1@yopmail.com', - kycStatus: 'N/A', - }, -]; +export interface TableColumn { + field: keyof T | string; + headerName: string; + render?: (value: unknown, row: T) => React.ReactNode; +} -export const Approve = () => { - const [age, setAge] = useState(''); - const [selectedRows, setSelectedRows] = useState([]); +interface MenuItemOption { + value: string; + label?: string; +} +interface DynamicTableProps { + data: { + rows: T[]; + columns: TableColumn[]; + actions: MenuItemOption[]; + }; + searchParamKey?: string; +} +export function ApproveTable({ + data, + searchParamKey = "merchantId", +}: DynamicTableProps) { + const { rows, columns, actions } = data; - const handleCheckboxChange = (userId: number) => (event: React.ChangeEvent) => { - const isChecked = event.target.checked; - setSelectedRows((prevSelected: number[]) => - isChecked - ? [...prevSelected, userId] - : prevSelected.filter((id) => id !== userId) - ); - console.log('Selected IDs:', isChecked - ? [...selectedRows, userId] - : selectedRows.filter((id) => id !== userId)); + const router = useRouter(); + const searchParams = useSearchParams(); + + const [selected, setSelected] = useState<(string | number)[]>([]); + const [search, setSearch] = useState(""); + + useEffect(() => { + const urlValue = searchParams.get(searchParamKey) ?? ""; + setSearch(urlValue); + }, [searchParams, searchParamKey]); + + const updateURL = useMemo( + () => + debounce((value: string) => { + const params = new URLSearchParams(searchParams.toString()); + if (value) params.set(searchParamKey, value); + else params.delete(searchParamKey); + + router.replace(`?${params.toString()}`, { scroll: false }); + }, 400), + [router, searchParams, searchParamKey], + ); + + const handleSearchChange = (e: React.ChangeEvent) => { + const value = e.target.value; + setSearch(value); + updateURL(value); }; - const handleChangeAge = (event: SelectChangeEvent) => { - setAge(event.target.value as string); + const handleCheckboxChange = (id: string | number, checked: boolean) => { + setSelected((prev) => + checked ? [...prev, id] : prev.filter((x) => x !== id), + ); + }; + + const handleToggleAll = (checked: boolean) => { + setSelected(checked ? rows.map((r) => r.id) : []); + }; + + const [action, setAction] = useState(""); + const handleActionChange = (e: SelectChangeEvent) => { + const selectedAction = e.target.value; + setAction(selectedAction); + + if (selected.length > 0) { + console.log("Selected Ids", selected); + console.log("Selected Action:", selectedAction); + } else { + console.warn("No rows selected for action:", selectedAction); + } }; return ( - + @@ -83,26 +125,21 @@ export const Approve = () => { ), }} /> - - {/* */} - {/* */} - {/* */} - {/* */} - {/* Action 1 */} - {/* Action 2 */} - {/* */} + + - Action + Action @@ -112,45 +149,38 @@ export const Approve = () => { - - Merchant-id - Tx-id - User - User email - KYC Status - KYC PSP - KYC PSP status - KYC ID status - KYC address status - KYC liveness status - KYC age status - KYC peps and sanctions - Suspected + + 0} + indeterminate={ + selected.length > 0 && selected.length < rows.length + } + onChange={(e) => handleToggleAll(e.target.checked)} + /> + + {columns.map((col, i) => ( + {col.headerName} + ))} {rows.map((row, idx) => ( - - {row.merchantId} - {row.txId} - - - {row.userId} - + + handleCheckboxChange(row.id, e.target.checked) + } + /> - {row.userEmail} - {row.kycStatus} - - - - - - - - + {columns.map((col, colIdx) => ( + + {col.render + ? col.render(row[col.field as keyof T], row) + : (row[col.field as keyof T] as React.ReactNode)} + + ))} ))} @@ -159,4 +189,3 @@ export const Approve = () => { ); } - diff --git a/app/features/UserRoles/AddUser/AddUser.scss b/app/features/UserRoles/AddUser/AddUser.scss index d6fc563..a66016a 100644 --- a/app/features/UserRoles/AddUser/AddUser.scss +++ b/app/features/UserRoles/AddUser/AddUser.scss @@ -1,15 +1,22 @@ .add-user { - position: sticky; - top: 40px; - width: 100%; - background: #fff; - z-index: 10; + margin-top: 30px; display: flex; - justify-content: flex-end; - align-items: center; - gap: 1rem; - padding: 1rem 0.5rem; - border-bottom: 1px solid #eee; + flex-wrap: wrap; + gap: 16px; + + &__sticky-container { + position: sticky; + top: 40px; + width: 100%; + background: #fff; + z-index: 10; + display: flex; + justify-content: flex-end; + align-items: center; + gap: 1rem; + padding: 1rem 0.5rem; + border-bottom: 1px solid #eee; + } &__button { padding: 0.5rem 1rem; @@ -20,15 +27,57 @@ display: flex; align-items: center; gap: 0.5rem; + + &--primary { + background: #1976d2; + color: #fff; + } + + &--secondary { + background: #e0e0e0; + color: #333; + } + } + input, + &__select { + flex: 1 1 20%; + min-width: 150px; + box-sizing: border-box; + padding: 8px; + font-size: 1rem; + border-radius: 4px; + border: 1px solid #ccc; + outline: none; + transition: border-color 0.3s ease; + + &:focus { + border-color: #0070f3; + } } - &__button--primary { - background: #1976d2; - color: #fff; - } + &__button-container { + flex-basis: 100%; + width: 100%; - &__button--secondary { - background: #e0e0e0; - color: #333; + button { + flex-basis: 100%; + margin-top: 16px; + padding: 10px 0; + font-size: 1rem; + border-radius: 4px; + width: 100px; + cursor: pointer; + } + + button:first-child { + color: var(--button-primary); + border-color: var(--button-primary); + } + + button:last-child { + color: var(--button-secondary); + border-color: var(--button-secondary); + margin-left: 8px; + } } } diff --git a/app/features/UserRoles/AddUser/AddUser.tsx b/app/features/UserRoles/AddUser/AddUser.tsx index 9f79eb7..e3b3531 100644 --- a/app/features/UserRoles/AddUser/AddUser.tsx +++ b/app/features/UserRoles/AddUser/AddUser.tsx @@ -1,32 +1,110 @@ -import { Add } from "@mui/icons-material"; -import React from "react"; -import "./AddUser.scss"; +"use client"; + +import React, { useState } from "react"; +import { useRouter } from "next/navigation"; +import "./AddUser.scss"; +import { addUser } from "@/services/roles.services"; +import { IEditUserForm } from "../User.interfaces"; + +interface AddUserFormProps { + onSuccess?: () => void; +} + +const AddUserForm: React.FC = ({ onSuccess }) => { + const router = useRouter(); + const [form, setForm] = useState({ + firstName: "", + lastName: "", + email: "", + phone: "", + role: "", + }); + + const [error, setError] = useState(""); + const [loading, setLoading] = useState(false); + + const handleChange = ( + e: React.ChangeEvent + ) => { + const { name, value } = e.target; + setForm((prev) => ({ ...prev, [name]: value })); + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + if (!form.firstName || !form.lastName || !form.email || !form.role) { + setError("Please fill in all required fields."); + return; + } + + try { + setLoading(true); + setError(""); + + await addUser(form); + if (onSuccess) onSuccess(); + router.refresh(); // <- refreshes the page (SSR re-runs) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (err: any) { + setError(err.message || "Something went wrong."); + } finally { + setLoading(false); + } + }; -const AddUser: React.FC<{ - onAddUser?: () => void; - onExport?: () => void; -}> = ({ onAddUser, onExport }) => { return ( -
- +
+ ); }; -export default AddUser; +export default AddUserForm; diff --git a/app/features/UserRoles/AddUser/AddUserButton.tsx b/app/features/UserRoles/AddUser/AddUserButton.tsx new file mode 100644 index 0000000..498a316 --- /dev/null +++ b/app/features/UserRoles/AddUser/AddUserButton.tsx @@ -0,0 +1,37 @@ +import { Add } from "@mui/icons-material"; +import React from "react"; +import "./AddUser.scss"; + +interface AddUserProps { + onAddUser?: () => void; + onExport?: () => void; +} + +const AddUser: React.FC = ({ onAddUser, onExport }) => { + return ( +
+
+ + + +
+
+ ); +}; + +export default AddUser; diff --git a/app/features/UserRoles/EditUser/EditUser.tsx b/app/features/UserRoles/EditUser/EditUser.tsx index b7bdbbf..1d8973d 100644 --- a/app/features/UserRoles/EditUser/EditUser.tsx +++ b/app/features/UserRoles/EditUser/EditUser.tsx @@ -1,17 +1,19 @@ import React from "react"; import { useRouter } from "next/navigation"; import { IEditUserForm, EditUserField } from "../User.interfaces"; -import { createRole } from "@/services/roles.services"; +import { addUser, editUser } from "@/services/roles.services"; +import { IUser } from "../../Pages/Admin/Users/interfaces"; import "./EditUser.scss"; -const EditUser = () => { +const EditUser = ({ user }: { user: IUser }) => { const router = useRouter(); + const { username, lastName, email, authorities: roles, phone } = user; const [form, setForm] = React.useState({ - firstName: "", - lastName: "", - email: "", - role: "", - phone: "", + firstName: username || "", + lastName: lastName || "", + email: email || "", + role: roles[0] || "", + phone: phone || "", }); const handleChange = (e: React.ChangeEvent) => { @@ -45,9 +47,9 @@ const EditUser = () => { e.preventDefault(); try { - await createRole(form); + await editUser(user.id, form); router.refresh(); // <- refreshes the page (SSR re-runs) - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (err: any) { console.log(err.message || "Error creating role"); // setError(err.message || "Error creating role"); diff --git a/app/features/UserRoles/userRoleCard.tsx b/app/features/UserRoles/userRoleCard.tsx index 4d544ba..2001141 100644 --- a/app/features/UserRoles/userRoleCard.tsx +++ b/app/features/UserRoles/userRoleCard.tsx @@ -21,28 +21,23 @@ import { } from "@mui/icons-material"; import EditUser from "./EditUser/EditUser"; import "./User.scss"; +import { IUser } from "../Pages/Admin/Users/interfaces"; interface Props { - username: string; - name: string; - email: string; + user: IUser; isAdmin: boolean; lastLogin: string; merchants: string[]; - roles: string[]; extraRolesCount?: number; } export default function UserRoleCard({ - username, - name, - email, + user, isAdmin, - roles, extraRolesCount, }: Props) { const [isEditing, setIsEditing] = useState(false); - + const { username, name, email, authorities: roles } = user; const handleEditClick = () => { setIsEditing(!isEditing); }; @@ -117,7 +112,7 @@ export default function UserRoleCard({ isEditing ? " user-card__edit-transition--open" : "" }`} > - {isEditing && } + {isEditing && } diff --git a/app/features/dashboard/sidebar/SidebarLink.constants.ts b/app/features/dashboard/sidebar/SidebarLink.constants.ts index c0420c5..88de6dc 100644 --- a/app/features/dashboard/sidebar/SidebarLink.constants.ts +++ b/app/features/dashboard/sidebar/SidebarLink.constants.ts @@ -37,8 +37,8 @@ export const PAGE_LINKS: ISidebarLink[] = [ icon: ArrowUpwardIcon, }, { - title: "Transaction History", - path: "/dashboard/transactions/history", + title: "All Transactions", + path: "/dashboard/transactions/all", icon: HistoryIcon, }, ], diff --git a/app/hooks/useTokenExpiration.ts b/app/hooks/useTokenExpiration.ts new file mode 100644 index 0000000..642b6ec --- /dev/null +++ b/app/hooks/useTokenExpiration.ts @@ -0,0 +1,66 @@ +"use client"; + +import { useEffect, useRef } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { useRouter } from "next/navigation"; +import { AppDispatch } from "@/app/redux/types"; +import { + selectTimeUntilExpiration, + selectIsLoggedIn, +} from "@/app/redux/auth/selectors"; +import { autoLogout } from "@/app/redux/auth/authSlice"; + +export function useTokenExpiration() { + const dispatch = useDispatch(); + const router = useRouter(); + const timeUntilExpiration = useSelector(selectTimeUntilExpiration); + const isLoggedIn = useSelector(selectIsLoggedIn); + const timeoutRef = useRef(null); + + useEffect(() => { + // Clear any existing timeout + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + timeoutRef.current = null; + } + + // Only set up expiration monitoring if user is logged in and we have expiration data + if (isLoggedIn && timeUntilExpiration > 0) { + // Set timeout to logout 1 second after token expires + const logoutDelay = (timeUntilExpiration + 1) * 1000; + + timeoutRef.current = setTimeout(() => { + console.log("Token expired, auto-logging out user"); + dispatch(autoLogout("Token expired")); + router.push("/login"); + }, logoutDelay); + + // Also set up periodic checks every 5 minutes + const checkInterval = setInterval(() => { + // Re-dispatch checkAuthStatus to get updated expiration time + // This will be handled by the ReduxProvider + }, 5 * 60 * 1000); // 5 minutes + + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + clearInterval(checkInterval); + }; + } + }, [isLoggedIn, timeUntilExpiration, dispatch, router]); + + // Cleanup on unmount + useEffect(() => { + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + }; + }, []); + + return { + timeUntilExpiration, + isLoggedIn, + }; +} diff --git a/app/login/LoginPageClient.tsx b/app/login/LoginPageClient.tsx index 20e96ee..1ffd414 100644 --- a/app/login/LoginPageClient.tsx +++ b/app/login/LoginPageClient.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { useDispatch, useSelector } from "react-redux"; import LoginModal from "../features/Auth/LoginModal"; @@ -18,10 +18,23 @@ export default function LoginPageClient() { const router = useRouter(); const searchParams = useSearchParams(); const redirectPath = searchParams.get("redirect") || "/dashboard"; + const reason = searchParams.get("reason"); const isLoggedIn = useSelector(selectIsLoggedIn); const status = useSelector(selectStatus); const authMessage = useSelector(selectAuthMessage); const dispatch = useDispatch(); + const [redirectMessage, setRedirectMessage] = useState(""); + + useEffect(() => { + // Set message based on redirect reason + if (reason === "expired-token") { + setRedirectMessage("Your session has expired. Please log in again."); + } else if (reason === "invalid-token") { + setRedirectMessage("Invalid session detected. Please log in again."); + } else if (reason === "no-token") { + setRedirectMessage("Please log in to access the backoffice."); + } + }, [reason]); useEffect(() => { if (isLoggedIn && status === "succeeded") { @@ -44,7 +57,7 @@ export default function LoginPageClient() {

Payment Backoffice

- You are logged in. Redirecting to dashboard... + {redirectMessage || "Please log in to access the backoffice."}

@@ -53,13 +66,6 @@ export default function LoginPageClient() { return (
-
-

Payment Backoffice

-

- Please log in to access the backoffice. -

-
- (null); + const initialCheckRef = useRef(null); + + useEffect(() => { + // Check authentication status when the ReduxProvider component mounts on the client. + // This ensures your Redux auth state is synced with the server-side token. + store.dispatch(checkAuthStatus()); + + // Do an additional check after 2 seconds to ensure we have the latest token info + initialCheckRef.current = setTimeout(() => { + store.dispatch(checkAuthStatus()); + }, 2000); + + // Set up periodic token validation every 5 minutes + intervalRef.current = setInterval(() => { + store.dispatch(checkAuthStatus()); + }, 5 * 60 * 1000); // 5 minutes + + return () => { + if (intervalRef.current) { + clearInterval(intervalRef.current); + } + if (initialCheckRef.current) { + clearTimeout(initialCheckRef.current); + } + }; + }, []); // Empty dependency array ensures it runs only once on mount + return {children}; } diff --git a/app/redux/auth/authSlice.tsx b/app/redux/auth/authSlice.tsx index 6652c2e..fe19431 100644 --- a/app/redux/auth/authSlice.tsx +++ b/app/redux/auth/authSlice.tsx @@ -6,6 +6,15 @@ interface AuthState { authMessage: string; status: "idle" | "loading" | "succeeded" | "failed"; error: string | null; + user: { + email: string; + role: string; + } | null; + tokenInfo: { + expiresAt: string; + timeUntilExpiration: number; + expiresInHours: number; + } | null; } const initialState: AuthState = { @@ -13,6 +22,8 @@ const initialState: AuthState = { authMessage: "", status: "idle", error: null, + user: null, + tokenInfo: null, }; // Async Thunk for Login @@ -21,7 +32,7 @@ export const login = createAsyncThunk( "auth/login", async ( { email, password }: { email: string; password: string }, - { rejectWithValue }, + { rejectWithValue } ) => { try { const response = await fetch("/api/auth/login", { @@ -46,14 +57,27 @@ export const login = createAsyncThunk( // Ensure localStorage access is client-side localStorage.setItem("userToken", "mock-authenticated"); // For client-side state sync } - return data.message || "Login successful"; - } catch (error) { - // Handle network errors or other unexpected issues - if (error instanceof Error) { - return rejectWithValue(error.message || "Network error during login"); + + // After successful login, check auth status to get token information + // This ensures we have the token expiration details immediately + const authStatusResponse = await fetch("/api/auth/status"); + if (authStatusResponse.ok) { + const authData = await authStatusResponse.json(); + return { + message: data.message || "Login successful", + user: authData.user, + tokenInfo: authData.tokenInfo, + }; } + + return data.message || "Login successful"; + } catch (error: unknown) { + // Handle network errors or other unexpected issues + const errorMessage = + error instanceof Error ? error.message : "Network error during login"; + return rejectWithValue(errorMessage); } - }, + } ); // Async Thunk for Logout @@ -77,14 +101,95 @@ export const logout = createAsyncThunk( // Ensure localStorage access is client-side localStorage.removeItem("userToken"); // Clear client-side flag } - return data.message || "Logged out successfully"; - } catch (error) { - // Handle network errors - if (error instanceof Error) { - return rejectWithValue(error.message || "Network error during logout"); + + // After successful logout, check auth status to ensure proper cleanup + const authStatusResponse = await fetch("/api/auth/status"); + if (authStatusResponse.ok) { + const authData = await authStatusResponse.json(); + return { + message: data.message || "Logged out successfully", + isAuthenticated: authData.isAuthenticated, + }; } + + return data.message || "Logged out successfully"; + } catch (error: unknown) { + // Handle network errors + const errorMessage = + error instanceof Error ? error.message : "Network error during logout"; + return rejectWithValue(errorMessage); } - }, + } +); + +// Async Thunk for automatic logout (when token expires) +export const autoLogout = createAsyncThunk( + "auth/autoLogout", + async (reason: string, { rejectWithValue }) => { + try { + // Clear the cookie by calling logout endpoint + await fetch("/api/auth/logout", { + method: "DELETE", + }); + + if (typeof window !== "undefined") { + // Clear client-side storage + localStorage.removeItem("userToken"); + } + + return { message: `Auto-logout: ${reason}` }; + } catch (error: unknown) { + const errorMessage = + error instanceof Error ? error.message : "Auto-logout failed"; + return rejectWithValue(errorMessage); + } + } +); + +// Async Thunk for manual refresh of authentication status +export const refreshAuthStatus = createAsyncThunk( + "auth/refreshStatus", + async (_, { rejectWithValue }) => { + try { + const response = await fetch("/api/auth/status"); + const data = await response.json(); + + if (!response.ok) { + return rejectWithValue(data.message || "Authentication refresh failed"); + } + + return data; + } catch (error: unknown) { + const errorMessage = + error instanceof Error + ? error.message + : "Network error during auth refresh"; + return rejectWithValue(errorMessage); + } + } +); + +// Async Thunk for checking authentication status +export const checkAuthStatus = createAsyncThunk( + "auth/checkStatus", + async (_, { rejectWithValue }) => { + try { + const response = await fetch("/api/auth/status"); + const data = await response.json(); + + if (!response.ok) { + return rejectWithValue(data.message || "Authentication check failed"); + } + + return data; + } catch (error: unknown) { + const errorMessage = + error instanceof Error + ? error.message + : "Network error during auth check"; + return rejectWithValue(errorMessage); + } + } ); // Create the authentication slice @@ -122,7 +227,14 @@ const authSlice = createSlice({ .addCase(login.fulfilled, (state, action) => { state.status = "succeeded"; state.isLoggedIn = true; - state.authMessage = action.payload; + // Handle both old string payload and new object payload + if (typeof action.payload === "string") { + state.authMessage = action.payload; + } else { + state.authMessage = action.payload.message; + state.user = action.payload.user || null; + state.tokenInfo = action.payload.tokenInfo || null; + } }) .addCase(login.rejected, (state, action) => { state.status = "failed"; @@ -139,13 +251,86 @@ const authSlice = createSlice({ .addCase(logout.fulfilled, (state, action) => { state.status = "succeeded"; state.isLoggedIn = false; - state.authMessage = action.payload; + // Handle both old string payload and new object payload + if (typeof action.payload === "string") { + state.authMessage = action.payload; + } else { + state.authMessage = action.payload.message; + // Ensure we're properly logged out + if (action.payload.isAuthenticated === false) { + state.user = null; + state.tokenInfo = null; + } + } + // Always clear user data on logout + state.user = null; + state.tokenInfo = null; }) .addCase(logout.rejected, (state, action) => { state.status = "failed"; state.isLoggedIn = true; // Stay logged in if logout failed state.error = action.payload as string; state.authMessage = action.payload as string; // Display error message + }) + // Check Auth Status Thunk Reducers + .addCase(checkAuthStatus.pending, (state) => { + state.status = "loading"; + state.error = null; + }) + .addCase(checkAuthStatus.fulfilled, (state, action) => { + state.status = "succeeded"; + state.isLoggedIn = action.payload.isAuthenticated; + state.user = action.payload.user || null; + state.tokenInfo = action.payload.tokenInfo || null; + state.error = null; + }) + .addCase(checkAuthStatus.rejected, (state, action) => { + state.status = "failed"; + state.isLoggedIn = false; + state.user = null; + state.tokenInfo = null; + state.error = action.payload as string; + }) + // Auto Logout Thunk Reducers + .addCase(autoLogout.pending, (state) => { + state.status = "loading"; + state.error = null; + state.authMessage = "Session expired, logging out..."; + }) + .addCase(autoLogout.fulfilled, (state, action) => { + state.status = "succeeded"; + state.isLoggedIn = false; + state.authMessage = action.payload.message; + state.user = null; + state.tokenInfo = null; + state.error = null; + }) + .addCase(autoLogout.rejected, (state, action) => { + state.status = "failed"; + state.isLoggedIn = false; + state.user = null; + state.tokenInfo = null; + state.error = action.payload as string; + state.authMessage = "Auto-logout failed"; + }) + // Refresh Auth Status Thunk Reducers + .addCase(refreshAuthStatus.pending, (state) => { + state.status = "loading"; + state.error = null; + }) + .addCase(refreshAuthStatus.fulfilled, (state, action) => { + state.status = "succeeded"; + state.isLoggedIn = action.payload.isAuthenticated; + state.user = action.payload.user || null; + state.tokenInfo = action.payload.tokenInfo || null; + state.error = null; + }) + .addCase(refreshAuthStatus.rejected, (state, action) => { + state.status = "failed"; + state.isLoggedIn = false; + state.user = null; + state.tokenInfo = null; + state.error = action.payload as string; }); }, }); diff --git a/app/redux/auth/selectors.ts b/app/redux/auth/selectors.ts index c74bf40..8cac5bf 100644 --- a/app/redux/auth/selectors.ts +++ b/app/redux/auth/selectors.ts @@ -4,3 +4,9 @@ export const selectIsLoggedIn = (state: RootState) => state.auth.isLoggedIn; export const selectStatus = (state: RootState) => state.auth?.status; export const selectError = (state: RootState) => state.auth?.error; export const selectAuthMessage = (state: RootState) => state.auth?.authMessage; +export const selectUser = (state: RootState) => state.auth?.user; +export const selectTokenInfo = (state: RootState) => state.auth?.tokenInfo; +export const selectTimeUntilExpiration = (state: RootState) => + state.auth?.tokenInfo?.timeUntilExpiration || 0; +export const selectExpiresInHours = (state: RootState) => + state.auth?.tokenInfo?.expiresInHours || 0; diff --git a/app/redux/store.ts b/app/redux/store.ts index 3d10547..e08f42b 100644 --- a/app/redux/store.ts +++ b/app/redux/store.ts @@ -8,6 +8,8 @@ export const makeStore = () => { advancedSearch: advancedSearchReducer, auth: authReducer, }, + // Enable Redux DevTools + devTools: process.env.NODE_ENV !== "production", }); }; diff --git a/app/services/approve.ts b/app/services/approve.ts new file mode 100644 index 0000000..f04a0b7 --- /dev/null +++ b/app/services/approve.ts @@ -0,0 +1,22 @@ +export async function getApproves({ + query, +}: { + query: string; +}) { + const res = await fetch( + `http://localhost:3000/api/dashboard/approve?${query}`, + { + cache: "no-store", + }, + ); + + if (!res.ok) { + // Handle error from the API + const errorData = await res + .json() + .catch(() => ({ message: "Unknown error" })); + throw new Error(errorData.message || `HTTP error! status: ${res.status}`); + } + + return res.json(); +} diff --git a/app/utils/auth.ts b/app/utils/auth.ts new file mode 100644 index 0000000..9863027 --- /dev/null +++ b/app/utils/auth.ts @@ -0,0 +1,47 @@ +import { jwtVerify } from "jose"; + +// Secret key for JWT verification (must match the one used for signing) +const JWT_SECRET = new TextEncoder().encode(process.env.JWT_SECRET); + +export interface JWTPayload { + email: string; + role: string; + iat: number; + exp: number; +} + +/** + * Validates a JWT token and returns the payload if valid + */ +export async function validateToken(token: string): Promise { + try { + const { payload } = await jwtVerify(token, JWT_SECRET); + return payload as unknown as JWTPayload; + } catch (error) { + console.error("Token validation error:", error); + return null; + } +} + +/** + * Checks if a token is expired + */ +export function isTokenExpired(payload: JWTPayload): boolean { + const currentTime = Math.floor(Date.now() / 1000); + return payload.exp < currentTime; +} + +/** + * Gets token expiration time in a human-readable format + */ +export function getTokenExpirationTime(payload: JWTPayload): Date { + return new Date(payload.exp * 1000); +} + +/** + * Gets time until token expires in seconds + */ +export function getTimeUntilExpiration(payload: JWTPayload): number { + const currentTime = Math.floor(Date.now() / 1000); + return Math.max(0, payload.exp - currentTime); +} diff --git a/next.config.ts b/next.config.ts index 0030107..ff819d9 100644 --- a/next.config.ts +++ b/next.config.ts @@ -8,6 +8,15 @@ const nextConfig: NextConfig = { } return config; }, + async redirects() { + return [ + { + source: "/", + destination: "/dashboard", + permanent: true, + }, + ]; + }, }; export default nextConfig; diff --git a/package-lock.json b/package-lock.json index cc25ad0..6d3c28f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,14 +14,19 @@ "@mui/material": "^7.1.2", "@mui/x-data-grid": "^8.5.2", "@mui/x-date-pickers": "^8.5.3", + "@reduxjs/toolkit": "^2.8.2", + "clsx": "^2.1.1", "date-fns": "^4.1.0", "dayjs": "^1.11.13", "file-saver": "^2.0.5", + "jose": "^6.0.12", "next": "15.3.3", "react": "^19.0.0", "react-date-range": "^2.0.1", "react-dom": "^19.0.0", + "react-redux": "^9.2.0", "recharts": "^2.15.3", + "sass": "^1.89.2", "xlsx": "^0.18.5" }, "devDependencies": { @@ -31,8 +36,10 @@ "@types/react": "^19", "@types/react-date-range": "^1.4.10", "@types/react-dom": "^19", + "@types/react-redux": "^7.1.34", "eslint": "^9", "eslint-config-next": "15.3.3", + "msw": "^2.10.2", "typescript": "^5" } }, @@ -175,6 +182,37 @@ "node": ">=6.9.0" } }, + "node_modules/@bundled-es-modules/cookie": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz", + "integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cookie": "^0.7.2" + } + }, + "node_modules/@bundled-es-modules/statuses": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", + "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", + "dev": true, + "license": "ISC", + "dependencies": { + "statuses": "^2.0.1" + } + }, + "node_modules/@bundled-es-modules/tough-cookie": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", + "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@types/tough-cookie": "^4.0.5", + "tough-cookie": "^4.1.4" + } + }, "node_modules/@emnapi/core": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", @@ -970,6 +1008,84 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@inquirer/confirm": { + "version": "5.1.14", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.14.tgz", + "integrity": "sha512-5yR4IBfe0kXe59r1YCTG8WXkUbl7Z35HK87Sw+WUyGD8wNUx7JvY7laahzeytyE1oLn74bQnL7hstctQxisQ8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "10.1.15", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.15.tgz", + "integrity": "sha512-8xrp836RZvKkpNbVvgWUlxjT4CraKk2q+I3Ksy+seI2zkcE+y6wNs1BVhgcv8VyImFecUhdQrYLdW32pAjwBdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "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" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.13.tgz", + "integrity": "sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.8.tgz", + "integrity": "sha512-lg9Whz8onIHRthWaN1Q9EGLa/0LFJjyM8mEUbL1eTi6yMGvBf8gvyDLtxSXztQsxMvhxxNpJYrwa1YHdq+w4Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", @@ -1018,6 +1134,24 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mswjs/interceptors": { + "version": "0.39.5", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.39.5.tgz", + "integrity": "sha512-B9nHSJYtsv79uo7QdkZ/b/WoKm20IkVSmTc/WCKarmDtFwM0dRx2ouEniqwNkzCSLn3fydzKmnMzjtfdOWt3VQ==", + "dev": true, + "license": "MIT", + "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" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@mui/core-downloads-tracker": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.2.tgz", @@ -1593,6 +1727,340 @@ "node": ">=12.4.0" } }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher/node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -1603,6 +2071,32 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@reduxjs/toolkit": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.8.2.tgz", + "integrity": "sha512-MYlOhQ0sLdw4ud48FoC5w0dH9VfWQjtCjreKwYTT3l+r427qYC5Y8PihNutepr8XrNaBUDQo9khWUwQxZaqt5A==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -1617,6 +2111,18 @@ "dev": true, "license": "MIT" }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -1643,6 +2149,13 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/d3-array": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", @@ -1720,6 +2233,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz", + "integrity": "sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "hoist-non-react-statics": "^3.3.0" + }, + "peerDependencies": { + "@types/react": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1803,6 +2329,29 @@ "@types/react": "^19.0.0" } }, + "node_modules/@types/react-redux": { + "version": "7.1.34", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.34.tgz", + "integrity": "sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, + "node_modules/@types/react-redux/node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, "node_modules/@types/react-transition-group": { "version": "4.4.12", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", @@ -1812,6 +2361,26 @@ "@types/react": "*" } }, + "node_modules/@types/statuses": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz", + "integrity": "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.34.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.1.tgz", @@ -2417,6 +2986,45 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2700,7 +3308,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -2829,18 +3437,76 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/classnames": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", "license": "MIT" }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -2917,6 +3583,16 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "license": "MIT" }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -3477,6 +4153,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -4014,7 +4700,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -4132,6 +4818,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -4265,6 +4961,16 @@ "dev": true, "license": "MIT" }, + "node_modules/graphql": { + "version": "16.11.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz", + "integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -4358,6 +5064,13 @@ "node": ">= 0.4" } }, + "node_modules/headers-polyfill": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", + "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -4377,6 +5090,22 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/immutable": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", + "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", + "license": "MIT" + }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -4582,7 +5311,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4604,6 +5333,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-generator-function": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", @@ -4627,7 +5366,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -4662,11 +5401,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true, + "license": "MIT" + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -4866,6 +5612,15 @@ "node": ">= 0.4" } }, + "node_modules/jose": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.0.12.tgz", + "integrity": "sha512-T8xypXs8CpmiIi78k0E+Lk7T2zlK4zDyg+o1CZ4AkOHgDg98ogdP2BeZ61lTFKFyoEwJ9RgAgN+SdM3iPgNonQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5068,7 +5823,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -5107,6 +5862,61 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/msw": { + "version": "2.10.4", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.10.4.tgz", + "integrity": "sha512-6R1or/qyele7q3RyPwNuvc0IxO8L8/Aim6Sz5ncXEgcWUNxSKE+udriTOWHtpMwmfkLYlacA2y7TIx4cL5lgHA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "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.39.1", + "@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" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.8.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -5202,6 +6012,13 @@ } } }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT", + "optional": true + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5342,6 +6159,13 @@ "node": ">= 0.8.0" } }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "dev": true, + "license": "MIT" + }, "node_modules/own-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", @@ -5448,6 +6272,13 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "license": "MIT" }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -5467,7 +6298,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -5535,6 +6366,19 @@ "react-is": "^16.13.1" } }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5545,6 +6389,13 @@ "node": ">=6" } }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true, + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -5618,6 +6469,29 @@ "react": "0.14 || 15 - 19" } }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, "node_modules/react-smooth": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", @@ -5649,6 +6523,19 @@ "react-dom": ">=16.6.0" } }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/recharts": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz", @@ -5687,6 +6574,21 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "license": "MIT" }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -5731,6 +6633,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true, + "license": "MIT" + }, "node_modules/reselect": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", @@ -5866,6 +6785,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sass": { + "version": "1.90.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.90.0.tgz", + "integrity": "sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==", + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, "node_modules/scheduler": { "version": "0.26.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", @@ -6081,6 +7020,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -6128,6 +7080,16 @@ "dev": true, "license": "MIT" }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/stop-iteration-iterator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", @@ -6150,6 +7112,35 @@ "node": ">=10.0.0" } }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, "node_modules/string.prototype.includes": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", @@ -6263,6 +7254,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -6395,7 +7399,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -6404,6 +7408,22 @@ "node": ">=8.0" } }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -6449,6 +7469,19 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -6567,6 +7600,16 @@ "dev": true, "license": "MIT" }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/unrs-resolver": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.9.0.tgz", @@ -6612,6 +7655,17 @@ "punycode": "^2.1.0" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/use-sync-external-store": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", @@ -6776,6 +7830,21 @@ "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/xlsx": { "version": "0.18.5", "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", @@ -6797,6 +7866,16 @@ "node": ">=0.8" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", @@ -6806,6 +7885,35 @@ "node": ">= 6" } }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "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" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -6818,6 +7926,19 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index c37bf54..363e708 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "date-fns": "^4.1.0", "dayjs": "^1.11.13", "file-saver": "^2.0.5", + "jose": "^6.0.12", "next": "15.3.3", "react": "^19.0.0", "react-date-range": "^2.0.1", diff --git a/public/mockServiceWorker.js b/public/mockServiceWorker.js index de7bc0f..be4527c 100644 --- a/public/mockServiceWorker.js +++ b/public/mockServiceWorker.js @@ -7,7 +7,7 @@ * - Please do NOT modify this file. */ -const PACKAGE_VERSION = '2.10.2' +const PACKAGE_VERSION = '2.10.4' const INTEGRITY_CHECKSUM = 'f5825c521429caf22a4dd13b66e243af' const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') const activeClientIds = new Set() diff --git a/services/roles.services.ts b/services/roles.services.ts index 4f14b61..f134a9a 100644 --- a/services/roles.services.ts +++ b/services/roles.services.ts @@ -1,6 +1,6 @@ import { IEditUserForm } from "@/app/features/UserRoles/User.interfaces"; -export async function createRole(data: IEditUserForm) { +export async function addUser(data: IEditUserForm) { const res = await fetch("/api/dashboard/admin/users", { method: "POST", headers: { "Content-Type": "application/json" }, @@ -13,3 +13,18 @@ export async function createRole(data: IEditUserForm) { return res.json(); // or return type depending on your backend } +export async function editUser(id: string, data: IEditUserForm) { + console.log("[editUser] - id", id, data); + const res = await fetch(`/api/dashboard/admin/users/${id}`, { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(data), + }); + + if (!res.ok) { + console.log("[editUser] - FAILING", id, data); + throw new Error("Failed to update user"); + } + + return res.json(); +} diff --git a/yarn.lock b/yarn.lock index 2400af5..9d82a29 100644 --- a/yarn.lock +++ b/yarn.lock @@ -84,48 +84,26 @@ "@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" + resolved "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz" 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" + resolved "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz" 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" + resolved "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz" integrity sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw== dependencies: "@types/tough-cookie" "^4.0.5" tough-cookie "^4.1.4" -"@emnapi/core@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.4.3.tgz#9ac52d2d5aea958f67e52c40a065f51de59b77d6" - integrity sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g== - dependencies: - "@emnapi/wasi-threads" "1.0.2" - tslib "^2.4.0" - -"@emnapi/runtime@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.4.3.tgz#c0564665c80dc81c448adac23f9dfbed6c838f7d" - integrity sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ== - dependencies: - tslib "^2.4.0" - -"@emnapi/wasi-threads@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz#977f44f844eac7d6c138a415a123818c655f874c" - integrity sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA== - dependencies: - tslib "^2.4.0" - "@emotion/babel-plugin@^11.13.5": version "11.13.5" resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz" @@ -171,7 +149,7 @@ resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz" integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ== -"@emotion/react@^11.14.0": +"@emotion/react@^11.0.0-rc.0", "@emotion/react@^11.14.0", "@emotion/react@^11.4.1", "@emotion/react@^11.5.0", "@emotion/react@^11.9.0": version "11.14.0" resolved "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz" integrity sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA== @@ -201,7 +179,7 @@ resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz" integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg== -"@emotion/styled@^11.14.0": +"@emotion/styled@^11.14.0", "@emotion/styled@^11.3.0", "@emotion/styled@^11.8.1": version "11.14.0" resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz" integrity sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA== @@ -334,144 +312,26 @@ resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz" integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== -"@img/sharp-darwin-arm64@0.34.2": - version "0.34.2" - resolved "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.2.tgz" - integrity sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg== - optionalDependencies: - "@img/sharp-libvips-darwin-arm64" "1.1.0" - -"@img/sharp-darwin-x64@0.34.2": - version "0.34.2" - resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.2.tgz#d37ff7c75c46d5a68a3756e3f1924ef7ca7b285e" - integrity sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g== - optionalDependencies: - "@img/sharp-libvips-darwin-x64" "1.1.0" - -"@img/sharp-libvips-darwin-arm64@1.1.0": - version "1.1.0" - resolved "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz" - integrity sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA== - -"@img/sharp-libvips-darwin-x64@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz#1239c24426c06a8e833815562f78047a3bfbaaf8" - integrity sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ== - -"@img/sharp-libvips-linux-arm64@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz#20d276cefd903ee483f0441ba35961679c286315" - integrity sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew== - -"@img/sharp-libvips-linux-arm@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz#067c0b566eae8063738cf1b1db8f8a8573b5465c" - integrity sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA== - -"@img/sharp-libvips-linux-ppc64@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz#682334595f2ca00e0a07a675ba170af165162802" - integrity sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ== - -"@img/sharp-libvips-linux-s390x@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz#82fcd68444b3666384235279c145c2b28d8ee302" - integrity sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA== - -"@img/sharp-libvips-linux-x64@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz#65b2b908bf47156b0724fde9095676c83a18cf5a" - integrity sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q== - -"@img/sharp-libvips-linuxmusl-arm64@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz#72accf924e80b081c8db83b900b444a67c203f01" - integrity sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w== - -"@img/sharp-libvips-linuxmusl-x64@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz#1fa052737e203f46bf44192acd01f9faf11522d7" - integrity sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A== - -"@img/sharp-linux-arm64@0.34.2": - version "0.34.2" - resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.2.tgz#c9690fac5f3137eaab3f7ad6065390d10f66f1fa" - integrity sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q== - optionalDependencies: - "@img/sharp-libvips-linux-arm64" "1.1.0" - -"@img/sharp-linux-arm@0.34.2": - version "0.34.2" - resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.2.tgz#771dd2ec645f85f98441359bfc118afaf38cbd8b" - integrity sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ== - optionalDependencies: - "@img/sharp-libvips-linux-arm" "1.1.0" - -"@img/sharp-linux-s390x@0.34.2": - version "0.34.2" - resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.2.tgz#82132d158abff57bd90b53574f2865f72f94e6c8" - integrity sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw== - optionalDependencies: - "@img/sharp-libvips-linux-s390x" "1.1.0" - -"@img/sharp-linux-x64@0.34.2": - version "0.34.2" - resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.2.tgz#d815fb87899d462b28b62a9252ad127f02fe0740" - integrity sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ== - optionalDependencies: - "@img/sharp-libvips-linux-x64" "1.1.0" - -"@img/sharp-linuxmusl-arm64@0.34.2": - version "0.34.2" - resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.2.tgz#cfac45b2abbc04628f676e123bfe3aeb300266c7" - integrity sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA== - optionalDependencies: - "@img/sharp-libvips-linuxmusl-arm64" "1.1.0" - -"@img/sharp-linuxmusl-x64@0.34.2": - version "0.34.2" - resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.2.tgz#b876c23ff51d0fb6d9f3b0a07e2f4d1436c203ad" - integrity sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA== - optionalDependencies: - "@img/sharp-libvips-linuxmusl-x64" "1.1.0" - -"@img/sharp-wasm32@0.34.2": - version "0.34.2" - resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.34.2.tgz#b1dd0bab547dccf517586eb1fa5852160bba3b82" - integrity sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ== - dependencies: - "@emnapi/runtime" "^1.4.3" - -"@img/sharp-win32-arm64@0.34.2": - version "0.34.2" - resolved "https://registry.yarnpkg.com/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.2.tgz#f37bee0f60c167f825a09d2b8de6849b823e8b30" - integrity sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ== - -"@img/sharp-win32-ia32@0.34.2": - version "0.34.2" - resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.2.tgz#8fc30b6655bc6ff8910344a2020d334aa6361672" - integrity sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw== - "@img/sharp-win32-x64@0.34.2": version "0.34.2" - resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.2.tgz#ecf19250f8fe35de684aa2b0ec6f773b3447247b" + resolved "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.2.tgz" integrity sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw== "@inquirer/confirm@^5.0.0": - version "5.1.13" - resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-5.1.13.tgz#4931515edc63e25d833c9a40ccf1855e8e822dbc" - integrity sha512-EkCtvp67ICIVVzjsquUiVSd+V5HRGOGQfsqA4E4vMWhYnB7InUL0pa0TIWt1i+OfP16Gkds8CdIu6yGZwOM1Yw== + version "5.1.14" + resolved "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.14.tgz" + integrity sha512-5yR4IBfe0kXe59r1YCTG8WXkUbl7Z35HK87Sw+WUyGD8wNUx7JvY7laahzeytyE1oLn74bQnL7hstctQxisQ8Q== dependencies: - "@inquirer/core" "^10.1.14" - "@inquirer/type" "^3.0.7" + "@inquirer/core" "^10.1.15" + "@inquirer/type" "^3.0.8" -"@inquirer/core@^10.1.14": - version "10.1.14" - resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-10.1.14.tgz#7678b2daaecf32fa2f6e02a03dc235f9620e197f" - integrity sha512-Ma+ZpOJPewtIYl6HZHZckeX1STvDnHTCB2GVINNUlSEn2Am6LddWwfPkIGY0IUFVjUUrr/93XlBwTK6mfLjf0A== +"@inquirer/core@^10.1.15": + version "10.1.15" + resolved "https://registry.npmjs.org/@inquirer/core/-/core-10.1.15.tgz" + integrity sha512-8xrp836RZvKkpNbVvgWUlxjT4CraKk2q+I3Ksy+seI2zkcE+y6wNs1BVhgcv8VyImFecUhdQrYLdW32pAjwBdA== dependencies: - "@inquirer/figures" "^1.0.12" - "@inquirer/type" "^3.0.7" + "@inquirer/figures" "^1.0.13" + "@inquirer/type" "^3.0.8" ansi-escapes "^4.3.2" cli-width "^4.1.0" mute-stream "^2.0.0" @@ -479,15 +339,15 @@ wrap-ansi "^6.2.0" yoctocolors-cjs "^2.1.2" -"@inquirer/figures@^1.0.12": - version "1.0.12" - resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.12.tgz#667d6254cc7ba3b0c010a323d78024a1d30c6053" - integrity sha512-MJttijd8rMFcKJC8NYmprWr6hD3r9Gd9qUC0XwPNwoEPWSMVJwA2MlXxF+nhZZNMY+HXsWa+o7KY2emWYIn0jQ== +"@inquirer/figures@^1.0.13": + version "1.0.13" + resolved "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.13.tgz" + integrity sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw== -"@inquirer/type@^3.0.7": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-3.0.7.tgz#b46bcf377b3172dbc768fdbd053e6492ad801a09" - integrity sha512-PfunHQcjwnju84L+ycmcMKB/pTPIngjUJvfnRhKY6FKPuYXlM4aQCb/nIdTFR6BEhMjFvngzvng/vBAJMZpLSA== +"@inquirer/type@^3.0.8": + version "3.0.8" + resolved "https://registry.npmjs.org/@inquirer/type/-/type-3.0.8.tgz" + integrity sha512-lg9Whz8onIHRthWaN1Q9EGLa/0LFJjyM8mEUbL1eTi6yMGvBf8gvyDLtxSXztQsxMvhxxNpJYrwa1YHdq+w4Jw== "@jridgewell/gen-mapping@^0.3.5": version "0.3.8" @@ -522,9 +382,9 @@ "@jridgewell/sourcemap-codec" "^1.4.14" "@mswjs/interceptors@^0.39.1": - version "0.39.2" - resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.39.2.tgz#de9de0ab23f99d387c7904df7219a92157d1d666" - integrity sha512-RuzCup9Ct91Y7V79xwCb146RaBRHZ7NBbrIUySumd1rpKqHL5OonaqrGIbug5hNwP/fRyxFMA6ISgw4FTtYFYg== + version "0.39.5" + resolved "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.39.5.tgz" + integrity sha512-B9nHSJYtsv79uo7QdkZ/b/WoKm20IkVSmTc/WCKarmDtFwM0dRx2ouEniqwNkzCSLn3fydzKmnMzjtfdOWt3VQ== dependencies: "@open-draft/deferred-promise" "^2.2.0" "@open-draft/logger" "^0.3.0" @@ -545,7 +405,7 @@ dependencies: "@babel/runtime" "^7.27.1" -"@mui/material@^7.1.2": +"@mui/material@^5.15.14 || ^6.0.0 || ^7.0.0", "@mui/material@^7.1.2": version "7.1.2" resolved "https://registry.npmjs.org/@mui/material/-/material-7.1.2.tgz" integrity sha512-Z5PYKkA6Kd8vS04zKxJNpwuvt6IoMwqpbidV7RCrRQQKwczIwcNcS8L6GnN4pzFYfEs+N9v6co27DmG07rcnoA== @@ -584,7 +444,7 @@ csstype "^3.1.3" prop-types "^15.8.1" -"@mui/system@^7.1.1": +"@mui/system@^5.15.14 || ^6.0.0 || ^7.0.0", "@mui/system@^7.1.1": version "7.1.1" resolved "https://registry.npmjs.org/@mui/system/-/system-7.1.1.tgz" integrity sha512-Kj1uhiqnj4Zo7PDjAOghtXJtNABunWvhcRU0O7RQJ7WOxeynoH6wXPcilphV8QTFtkKaip8EiNJRiCD+B3eROA== @@ -651,15 +511,6 @@ "@mui/utils" "^7.1.1" reselect "^5.1.1" -"@napi-rs/wasm-runtime@^0.2.11": - version "0.2.11" - resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz#192c1610e1625048089ab4e35bc0649ce478500e" - integrity sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA== - dependencies: - "@emnapi/core" "^1.4.3" - "@emnapi/runtime" "^1.4.3" - "@tybys/wasm-util" "^0.9.0" - "@next/env@15.3.3": version "15.3.3" resolved "https://registry.npmjs.org/@next/env/-/env-15.3.3.tgz" @@ -672,44 +523,9 @@ dependencies: fast-glob "3.3.1" -"@next/swc-darwin-arm64@15.3.3": - version "15.3.3" - resolved "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.3.tgz" - integrity sha512-WRJERLuH+O3oYB4yZNVahSVFmtxRNjNF1I1c34tYMoJb0Pve+7/RaLAJJizyYiFhjYNGHRAE1Ri2Fd23zgDqhg== - -"@next/swc-darwin-x64@15.3.3": - version "15.3.3" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.3.tgz#71588bad245180ffd1af1e1f894477287e739eb0" - integrity sha512-XHdzH/yBc55lu78k/XwtuFR/ZXUTcflpRXcsu0nKmF45U96jt1tsOZhVrn5YH+paw66zOANpOnFQ9i6/j+UYvw== - -"@next/swc-linux-arm64-gnu@15.3.3": - version "15.3.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.3.tgz#66a15f749c14f04a89f8c7e21c7a8d343fc34e6e" - integrity sha512-VZ3sYL2LXB8znNGcjhocikEkag/8xiLgnvQts41tq6i+wql63SMS1Q6N8RVXHw5pEUjiof+II3HkDd7GFcgkzw== - -"@next/swc-linux-arm64-musl@15.3.3": - version "15.3.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.3.tgz#14bd66213f7f33d6909574750bcb05037221a2ac" - integrity sha512-h6Y1fLU4RWAp1HPNJWDYBQ+e3G7sLckyBXhmH9ajn8l/RSMnhbuPBV/fXmy3muMcVwoJdHL+UtzRzs0nXOf9SA== - -"@next/swc-linux-x64-gnu@15.3.3": - version "15.3.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.3.tgz#4a19434545e5e752d9a3ed71f9b34982725f6293" - integrity sha512-jJ8HRiF3N8Zw6hGlytCj5BiHyG/K+fnTKVDEKvUCyiQ/0r5tgwO7OgaRiOjjRoIx2vwLR+Rz8hQoPrnmFbJdfw== - -"@next/swc-linux-x64-musl@15.3.3": - version "15.3.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.3.tgz#41ab140dd0a04ab7291adbec5836c1ce251a588c" - integrity sha512-HrUcTr4N+RgiiGn3jjeT6Oo208UT/7BuTr7K0mdKRBtTbT4v9zJqCDKO97DUqqoBK1qyzP1RwvrWTvU6EPh/Cw== - -"@next/swc-win32-arm64-msvc@15.3.3": - version "15.3.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.3.tgz#fcd1d7e0007b7b73d1acdbf0ad6d91f7aa2deb15" - integrity sha512-SxorONgi6K7ZUysMtRF3mIeHC5aA3IQLmKFQzU0OuhuUYwpOBc1ypaLJLP5Bf3M9k53KUUUj4vTPwzGvl/NwlQ== - "@next/swc-win32-x64-msvc@15.3.3": version "15.3.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.3.tgz#c0e33e069d7922dd0546cac77a0247ad81d4a1aa" + resolved "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.3.tgz" integrity sha512-4QZG6F8enl9/S2+yIiOiju0iCTFd93d8VC1q9LZS4p/Xuk81W2QDjCFeoogmrWWkAD59z8ZxepBQap2dKS5ruw== "@nodelib/fs.scandir@2.1.5": @@ -720,7 +536,7 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": version "2.0.5" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== @@ -740,12 +556,12 @@ "@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" + resolved "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz" 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" + resolved "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz" integrity sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ== dependencies: is-node-process "^1.2.0" @@ -753,77 +569,17 @@ "@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" + resolved "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz" integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== -"@parcel/watcher-android-arm64@2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz#507f836d7e2042f798c7d07ad19c3546f9848ac1" - integrity sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA== - -"@parcel/watcher-darwin-arm64@2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz#3d26dce38de6590ef79c47ec2c55793c06ad4f67" - integrity sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw== - -"@parcel/watcher-darwin-x64@2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz#99f3af3869069ccf774e4ddfccf7e64fd2311ef8" - integrity sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg== - -"@parcel/watcher-freebsd-x64@2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz#14d6857741a9f51dfe51d5b08b7c8afdbc73ad9b" - integrity sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ== - -"@parcel/watcher-linux-arm-glibc@2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz#43c3246d6892381db473bb4f663229ad20b609a1" - integrity sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA== - -"@parcel/watcher-linux-arm-musl@2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz#663750f7090bb6278d2210de643eb8a3f780d08e" - integrity sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q== - -"@parcel/watcher-linux-arm64-glibc@2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz#ba60e1f56977f7e47cd7e31ad65d15fdcbd07e30" - integrity sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w== - -"@parcel/watcher-linux-arm64-musl@2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz#f7fbcdff2f04c526f96eac01f97419a6a99855d2" - integrity sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg== - -"@parcel/watcher-linux-x64-glibc@2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz#4d2ea0f633eb1917d83d483392ce6181b6a92e4e" - integrity sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A== - -"@parcel/watcher-linux-x64-musl@2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz#277b346b05db54f55657301dd77bdf99d63606ee" - integrity sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg== - -"@parcel/watcher-win32-arm64@2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz#7e9e02a26784d47503de1d10e8eab6cceb524243" - integrity sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw== - -"@parcel/watcher-win32-ia32@2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz#2d0f94fa59a873cdc584bf7f6b1dc628ddf976e6" - integrity sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ== - "@parcel/watcher-win32-x64@2.5.1": version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz#ae52693259664ba6f2228fa61d7ee44b64ea0947" + resolved "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz" integrity sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA== "@parcel/watcher@^2.4.1": version "2.5.1" - resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.5.1.tgz#342507a9cfaaf172479a882309def1e991fb1200" + resolved "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz" integrity sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg== dependencies: detect-libc "^1.0.3" @@ -852,7 +608,7 @@ "@reduxjs/toolkit@^2.8.2": version "2.8.2" - resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-2.8.2.tgz#f4e9f973c6fc930c1e0f3bf462cc95210c28f5f9" + resolved "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.8.2.tgz" integrity sha512-MYlOhQ0sLdw4ud48FoC5w0dH9VfWQjtCjreKwYTT3l+r427qYC5Y8PihNutepr8XrNaBUDQo9khWUwQxZaqt5A== dependencies: "@standard-schema/spec" "^1.0.0" @@ -874,12 +630,12 @@ "@standard-schema/spec@^1.0.0": version "1.0.0" - resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.0.0.tgz#f193b73dc316c4170f2e82a881da0f550d551b9c" + resolved "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz" integrity sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA== "@standard-schema/utils@^0.3.0": version "0.3.0" - resolved "https://registry.yarnpkg.com/@standard-schema/utils/-/utils-0.3.0.tgz#3d5e608f16c2390c10528e98e59aef6bf73cae7b" + resolved "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz" integrity sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g== "@swc/counter@0.1.3": @@ -894,16 +650,9 @@ dependencies: tslib "^2.8.0" -"@tybys/wasm-util@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.9.0.tgz#3e75eb00604c8d6db470bf18c37b7d984a0e3355" - integrity sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw== - dependencies: - tslib "^2.4.0" - "@types/cookie@^0.6.0": version "0.6.0" - resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" + resolved "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz" integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== "@types/d3-array@^3.0.3": @@ -968,11 +717,10 @@ integrity sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A== "@types/hoist-non-react-statics@^3.3.0": - version "3.3.6" - resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz#6bba74383cdab98e8db4e20ce5b4a6b98caed010" - integrity sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw== + version "3.3.7" + resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz" + integrity sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g== dependencies: - "@types/react" "*" hoist-non-react-statics "^3.3.0" "@types/json-schema@^7.0.15": @@ -985,7 +733,7 @@ resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/node@^20": +"@types/node@^20", "@types/node@>=18": version "20.19.1" resolved "https://registry.npmjs.org/@types/node/-/node-20.19.1.tgz" integrity sha512-jJD50LtlD2dodAEO653i3YF04NWak6jN3ky+Ri3Em3mGR39/glWiboM/IePaRbgwSfqM1TpGXfAg8ohn/4dTgA== @@ -1017,7 +765,7 @@ "@types/react-redux@^7.1.34": version "7.1.34" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.34.tgz#83613e1957c481521e6776beeac4fd506d11bd0e" + resolved "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.34.tgz" integrity sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ== dependencies: "@types/hoist-non-react-statics" "^3.3.0" @@ -1030,7 +778,7 @@ resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz" integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w== -"@types/react@*", "@types/react@^19": +"@types/react@*", "@types/react@^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react@^18.2.25 || ^19", "@types/react@^19", "@types/react@^19.0.0": version "19.1.8" resolved "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz" integrity sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g== @@ -1039,17 +787,17 @@ "@types/statuses@^2.0.4": version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/statuses/-/statuses-2.0.6.tgz#66748315cc9a96d63403baa8671b2c124f8633aa" + resolved "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz" integrity sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA== "@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" + resolved "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz" integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== "@types/use-sync-external-store@^0.0.6": version "0.0.6" - resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz#60be8d21baab8c305132eb9cb912ed497852aadc" + resolved "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz" integrity sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg== "@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": @@ -1067,7 +815,7 @@ natural-compare "^1.4.0" ts-api-utils "^2.1.0" -"@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": +"@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser@^8.34.1": version "8.34.1" resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.1.tgz" integrity sha512-4O3idHxhyzjClSMJ0a29AcoK0+YwnEqzI6oz3vlRf3xw0zbzt15MzXwItOlnr5nIth6zlY2RENLsOPvhyrKAQA== @@ -1095,7 +843,7 @@ "@typescript-eslint/types" "8.34.1" "@typescript-eslint/visitor-keys" "8.34.1" -"@typescript-eslint/tsconfig-utils@8.34.1", "@typescript-eslint/tsconfig-utils@^8.34.1": +"@typescript-eslint/tsconfig-utils@^8.34.1", "@typescript-eslint/tsconfig-utils@8.34.1": version "8.34.1" resolved "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.1.tgz" integrity sha512-K4Sjdo4/xF9NEeA2khOb7Y5nY6NSXBnod87uniVYW9kHP+hNlDV8trUSFeynA2uxWam4gIWgWoygPrv9VMWrYg== @@ -1110,7 +858,7 @@ debug "^4.3.4" ts-api-utils "^2.1.0" -"@typescript-eslint/types@8.34.1", "@typescript-eslint/types@^8.34.1": +"@typescript-eslint/types@^8.34.1", "@typescript-eslint/types@8.34.1": version "8.34.1" resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.1.tgz" integrity sha512-rjLVbmE7HR18kDsjNIZQHxmv9RZwlgzavryL5Lnj2ujIRTeXlKtILHgRNmQ3j4daw7zd+mQgy+uyt6Zo6I0IGA== @@ -1149,101 +897,9 @@ "@typescript-eslint/types" "8.34.1" eslint-visitor-keys "^4.2.1" -"@unrs/resolver-binding-android-arm-eabi@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.9.0.tgz#e91317973356eb845c9186db5f9ec43e8d0002eb" - integrity sha512-h1T2c2Di49ekF2TE8ZCoJkb+jwETKUIPDJ/nO3tJBKlLFPu+fyd93f0rGP/BvArKx2k2HlRM4kqkNarj3dvZlg== - -"@unrs/resolver-binding-android-arm64@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.9.0.tgz#fbdd79b2a8e478e02e1c0751dfbc100017522161" - integrity sha512-sG1NHtgXtX8owEkJ11yn34vt0Xqzi3k9TJ8zppDmyG8GZV4kVWw44FHwKwHeEFl07uKPeC4ZoyuQaGh5ruJYPA== - -"@unrs/resolver-binding-darwin-arm64@1.9.0": - version "1.9.0" - resolved "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.9.0.tgz" - integrity sha512-nJ9z47kfFnCxN1z/oYZS7HSNsFh43y2asePzTEZpEvK7kGyuShSl3RRXnm/1QaqFL+iP+BjMwuB+DYUymOkA5A== - -"@unrs/resolver-binding-darwin-x64@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.9.0.tgz#4a205940ec311ac8396c3f25043644b78cc98a20" - integrity sha512-TK+UA1TTa0qS53rjWn7cVlEKVGz2B6JYe0C++TdQjvWYIyx83ruwh0wd4LRxYBM5HeuAzXcylA9BH2trARXJTw== - -"@unrs/resolver-binding-freebsd-x64@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.9.0.tgz#ed82e000f7248011696ecc8894f574caa197b0be" - integrity sha512-6uZwzMRFcD7CcCd0vz3Hp+9qIL2jseE/bx3ZjaLwn8t714nYGwiE84WpaMCYjU+IQET8Vu/+BNAGtYD7BG/0yA== - -"@unrs/resolver-binding-linux-arm-gnueabihf@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.9.0.tgz#534a8b32118590f7fb9edd21c6576243a89a8aad" - integrity sha512-bPUBksQfrgcfv2+mm+AZinaKq8LCFvt5PThYqRotqSuuZK1TVKkhbVMS/jvSRfYl7jr3AoZLYbDkItxgqMKRkg== - -"@unrs/resolver-binding-linux-arm-musleabihf@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.9.0.tgz#b31718752e77cecbbcf7ba1e01dea97c1a5ee7e0" - integrity sha512-uT6E7UBIrTdCsFQ+y0tQd3g5oudmrS/hds5pbU3h4s2t/1vsGWbbSKhBSCD9mcqaqkBwoqlECpUrRJCmldl8PA== - -"@unrs/resolver-binding-linux-arm64-gnu@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.9.0.tgz#0f11ba195020cfa869533fb74733d68162349d14" - integrity sha512-vdqBh911wc5awE2bX2zx3eflbyv8U9xbE/jVKAm425eRoOVv/VseGZsqi3A3SykckSpF4wSROkbQPvbQFn8EsA== - -"@unrs/resolver-binding-linux-arm64-musl@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.9.0.tgz#8b6bc086cf9efaa22e8f2fef381786d6636b8e19" - integrity sha512-/8JFZ/SnuDr1lLEVsxsuVwrsGquTvT51RZGvyDB/dOK3oYK2UqeXzgeyq6Otp8FZXQcEYqJwxb9v+gtdXn03eQ== - -"@unrs/resolver-binding-linux-ppc64-gnu@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.9.0.tgz#5cd15899af31c2bbf90bfca5f798f64a16770e23" - integrity sha512-FkJjybtrl+rajTw4loI3L6YqSOpeZfDls4SstL/5lsP2bka9TiHUjgMBjygeZEis1oC8LfJTS8FSgpKPaQx2tQ== - -"@unrs/resolver-binding-linux-riscv64-gnu@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.9.0.tgz#4f2c75af52437eb10b48ea5b72750fb65fb174be" - integrity sha512-w/NZfHNeDusbqSZ8r/hp8iL4S39h4+vQMc9/vvzuIKMWKppyUGKm3IST0Qv0aOZ1rzIbl9SrDeIqK86ZpUK37w== - -"@unrs/resolver-binding-linux-riscv64-musl@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.9.0.tgz#6a87e82e0dd39d34ff37ddba6accf73cdb396e86" - integrity sha512-bEPBosut8/8KQbUixPry8zg/fOzVOWyvwzOfz0C0Rw6dp+wIBseyiHKjkcSyZKv/98edrbMknBaMNJfA/UEdqw== - -"@unrs/resolver-binding-linux-s390x-gnu@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.9.0.tgz#6524cc3c01309022de86c4a7317fe7d9f9fb855c" - integrity sha512-LDtMT7moE3gK753gG4pc31AAqGUC86j3AplaFusc717EUGF9ZFJ356sdQzzZzkBk1XzMdxFyZ4f/i35NKM/lFA== - -"@unrs/resolver-binding-linux-x64-gnu@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.9.0.tgz#85fb8a45dccf3823cd73ea4b61b2c3f2e8ab6653" - integrity sha512-WmFd5KINHIXj8o1mPaT8QRjA9HgSXhN1gl9Da4IZihARihEnOylu4co7i/yeaIpcfsI6sYs33cNZKyHYDh0lrA== - -"@unrs/resolver-binding-linux-x64-musl@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.9.0.tgz#235e539da5872df51c03e0e050a1c715e25044ca" - integrity sha512-CYuXbANW+WgzVRIl8/QvZmDaZxrqvOldOwlbUjIM4pQ46FJ0W5cinJ/Ghwa/Ng1ZPMJMk1VFdsD/XwmCGIXBWg== - -"@unrs/resolver-binding-wasm32-wasi@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.9.0.tgz#1bc614ce2ba61330c16bffa1e50f41d95d25c0a6" - integrity sha512-6Rp2WH0OoitMYR57Z6VE8Y6corX8C6QEMWLgOV6qXiJIeZ1F9WGXY/yQ8yDC4iTraotyLOeJ2Asea0urWj2fKQ== - dependencies: - "@napi-rs/wasm-runtime" "^0.2.11" - -"@unrs/resolver-binding-win32-arm64-msvc@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.9.0.tgz#0d8704275a9f2634d81b35d8a00a2f4bd8dec7fa" - integrity sha512-rknkrTRuvujprrbPmGeHi8wYWxmNVlBoNW8+4XF2hXUnASOjmuC9FNF1tGbDiRQWn264q9U/oGtixyO3BT8adQ== - -"@unrs/resolver-binding-win32-ia32-msvc@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.9.0.tgz#46909cbeb9a38b3f31a64833fe03aa1aebb8da2b" - integrity sha512-Ceymm+iBl+bgAICtgiHyMLz6hjxmLJKqBim8tDzpX61wpZOx2bPK6Gjuor7I2RiUynVjvvkoRIkrPyMwzBzF3A== - "@unrs/resolver-binding-win32-x64-msvc@1.9.0": version "1.9.0" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.9.0.tgz#708b957d5d66543c45240b4c6b45ee63ed59b6b7" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.9.0.tgz" integrity sha512-k59o9ZyeyS0hAlcaKFezYSH2agQeRFEB7KoQLXl3Nb3rgkqT1NY9Vwy+SqODiLmYnEjxWJVRE/yq2jFVqdIxZw== acorn-jsx@^5.3.2: @@ -1251,7 +907,7 @@ acorn-jsx@^5.3.2: resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.15.0: +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.15.0: version "8.15.0" resolved "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz" integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== @@ -1273,14 +929,14 @@ ajv@^6.12.4: ansi-escapes@^4.3.2: version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== dependencies: type-fest "^0.21.3" ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-styles@^4.0.0, ansi-styles@^4.1.0: @@ -1515,7 +1171,7 @@ chalk@^4.0.0: chokidar@^4.0.0: version "4.0.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz" integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== dependencies: readdirp "^4.0.1" @@ -1527,7 +1183,7 @@ classnames@^2.2.6: cli-width@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" + resolved "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz" integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== client-only@0.0.1: @@ -1537,7 +1193,7 @@ client-only@0.0.1: cliui@^8.0.1: version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" @@ -1594,7 +1250,7 @@ convert-source-map@^1.5.0: cookie@^0.7.2: version "0.7.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== cosmiconfig@^7.0.0: @@ -1627,7 +1283,7 @@ csstype@^3.0.2, csstype@^3.1.3: resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== -"d3-array@2 - 3", "d3-array@2.10.0 - 3", d3-array@^3.1.6: +d3-array@^3.1.6, "d3-array@2 - 3", "d3-array@2.10.0 - 3": version "3.2.4" resolved "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz" integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== @@ -1649,7 +1305,7 @@ d3-ease@^3.0.1: resolved "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz" integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== -"d3-interpolate@1.2.0 - 3", d3-interpolate@^3.0.1: +d3-interpolate@^3.0.1, "d3-interpolate@1.2.0 - 3": version "3.0.1" resolved "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz" integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== @@ -1686,7 +1342,7 @@ d3-shape@^3.1.0: dependencies: d3-time "1 - 3" -"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@^3.0.0: +d3-time@^3.0.0, "d3-time@1 - 3", "d3-time@2.1.1 - 3": version "3.1.0" resolved "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz" integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== @@ -1737,12 +1393,12 @@ date-fns@^2.16.1: dependencies: "@babel/runtime" "^7.21.0" -date-fns@^4.1.0: +"date-fns@^2.25.0 || ^3.2.0 || ^4.0.0", date-fns@^4.1.0, "date-fns@3.0.6 || >=3.0.0": version "4.1.0" resolved "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz" integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg== -dayjs@^1.11.13: +dayjs@^1.10.7, dayjs@^1.11.13: version "1.11.13" resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== @@ -1791,7 +1447,7 @@ define-properties@^1.1.3, define-properties@^1.2.1: detect-libc@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz" integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== detect-libc@^2.0.4: @@ -1825,7 +1481,7 @@ dunder-proto@^1.0.0, dunder-proto@^1.0.1: emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== emoji-regex@^9.2.2: @@ -1967,7 +1623,7 @@ es-to-primitive@^1.3.0: escalade@^3.1.1: version "3.2.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz" integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-string-regexp@^4.0.0: @@ -2020,7 +1676,7 @@ eslint-module-utils@^2.12.0: dependencies: debug "^3.2.7" -eslint-plugin-import@^2.31.0: +eslint-plugin-import@*, eslint-plugin-import@^2.31.0: version "2.31.0" resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz" integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A== @@ -2113,7 +1769,7 @@ eslint-visitor-keys@^4.2.1: resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz" integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== -eslint@^9: +eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.23.0 || ^8.0.0 || ^9.0.0", "eslint@^8.57.0 || ^9.0.0", eslint@^9: version "9.29.0" resolved "https://registry.npmjs.org/eslint/-/eslint-9.29.0.tgz" integrity sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ== @@ -2202,17 +1858,6 @@ fast-equals@^5.0.1: resolved "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz" integrity sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw== -fast-glob@3.3.1: - version "3.3.1" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" - integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - fast-glob@^3.3.2: version "3.3.3" resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz" @@ -2224,6 +1869,17 @@ fast-glob@^3.3.2: merge2 "^1.3.0" micromatch "^4.0.8" +fast-glob@3.3.1: + version "3.3.1" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" @@ -2327,7 +1983,7 @@ functions-have-names@^1.2.3: 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" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7, get-intrinsic@^1.3.0: @@ -2414,7 +2070,7 @@ graphemer@^1.4.0: graphql@^16.8.1: version "16.11.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.11.0.tgz#96d17f66370678027fdf59b2d4c20b4efaa8a633" + resolved "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz" integrity sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw== has-bigints@^1.0.2: @@ -2462,7 +2118,7 @@ hasown@^2.0.2: headers-polyfill@^4.0.2: version "4.0.3" - resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-4.0.3.tgz#922a0155de30ecc1f785bcf04be77844ca95ad07" + resolved "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz" integrity sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ== hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1: @@ -2484,12 +2140,12 @@ ignore@^7.0.0: immer@^10.0.3: version "10.1.1" - resolved "https://registry.yarnpkg.com/immer/-/immer-10.1.1.tgz#206f344ea372d8ea176891545ee53ccc062db7bc" + resolved "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz" integrity sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw== immutable@^5.0.2: version "5.1.3" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-5.1.3.tgz#e6486694c8b76c37c063cca92399fa64098634d4" + resolved "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz" integrity sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg== import-fresh@^3.2.1: @@ -2614,7 +2270,7 @@ is-finalizationregistry@^1.1.0: is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-generator-function@^1.0.10: @@ -2646,7 +2302,7 @@ is-negative-zero@^2.0.3: 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" + resolved "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz" integrity sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw== is-number-object@^1.1.1: @@ -2750,6 +2406,11 @@ iterator.prototype@^1.1.4: has-symbols "^1.1.0" set-function-name "^2.0.2" +jose@^6.0.12: + version "6.0.12" + resolved "https://registry.npmjs.org/jose/-/jose-6.0.12.tgz" + integrity sha512-T8xypXs8CpmiIi78k0E+Lk7T2zlK4zDyg+o1CZ4AkOHgDg98ogdP2BeZ61lTFKFyoEwJ9RgAgN+SdM3iPgNonQ== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" @@ -2903,9 +2564,9 @@ ms@^2.1.1, ms@^2.1.3: integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== msw@^2.10.2: - version "2.10.2" - resolved "https://registry.yarnpkg.com/msw/-/msw-2.10.2.tgz#e7a56ed0b6865b00a30b4c4a5b59e5388fd48315" - integrity sha512-RCKM6IZseZQCWcSWlutdf590M8nVfRHG1ImwzOtwz8IYxgT4zhUO0rfTcTvDGiaFE0Rhcc+h43lcF3Jc9gFtwQ== + version "2.10.4" + resolved "https://registry.npmjs.org/msw/-/msw-2.10.4.tgz" + integrity sha512-6R1or/qyele7q3RyPwNuvc0IxO8L8/Aim6Sz5ncXEgcWUNxSKE+udriTOWHtpMwmfkLYlacA2y7TIx4cL5lgHA== dependencies: "@bundled-es-modules/cookie" "^2.0.1" "@bundled-es-modules/statuses" "^1.0.1" @@ -2928,7 +2589,7 @@ msw@^2.10.2: mute-stream@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-2.0.0.tgz#a5446fc0c512b71c83c44d908d5c7b7b4c493b2b" + resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz" integrity sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA== nanoid@^3.3.6: @@ -2971,7 +2632,7 @@ next@15.3.3: node-addon-api@^7.0.0: version "7.1.1" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz" integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== object-assign@^4.1.1: @@ -3054,7 +2715,7 @@ optionator@^0.9.3: outvariant@^1.4.0, outvariant@^1.4.3: version "1.4.3" - resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.3.tgz#221c1bfc093e8fec7075497e7799fdbf43d14873" + resolved "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz" integrity sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA== own-keys@^1.0.1: @@ -3114,7 +2775,7 @@ path-parse@^1.0.7: 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" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz" integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== path-type@^4.0.0: @@ -3132,7 +2793,7 @@ picomatch@^2.3.1: resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -picomatch@^4.0.2: +"picomatch@^3 || ^4", picomatch@^4.0.2: version "4.0.2" resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz" integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== @@ -3167,7 +2828,7 @@ prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: psl@^1.1.33: version "1.15.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" + resolved "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz" integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== dependencies: punycode "^2.3.1" @@ -3179,7 +2840,7 @@ punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: querystringify@^2.1.1: version "2.2.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + resolved "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz" integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== queue-microtask@^1.2.2: @@ -3197,7 +2858,7 @@ react-date-range@^2.0.1: react-list "^0.8.13" shallow-equal "^1.2.1" -react-dom@^19.0.0: +"react-dom@^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react-dom@^19.0.0, react-dom@>=16.6.0: version "19.1.0" resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz" integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g== @@ -3224,9 +2885,9 @@ react-list@^0.8.13: resolved "https://registry.npmjs.org/react-list/-/react-list-0.8.18.tgz" integrity sha512-1OSdDvzuKuwDJvQNuhXxxL+jTmmdtKg1i6KtYgxI9XR98kbOql1FcSGP+Lcvo91fk3cYng+Z6YkC6X9HRJwxfw== -react-redux@^9.2.0: +"react-redux@^7.2.1 || ^8.1.3 || ^9.0.0", react-redux@^9.2.0: version "9.2.0" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.2.0.tgz#96c3ab23fb9a3af2cb4654be4b51c989e32366f5" + resolved "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz" integrity sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g== dependencies: "@types/use-sync-external-store" "^0.0.6" @@ -3251,14 +2912,14 @@ react-transition-group@^4.4.5: loose-envify "^1.4.0" prop-types "^15.6.2" -react@^19.0.0: +"react@^0.14 || ^15.0.0-rc || >=15.0", "react@^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.9.0 || ^17.0.0 || ^18 || ^19", "react@^17.0.0 || ^18.0.0 || ^19.0.0", "react@^18.0 || ^19", "react@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react@^19.0.0, react@^19.1.0, "react@>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0", react@>=16.6.0, react@>=16.8.0, "react@0.14 || 15 - 19": version "19.1.0" resolved "https://registry.npmjs.org/react/-/react-19.1.0.tgz" integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg== readdirp@^4.0.1: version "4.1.2" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz" integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== recharts-scale@^0.4.4: @@ -3284,19 +2945,19 @@ recharts@^2.15.3: redux-thunk@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-3.1.0.tgz#94aa6e04977c30e14e892eae84978c1af6058ff3" + resolved "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz" integrity sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw== redux@^4.0.0: version "4.2.1" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" + resolved "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz" integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== dependencies: "@babel/runtime" "^7.9.2" -redux@^5.0.1: +redux@^5.0.0, redux@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/redux/-/redux-5.0.1.tgz#97fa26881ce5746500125585d5642c77b6e9447b" + resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz" integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w== reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: @@ -3327,12 +2988,12 @@ regexp.prototype.flags@^1.5.3, regexp.prototype.flags@^1.5.4: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" 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" + resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== reselect@^5.1.0, reselect@^5.1.1: @@ -3408,10 +3069,10 @@ safe-regex-test@^1.0.3, safe-regex-test@^1.1.0: es-errors "^1.3.0" is-regex "^1.2.1" -sass@^1.89.2: - version "1.89.2" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.89.2.tgz#a771716aeae774e2b529f72c0ff2dfd46c9de10e" - integrity sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA== +sass@^1.3.0, sass@^1.89.2: + version "1.90.0" + resolved "https://registry.npmjs.org/sass/-/sass-1.90.0.tgz" + integrity sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q== dependencies: chokidar "^4.0.0" immutable "^5.0.2" @@ -3555,7 +3216,7 @@ side-channel@^1.1.0: signal-exit@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== simple-swizzle@^0.2.2: @@ -3565,7 +3226,7 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" -"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: +source-map-js@^1.0.2, "source-map-js@>=0.6.2 <2.0.0": version "1.2.1" resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== @@ -3589,7 +3250,7 @@ stable-hash@^0.0.5: statuses@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.2.tgz#8f75eecef765b5e1cfcdc080da59409ed424e382" + resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz" integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw== stop-iteration-iterator@^1.1.0: @@ -3607,12 +3268,12 @@ streamsearch@^1.1.0: 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" + resolved "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz" integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" @@ -3689,7 +3350,7 @@ string.prototype.trimstart@^1.0.8: strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" @@ -3750,7 +3411,7 @@ to-regex-range@^5.0.1: tough-cookie@^4.1.4: version "4.1.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz" integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== dependencies: psl "^1.1.33" @@ -3787,12 +3448,12 @@ type-check@^0.4.0, type-check@~0.4.0: type-fest@^0.21.3: version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== type-fest@^4.26.1: version "4.41.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz" integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== typed-array-buffer@^1.0.3: @@ -3840,7 +3501,7 @@ typed-array-length@^1.0.7: possible-typed-array-names "^1.0.0" reflect.getprototypeof "^1.0.6" -typescript@^5: +typescript@^5, "typescript@>= 4.8.x", typescript@>=3.3.1, typescript@>=4.8.4, "typescript@>=4.8.4 <5.9.0": version "5.8.3" resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz" integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== @@ -3862,7 +3523,7 @@ undici-types@~6.21.0: universalify@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz" integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== unrs-resolver@^1.6.2: @@ -3901,7 +3562,7 @@ uri-js@^4.2.2: url-parse@^1.5.3: version "1.5.10" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz" integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== dependencies: querystringify "^2.1.1" @@ -4009,7 +3670,7 @@ word@~0.3.0: wrap-ansi@^6.2.0: version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== dependencies: ansi-styles "^4.0.0" @@ -4018,7 +3679,7 @@ wrap-ansi@^6.2.0: wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -4040,7 +3701,7 @@ xlsx@^0.18.5: y18n@^5.0.5: version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yaml@^1.10.0: @@ -4050,12 +3711,12 @@ yaml@^1.10.0: yargs-parser@^21.1.1: version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" 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" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" @@ -4073,5 +3734,5 @@ yocto-queue@^0.1.0: yoctocolors-cjs@^2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz#f4b905a840a37506813a7acaa28febe97767a242" + resolved "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz" integrity sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==