Compare commits

...

7 Commits

Author SHA1 Message Date
4ef94b4fbb Merge branch 'main' into feat/digital-innovation 2025-08-26 20:55:47 +03:30
b5c734ebce fix the popup in graph 2025-08-26 18:23:48 +03:30
mahmoodsht
32aaac72f2 جزییات 2025-08-26 16:24:50 +03:30
mahmoodsht
fa90d286af جزییات 2025-08-26 14:23:26 +03:30
mahmoodsht
d31ef7161b جزییات 2025-08-26 14:01:39 +03:30
mahmoodsht
a0769dd1b9 Update dashboard-home.tsx 2025-08-26 13:00:47 +03:30
fd9a178df7 refactor the call api function,also update the componenet in main page (#3)
Reviewed-on: https://git.pelekan.org/Saeed0920/inogen/pulls/3
Co-authored-by: Saeed Abadiyan <sd.eed1381@gmail.com>
Co-committed-by: Saeed Abadiyan <sd.eed1381@gmail.com>
2025-08-26 12:06:52 +03:30
13 changed files with 1272 additions and 180 deletions

View File

@ -109,7 +109,7 @@ This document describes the exact implementation of the login page based on the
داشبورد مدیریت فناوری و نوآوری داشبورد مدیریت فناوری و نوآوری
</h2> </h2>
<p className="text-gray-300 text-sm font-persian leading-relaxed"> <p className="text-gray-300 text-sm font-persian leading-relaxed">
لطفاً نام کاربری و پسورد خود را وارد فهرست خواسته شده وارد لطفاً نام کاربری و کلمه عبور خود را وارد فهرست خواسته شده وارد
<br /> <br />
فرمایید. فرمایید.
</p> </p>

View File

@ -1,44 +1,557 @@
import React from "react"; import React, { useState, useEffect } from "react";
import { DashboardLayout } from "./layout"; import { DashboardLayout } from "./layout";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import { Progress } from "~/components/ui/progress";
import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button";
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, LineChart, Line } from 'recharts';
import apiService from "~/lib/api";
import toast from "react-hot-toast";
import { Calendar, TrendingUp, TrendingDown, Target, Lightbulb, DollarSign, Minus, CheckCircle, BookOpen } from "lucide-react";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "~/components/ui/tabs";
import { CustomBarChart } from "~/components/ui/custom-bar-chart";
import {
Label,
PolarGrid,
PolarRadiusAxis,
RadialBar,
RadialBarChart,
} from "recharts"
import { ChartContainer } from "~/components/ui/chart"
import { formatNumber } from "~/lib/utils";
export function DashboardHome() { export function DashboardHome() {
const [dashboardData, setDashboardData] = useState<any | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
fetchDashboardData();
}, []);
const fetchDashboardData = async () => {
try {
setLoading(true);
setError(null);
// First authenticate if needed
const token = localStorage.getItem('auth_token');
if (!token) {
await apiService.login('inogen_admin', '123456');
}
// Fetch top cards data
const topCardsResponse = await apiService.call({
main_page_first_function: {}
});
// Fetch left section data
const leftCardsResponse = await apiService.call({
main_page_second_function: {}
});
const topCardsResponseData = JSON.parse(topCardsResponse?.data);
const leftCardsResponseData = JSON.parse(leftCardsResponse?.data);
console.log('API Responses:', { topCardsResponseData, leftCardsResponseData });
// Use real API data structure with English keys
const topData = topCardsResponseData || {};
const leftData = leftCardsResponseData || {};
const realData = {
topData: topData,
leftData: leftData,
chartData: leftCardsResponseData?.chartData || []
};
setDashboardData(realData);
} catch (error) {
console.error('Error fetching dashboard data:', error);
const errorMessage = error instanceof Error ? error.message : 'خطای نامشخص';
setError(`خطا در بارگذاری داده‌ها: ${errorMessage}`);
toast.error(`خطا در بارگذاری داده‌ها: ${errorMessage}`);
} finally {
setLoading(false);
}
};
// RadialBarChart data for ideas visualization
const getIdeasChartData = () => {
if (!dashboardData?.topData) return [{ browser: "safari", visitors: 0, fill: "var(--color-safari)" }];
const registered = parseFloat(dashboardData.topData.registered_innovation_technology_idea || '0');
const ongoing = parseFloat(dashboardData.topData.ongoing_innovation_technology_ideas || '0');
const percentage = registered > 0 ? Math.round((ongoing / registered) * 100) : 0;
return [{ browser: "safari", visitors: percentage, fill: "var(--color-safari)" }];
};
const chartData = getIdeasChartData();
const chartConfig = {
visitors: {
label: "Ideas Progress",
},
safari: {
label: "Safari",
color: "var(--chart-2)",
},
};
if (loading) {
return (
<DashboardLayout>
<div className="p-6">
<div className="flex items-center justify-center h-64">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
</div>
</div>
</DashboardLayout>
);
}
if (error || !dashboardData) {
return (
<DashboardLayout>
<div className="p-6">
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-red-500/50">
<CardContent className="p-6">
<div className="flex flex-col items-center justify-center space-y-4">
<div className="p-4 bg-red-500/20 rounded-full">
<CheckCircle className="w-12 h-12 text-red-400" />
</div>
<h3 className="text-xl font-bold text-red-400 text-center">
خطا در بارگذاری دادهها
</h3>
<p className="text-gray-300 text-center max-w-md">
{error || 'خطای نامشخص در بارگذاری داده‌های داشبورد رخ داده است'}
</p>
<Button
onClick={fetchDashboardData}
variant="outline"
className="border-red-500/50 text-red-400 hover:bg-red-500/10"
>
تلاش مجدد
</Button>
</div>
</CardContent>
</Card>
</div>
</DashboardLayout>
);
}
return ( return (
<DashboardLayout> <DashboardLayout>
<div className="p-6"> <div className="p-3 pb-0 grid grid-cols-3 gap-4">
{/* Main Content Area - Empty for now */} {/* Top Cards Row - Redesigned to match other components */}
<div className="space-y-6"> <div className="flex justify-between gap-6 [&>*]:w-full col-span-3">
<Card> {/* Ideas Card */}
<CardHeader></CardHeader> <Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardContent> <CardContent className="p-4">
<div className="flex items-center justify-center h-64 text-gray-500 dark:text-gray-400"> <div className="flex flex-col justify-between gap-2">
<div className="text-center"> <div className="flex justify-between items-center border-b-2 mx-4 border-gray-500/20">
<div className="w-16 h-16 mx-auto mb-4 bg-gray-100 dark:bg-gray-800 rounded-full flex items-center justify-center"> <h3 className="text-lg font-bold text-white font-persian py-2">
<svg ایدههای فناوری و نوآوری
className="w-8 h-8" </h3>
fill="none" </div>
stroke="currentColor" <div className="flex items-center gap-2 justify-center flex-row-reverse p-1">
viewBox="0 0 24 24" <ChartContainer config={chartConfig} className="w-full h-full max-h-20 max-w-40">
> <RadialBarChart data={chartData} startAngle={0} endAngle={250} innerRadius={30} outerRadius={50}>
<path <PolarGrid
strokeLinecap="round" gridType="circle"
strokeLinejoin="round" radialLines={false}
strokeWidth={2} stroke="none"
d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" className="first:fill-muted last:fill-background"
/> polarRadius={[36, 24]}
</svg> />
<RadialBar dataKey="visitors" background cornerRadius={5} />
<PolarRadiusAxis tick={false} tickLine={false} axisLine={false}>
<Label
content={({ viewBox }) => {
if (viewBox && "cx" in viewBox && "cy" in viewBox) {
return (
<text x={viewBox.cx} y={viewBox.cy} textAnchor="middle" dominantBaseline="middle">
<tspan x={viewBox.cx} y={viewBox.cy} className="fill-foreground text-lg font-bold">
{formatNumber(dashboardData.topData?.ongoing_innovation_technology_ideas || '0')}%
</tspan>
</text>
)
}
}}
/>
</PolarRadiusAxis>
</RadialBarChart>
</ChartContainer>
<div className="font-bold font-persian text-center mt-2">
<div className="flex flex-col justify-between items-center">
<span className="flex font-bold items-center gap-1">
<div className="font-light">ثبت شده :</div>
{formatNumber(dashboardData.topData?.registered_innovation_technology_idea || '0')}
</span>
<span className="flex items-center gap-1 font-bold">
<div className="font-light">در حال اجرا :</div>
{formatNumber(dashboardData.topData?.ongoing_innovation_technology_ideas || '0')}
</span>
</div>
</div>
</div>
</div>
</CardContent>
</Card>
{/* Revenue Card */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardContent className="p-4">
<div className="flex flex-col justify-between gap-2">
<div className="flex justify-between items-center border-b-2 mx-4 border-gray-500/20">
<h3 className="text-lg font-bold text-white font-persian">
افزایش درآمد مبتنی بر فناوری و نوآوری
</h3>
</div>
<div className="flex items-center justify-center flex-col p-1">
<div className="flex items-center gap-4">
<div className="text-center">
<p className="text-2xl font-bold text-green-400">
%{formatNumber(dashboardData.topData?.technology_innovation_based_revenue_growth_percent || '0')}
</p>
<div className="text-xs text-gray-400 font-persian">
درصد به کل درآمد
</div>
</div>
<div className="text-center">
<p className="text-2xl font-bold text-green-400">
{formatNumber(dashboardData.topData?.technology_innovation_based_revenue_growth || '0')}
</p>
<div className="text-xs text-gray-400 font-persian">
میلیون ریال
</div>
</div>
</div>
</div>
</div>
</CardContent>
</Card>
{/* Cost Reduction Card */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardContent className="p-4">
<div className="flex flex-col justify-between gap-2">
<div className="flex justify-between items-center border-b-2 mx-4 border-gray-500/20">
<h3 className="text-lg font-bold text-white font-persian">
کاهش هزینه ها مبتنی بر فناوری و نوآوری
</h3>
</div>
<div className="flex items-center justify-center flex-col p-1">
<div className="flex items-center gap-4">
<div className="text-center">
<p className="text-2xl font-bold text-orange-400">
%{formatNumber(dashboardData.topData?.technology_innovation_based_cost_reduction_percent || '0')}
</p>
<div className="text-xs text-gray-400 font-persian">
درصد به کل هزینه
</div>
</div>
<div className="text-center">
<p className="text-2xl font-bold text-orange-400">
{formatNumber(Math.round((parseFloat(dashboardData.topData?.technology_innovation_based_cost_reduction?.replace(/,/g, '') || '0')) / 1000000))}
</p>
<div className="text-xs text-gray-400 font-persian">
میلیون ریال
</div>
</div>
</div>
</div>
</div>
</CardContent>
</Card>
{/* Budget Ratio Card */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardContent className="p-4">
<div className="flex flex-col justify-between gap-2">
<div className="flex justify-between items-center border-b-2 mx-4 border-gray-500/20">
<h3 className="text-lg font-bold text-white font-persian">
نسبت تحقق بودجه فناوی و نوآوری
</h3>
</div>
<div className="flex items-center gap-2 justify-center flex-row-reverse p-1">
<ChartContainer config={chartConfig} className="w-full h-full max-h-20 max-w-40">
<RadialBarChart data={[{
browser: "budget",
visitors: parseFloat(dashboardData.topData?.innovation_budget_achievement_percent || '0'),
fill: "var(--chart-3)"
}]} startAngle={0} endAngle={250} innerRadius={30} outerRadius={50}>
<PolarGrid
gridType="circle"
radialLines={false}
stroke="none"
className="first:fill-muted last:fill-background"
polarRadius={[36, 24]}
/>
<RadialBar dataKey="visitors" background cornerRadius={5} />
<PolarRadiusAxis tick={false} tickLine={false} axisLine={false}>
<Label
content={({ viewBox }) => {
if (viewBox && "cx" in viewBox && "cy" in viewBox) {
return (
<text x={viewBox.cx} y={viewBox.cy} textAnchor="middle" dominantBaseline="middle">
<tspan x={viewBox.cx} y={viewBox.cy} className="fill-foreground text-lg font-bold">
%{formatNumber(dashboardData.topData?.innovation_budget_achievement_percent || '0')}
</tspan>
</text>
)
}
}}
/>
</PolarRadiusAxis>
</RadialBarChart>
</ChartContainer>
<div className="font-bold font-persian text-center mt-2">
<div className="flex flex-col justify-between items-center">
<span className="flex font-bold items-center gap-1">
<div className="font-light">مصوب :</div>
{formatNumber(Math.round((parseFloat(dashboardData.topData?.approved_innovation_budget_achievement_ratio?.replace(/,/g, '') || '0')) / 1000000000))}
</span>
<span className="flex items-center gap-1 font-bold">
<div className="font-light">جذب شده :</div>
{formatNumber(Math.round((parseFloat(dashboardData.topData?.allocated_innovation_budget_achievement_ratio?.replace(/,/g, '') || '0')) / 1000000000))}
</span>
</div>
</div> </div>
<p className="text-lg font-medium font-persian mb-2">
صفحه در دست ساخت
</p>
<p className="text-sm font-persian">
محتوای این بخش به زودی اضافه خواهد شد
</p>
</div> </div>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
</div> </div>
{/* Main Content with Tabs */}
<Tabs defaultValue="charts" className=" col-span-2 row-start-2 bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)]">
<TabsList className="bg-transparent">
<TabsTrigger value="charts" className=" text-white data-[state=active]:bg-blue-500/20 data-[state=active]:text-blue-400">
مقایسه ای
</TabsTrigger>
<TabsTrigger value="canvas" disabled className="text-gray-500 cursor-not-allowed">
شماتیک
</TabsTrigger>
</TabsList>
<TabsContent value="charts" className="">
<div className=" gap-6">
{/* Right Section - Charts */}
<div className="">
{/* Main Chart */}
<Card className="bg-transparent px-2 border-none">
<CardHeader>
<CardTitle className="text-white text-xl">تحلیل ارزشها</CardTitle>
<p className="text-gray-400 text-sm">نمودار مقایسهای عملکرد ماهانه</p>
</CardHeader>
<CardContent className="border-none">
<div className="h-60 ">
<ResponsiveContainer width="100%" height="100%">
<LineChart data={[
{ month: 'فروردین', ideas: 12, revenue: 850, cost: 320 },
{ month: 'اردیبهشت', ideas: 19, revenue: 1200, cost: 450 },
{ month: 'خرداد', ideas: 8, revenue: 980, cost: 280 },
{ month: 'تیر', ideas: 15, revenue: 1400, cost: 520 },
{ month: 'مرداد', ideas: 22, revenue: 1650, cost: 680 },
{ month: 'شهریور', ideas: 18, revenue: 1320, cost: 590 }
]}>
<CartesianGrid strokeDasharray="3 3" stroke="#374151" />
<XAxis
dataKey="month"
stroke="#9CA3AF"
fontSize={11}
/>
<YAxis stroke="#9CA3AF" fontSize={11} />
<Tooltip
contentStyle={{
backgroundColor: '#1F2937',
border: '1px solid #374151',
borderRadius: '8px',
color: '#F9FAFB'
}}
/>
<Line
type="monotone"
dataKey="ideas"
stroke="#3B82F6"
strokeWidth={3}
name="ایده‌ها"
dot={{ fill: '#3B82F6', strokeWidth: 2, r: 4 }}
/>
<Line
type="monotone"
dataKey="revenue"
stroke="#10B981"
strokeWidth={3}
name="درآمد (میلیون)"
dot={{ fill: '#10B981', strokeWidth: 2, r: 4 }}
/>
<Line
type="monotone"
dataKey="cost"
stroke="#F59E0B"
strokeWidth={3}
name="کاهش هزینه (میلیون)"
dot={{ fill: '#F59E0B', strokeWidth: 2, r: 4 }}
/>
</LineChart>
</ResponsiveContainer>
</div>
</CardContent>
</Card>
</div>
</div>
</TabsContent>
</Tabs>
{/* Left Section - Status Cards */}
<div className="space-y-4 row-start-2 col-spend-1 ">
{/* Technology Intensity */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardContent className="p-4">
<div className="flex items-center gap-3">
<CardTitle className="text-white text-base min-w-[120px]">شدت فناوری</CardTitle>
<Progress value={parseFloat(dashboardData.leftData?.technology_intensity || '0')} className="h-2 flex-1" />
<p className="text-sm text-gray-400 min-w-[60px] text-left">%{formatNumber(dashboardData.leftData?.technology_intensity || '0')}</p>
</div>
</CardContent>
</Card>
{/* Program Status */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardContent className="p-4">
<CustomBarChart
title="وضعیت برنامه‌های فناوری و نوآوری"
loading={loading}
data={[
{
label: "اجرا شده",
value: parseFloat(dashboardData?.leftData?.executed_project || '0'),
color: "bg-green-400",
labelColor: "text-white",
},
{
label: "در حال اجرا",
value: parseFloat(dashboardData?.leftData?.in_progress_project || '0'),
color: "bg-blue-400",
labelColor: "text-white",
},
{
label: "برنامه‌ریزی شده",
value: parseFloat(dashboardData?.leftData?.planned_project || '0'),
color: "bg-red-400",
labelColor: "text-white",
},
]}
barHeight="h-5"
showAxisLabels={false}
/>
</CardContent>
</Card>
{/* Publications */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardHeader className="pb-3">
<CardTitle className="text-white text-lg">انتشارات فناوری و نوآوری</CardTitle>
</CardHeader>
<CardContent className="p-4">
<div className="grid grid-cols-2 grid-rows-2 gap-3">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-blue-400" />
<span className="text-gray-300 text-sm">کتاب:</span>
</div>
<span className="text-lg font-bold text-blue-400">
{formatNumber(dashboardData.leftData?.printed_books_count || '0')}
</span>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-purple-400" />
<span className="text-gray-300 text-sm">پتنت:</span>
</div>
<span className="text-lg font-bold text-purple-400">
{formatNumber(dashboardData.leftData?.registered_patents_count || '0')}
</span>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-yellow-400" />
<span className="text-gray-300 text-sm">گزارش:</span>
</div>
<span className="text-lg font-bold text-yellow-400">
{formatNumber(dashboardData.leftData?.published_reports_count || '0')}
</span>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-green-400" />
<span className="text-gray-300 text-sm">مقاله:</span>
</div>
<span className="text-lg font-bold text-green-400">
{formatNumber(dashboardData.leftData?.printed_articles_count || '0')}
</span>
</div>
</div>
</CardContent>
</Card>
{/* Promotion */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardHeader className="pb-3">
<CardTitle className="text-white text-lg">ترویج فناوری و نوآوری</CardTitle>
</CardHeader>
<CardContent className="p-4">
<div className="space-y-3">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-purple-400" />
<span className="text-gray-300 text-sm">کنفرانس:</span>
</div>
<span className="text-lg font-bold text-purple-400">
{formatNumber(dashboardData.leftData?.attended_conferences_count || '0')}
</span>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-blue-400" />
<span className="text-gray-300 text-sm">شرکت در رویداد:</span>
</div>
<span className="text-lg font-bold text-blue-400">
{formatNumber(dashboardData.leftData?.attended_events_count || '0')}
</span>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-yellow-400" />
<span className="text-gray-300 text-sm">نمایشگاه:</span>
</div>
<span className="text-lg font-bold text-yellow-400">
{formatNumber(dashboardData.leftData?.attended_exhibitions_count || '0')}
</span>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-green-400" />
<span className="text-gray-300 text-sm">برگزاری رویداد:</span>
</div>
<span className="text-lg font-bold text-green-400">
{formatNumber(dashboardData.leftData?.organized_events_count || '0')}
</span>
</div>
</div>
</CardContent>
</Card>
</div>
</div> </div>
</DashboardLayout> </DashboardLayout>
); );

View File

@ -26,7 +26,7 @@ interface HeaderProps {
export function Header({ export function Header({
onToggleSidebar, onToggleSidebar,
className, className,
title = "داشبورد", title = "صفحه اول",
}: HeaderProps) { }: HeaderProps) {
const { user } = useAuth(); const { user } = useAuth();
const [isProfileMenuOpen, setIsProfileMenuOpen] = useState(false); const [isProfileMenuOpen, setIsProfileMenuOpen] = useState(false);

View File

@ -169,7 +169,7 @@ export function ProcessInnovationPage() {
stats.productionStopsPreventionSum.toFixed?.(1) ?? stats.productionStopsPreventionSum.toFixed?.(1) ??
stats.productionStopsPreventionSum, stats.productionStopsPreventionSum,
), ),
description: "ظرفیت افزایش یافته", description: "تن افزایش یافته",
icon: <CirclePause />, icon: <CirclePause />,
color: "text-emerald-400", color: "text-emerald-400",
}, },
@ -194,7 +194,7 @@ export function ProcessInnovationPage() {
}, },
{ {
id: "frequent-failures-reduction", id: "frequent-failures-reduction",
title: "کاهش خرابیهای پرتکرار", title: "کاهش خرابی های پرتکرار",
value: formatNumber( value: formatNumber(
stats.frequentFailuresReductionSum.toFixed?.(1) ?? stats.frequentFailuresReductionSum.toFixed?.(1) ??
stats.frequentFailuresReductionSum, stats.frequentFailuresReductionSum,
@ -392,7 +392,7 @@ export function ProcessInnovationPage() {
const fetchStats = async () => { const fetchStats = async () => {
try { try {
setStatsLoading(true); setStatsLoading(true);
const raw = await apiService.callInnovationProcess<any>({ const raw = await apiService.call<any>({
innovation_process_function: {}, innovation_process_function: {},
}); });

View File

@ -368,7 +368,7 @@ export function Sidebar({
/> />
<div className="font-persian"> <div className="font-persian">
<div className="text-sm font-semibold text-white"> <div className="text-sm font-semibold text-white">
سیستم اینوژن داشبورد اینوژن
</div> </div>
<div className="text-xs text-gray-400">نسخه ۰.۱</div> <div className="text-xs text-gray-400">نسخه ۰.۱</div>
</div> </div>

View File

@ -68,15 +68,17 @@ export function InfoPanel({ selectedCompany }: InfoPanelProps) {
setIsLoading(true); setIsLoading(true);
try { try {
const [countsRes, processRes] = await Promise.all([ const [countsRes, processRes] = await Promise.all([
apiService.callInnovationProcess<EcosystemCounts>({ apiService.call<EcosystemCounts>({
ecosystem_counts_function: {}, ecosystem_count_function: {},
}), }),
apiService.callInnovationProcess<ProcessActorsResponse[]>({ apiService.call<ProcessActorsResponse[]>({
process_creating_actors_function: {}, process_creating_actors_function: {},
}), }),
]); ]);
setCounts(JSON.parse(countsRes.data)); setCounts(
JSON.parse(JSON.parse(countsRes.data).ecosystem_count_function)[0],
);
// Process the years data and fill missing years // Process the years data and fill missing years
const processedData = processYearsData( const processedData = processYearsData(
@ -164,7 +166,7 @@ export function InfoPanel({ selectedCompany }: InfoPanelProps) {
}, },
{ label: "شتابدهنده", value: parseNumber(counts.accelerator_count) }, { label: "شتابدهنده", value: parseNumber(counts.accelerator_count) },
{ label: "دانشگاه", value: parseNumber(counts.university_count) }, { label: "دانشگاه", value: parseNumber(counts.university_count) },
{ label: "صندوق", value: parseNumber(counts.fund_count) }, { label: "صندوق های مالی", value: parseNumber(counts.fund_count) },
{ label: "شرکت", value: parseNumber(counts.company_count) }, { label: "شرکت", value: parseNumber(counts.company_count) },
] ]
: []; : [];
@ -404,6 +406,23 @@ export function InfoPanel({ selectedCompany }: InfoPanelProps) {
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
{/* Footer - MOU Count */}
{/* <CardContent className="py-3">
<div className="flex font-bold text-xl px-6 justify-between text-gray-300 font-persian mb-1">
تعداد تفاهم نامه ها
<span className="text-2xl">{formatNumber(counts.mou_count)}</span>
</div>
</CardContent> */}
<CardHeader className="text-center pb-2 border-b-2 border-[#3F415A]">
<CardTitle className="font-persian text-xl text-white flex justify-between px-4">
تعداد تفاهم نامه ها
<span className="font-bold text-3xl">
{formatNumber(counts.mou_count)}
</span>
</CardTitle>
</CardHeader>
<CardHeader className="text-center pb-2 border-b-2 border-[#3F415A]"> <CardHeader className="text-center pb-2 border-b-2 border-[#3F415A]">
<CardTitle className="font-persian text-xl text-white flex justify-between px-4"> <CardTitle className="font-persian text-xl text-white flex justify-between px-4">
تعداد بازیگران تعداد بازیگران
@ -495,13 +514,6 @@ export function InfoPanel({ selectedCompany }: InfoPanelProps) {
</div> </div>
</CardContent> </CardContent>
{/* Footer - MOU Count */}
<CardContent className="py-3">
<div className="flex font-bold text-xl px-6 justify-between text-gray-300 font-persian mb-1">
تعداد تفاهم نامه ها
<span className="text-2xl">{formatNumber(counts.mou_count)}</span>
</div>
</CardContent>
</Card> </Card>
</div> </div>
); );

View File

@ -88,7 +88,7 @@ export function NetworkGraph({ onNodeClick }: NetworkGraphProps) {
(async () => { (async () => {
setIsLoading(true); setIsLoading(true);
try { try {
const res = await apiService.callInnovationProcess<any[]>({ const res = await apiService.call<any[]>({
graph_production_function: {}, graph_production_function: {},
}); });
if (aborted) return; if (aborted) return;
@ -102,7 +102,7 @@ export function NetworkGraph({ onNodeClick }: NetworkGraphProps) {
// Create center node // Create center node
const centerNode: Node = { const centerNode: Node = {
id: "center", id: "center",
label: "مرکز اکوسیستم", label: "", //مرکز زیست بوم
category: "center", category: "center",
stageid: 0, stageid: 0,
isCenter: true, isCenter: true,
@ -155,7 +155,7 @@ export function NetworkGraph({ onNodeClick }: NetworkGraphProps) {
// Import apiService for the onClick handler // Import apiService for the onClick handler
const callAPI = useCallback(async (stage_id: number) => { const callAPI = useCallback(async (stage_id: number) => {
return await apiService.callInnovationProcess<any>({ return await apiService.call<any>({
get_values_workflow_function: { get_values_workflow_function: {
stage_id: stage_id, stage_id: stage_id,
}, },
@ -317,7 +317,8 @@ export function NetworkGraph({ onNodeClick }: NetworkGraphProps) {
.attr("ry", 8) .attr("ry", 8)
.attr("fill", categoryToColor[d.category] || "#94A3B8") .attr("fill", categoryToColor[d.category] || "#94A3B8")
.attr("stroke", "#FFFFFF") .attr("stroke", "#FFFFFF")
.attr("stroke-width", 3); .attr("stroke-width", 3)
.style("pointer-events", "none");
// Add center image if available // Add center image if available
if (d.imageUrl || d.isCenter) { if (d.imageUrl || d.isCenter) {
@ -399,6 +400,7 @@ export function NetworkGraph({ onNodeClick }: NetworkGraphProps) {
// Add hover effects // Add hover effects
nodeGroup nodeGroup
.on("mouseenter", function (event, d) { .on("mouseenter", function (event, d) {
if (d.isCenter) return;
d3.select(this) d3.select(this)
.select(d.isCenter ? "rect" : "circle") .select(d.isCenter ? "rect" : "circle")
.attr("filter", "url(#glow)") .attr("filter", "url(#glow)")
@ -419,7 +421,6 @@ export function NetworkGraph({ onNodeClick }: NetworkGraphProps) {
// Add click handlers // Add click handlers
nodeGroup.on("click", async function (event, d) { nodeGroup.on("click", async function (event, d) {
setIsLoading(true);
event.stopPropagation(); event.stopPropagation();
// Don't handle center node clicks // Don't handle center node clicks
@ -471,7 +472,6 @@ export function NetworkGraph({ onNodeClick }: NetworkGraphProps) {
onNodeClick(basicDetails); onNodeClick(basicDetails);
} }
} }
setIsLoading(false);
}); });
// Update positions on simulation tick // Update positions on simulation tick

351
app/components/ui/chart.tsx Normal file
View File

@ -0,0 +1,351 @@
import * as React from "react"
import * as RechartsPrimitive from "recharts"
import { cn } from "~/lib/utils"
// Format: { THEME_NAME: CSS_SELECTOR }
const THEMES = { light: "", dark: ".dark" } as const
export type ChartConfig = {
[k in string]: {
label?: React.ReactNode
icon?: React.ComponentType
} & (
| { color?: string; theme?: never }
| { color?: never; theme: Record<keyof typeof THEMES, string> }
)
}
type ChartContextProps = {
config: ChartConfig
}
const ChartContext = React.createContext<ChartContextProps | null>(null)
function useChart() {
const context = React.useContext(ChartContext)
if (!context) {
throw new Error("useChart must be used within a <ChartContainer />")
}
return context
}
function ChartContainer({
id,
className,
children,
config,
...props
}: React.ComponentProps<"div"> & {
config: ChartConfig
children: React.ComponentProps<
typeof RechartsPrimitive.ResponsiveContainer
>["children"]
}) {
const uniqueId = React.useId()
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`
return (
<ChartContext.Provider value={{ config }}>
<div
data-slot="chart"
data-chart={chartId}
className={cn(
"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
className
)}
{...props}
>
<ChartStyle id={chartId} config={config} />
<RechartsPrimitive.ResponsiveContainer>
{children}
</RechartsPrimitive.ResponsiveContainer>
</div>
</ChartContext.Provider>
)
}
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
const colorConfig = Object.entries(config).filter(
([, config]) => config.theme || config.color
)
if (!colorConfig.length) {
return null
}
return (
<style
dangerouslySetInnerHTML={{
__html: Object.entries(THEMES)
.map(
([theme, prefix]) => `
${prefix} [data-chart=${id}] {
${colorConfig
.map(([key, itemConfig]) => {
const color =
itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
itemConfig.color
return color ? ` --color-${key}: ${color};` : null
})
.join("\n")}
}
`
)
.join("\n"),
}}
/>
)
}
const ChartTooltip = RechartsPrimitive.Tooltip
function ChartTooltipContent({
active,
payload,
className,
indicator = "dot",
hideLabel = false,
hideIndicator = false,
label,
labelFormatter,
labelClassName,
formatter,
color,
nameKey,
labelKey,
}: React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
React.ComponentProps<"div"> & {
hideLabel?: boolean
hideIndicator?: boolean
indicator?: "line" | "dot" | "dashed"
nameKey?: string
labelKey?: string
}) {
const { config } = useChart()
const tooltipLabel = React.useMemo(() => {
if (hideLabel || !payload?.length) {
return null
}
const [item] = payload
const key = `${labelKey || item?.dataKey || item?.name || "value"}`
const itemConfig = getPayloadConfigFromPayload(config, item, key)
const value =
!labelKey && typeof label === "string"
? config[label as keyof typeof config]?.label || label
: itemConfig?.label
if (labelFormatter) {
return (
<div className={cn("font-medium", labelClassName)}>
{labelFormatter(value, payload)}
</div>
)
}
if (!value) {
return null
}
return <div className={cn("font-medium", labelClassName)}>{value}</div>
}, [
label,
labelFormatter,
payload,
hideLabel,
labelClassName,
config,
labelKey,
])
if (!active || !payload?.length) {
return null
}
const nestLabel = payload.length === 1 && indicator !== "dot"
return (
<div
className={cn(
"border-border/50 bg-background grid min-w-[8rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl",
className
)}
>
{!nestLabel ? tooltipLabel : null}
<div className="grid gap-1.5">
{payload.map((item, index) => {
const key = `${nameKey || item.name || item.dataKey || "value"}`
const itemConfig = getPayloadConfigFromPayload(config, item, key)
const indicatorColor = color || item.payload.fill || item.color
return (
<div
key={item.dataKey}
className={cn(
"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5",
indicator === "dot" && "items-center"
)}
>
{formatter && item?.value !== undefined && item.name ? (
formatter(item.value, item.name, item, index, item.payload)
) : (
<>
{itemConfig?.icon ? (
<itemConfig.icon />
) : (
!hideIndicator && (
<div
className={cn(
"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)",
{
"h-2.5 w-2.5": indicator === "dot",
"w-1": indicator === "line",
"w-0 border-[1.5px] border-dashed bg-transparent":
indicator === "dashed",
"my-0.5": nestLabel && indicator === "dashed",
}
)}
style={
{
"--color-bg": indicatorColor,
"--color-border": indicatorColor,
} as React.CSSProperties
}
/>
)
)}
<div
className={cn(
"flex flex-1 justify-between leading-none",
nestLabel ? "items-end" : "items-center"
)}
>
<div className="grid gap-1.5">
{nestLabel ? tooltipLabel : null}
<span className="text-muted-foreground">
{itemConfig?.label || item.name}
</span>
</div>
{item.value && (
<span className="text-foreground font-mono font-medium tabular-nums">
{item.value.toLocaleString()}
</span>
)}
</div>
</>
)}
</div>
)
})}
</div>
</div>
)
}
const ChartLegend = RechartsPrimitive.Legend
function ChartLegendContent({
className,
hideIcon = false,
payload,
verticalAlign = "bottom",
nameKey,
}: React.ComponentProps<"div"> &
Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
hideIcon?: boolean
nameKey?: string
}) {
const { config } = useChart()
if (!payload?.length) {
return null
}
return (
<div
className={cn(
"flex items-center justify-center gap-4",
verticalAlign === "top" ? "pb-3" : "pt-3",
className
)}
>
{payload.map((item) => {
const key = `${nameKey || item.dataKey || "value"}`
const itemConfig = getPayloadConfigFromPayload(config, item, key)
return (
<div
key={item.value}
className={cn(
"[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3"
)}
>
{itemConfig?.icon && !hideIcon ? (
<itemConfig.icon />
) : (
<div
className="h-2 w-2 shrink-0 rounded-[2px]"
style={{
backgroundColor: item.color,
}}
/>
)}
{itemConfig?.label}
</div>
)
})}
</div>
)
}
// Helper to extract item config from a payload.
function getPayloadConfigFromPayload(
config: ChartConfig,
payload: unknown,
key: string
) {
if (typeof payload !== "object" || payload === null) {
return undefined
}
const payloadPayload =
"payload" in payload &&
typeof payload.payload === "object" &&
payload.payload !== null
? payload.payload
: undefined
let configLabelKey: string = key
if (
key in payload &&
typeof payload[key as keyof typeof payload] === "string"
) {
configLabelKey = payload[key as keyof typeof payload] as string
} else if (
payloadPayload &&
key in payloadPayload &&
typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
) {
configLabelKey = payloadPayload[
key as keyof typeof payloadPayload
] as string
}
return configLabelKey in config
? config[configLabelKey]
: config[key as keyof typeof config]
}
export {
ChartContainer,
ChartTooltip,
ChartTooltipContent,
ChartLegend,
ChartLegendContent,
ChartStyle,
}

View File

@ -0,0 +1,26 @@
import * as React from "react"
import * as ProgressPrimitive from "@radix-ui/react-progress"
import { cn } from "~/lib/utils"
const Progress = React.forwardRef<
React.ElementRef<typeof ProgressPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
>(({ className, value, ...props }, ref) => (
<ProgressPrimitive.Root
ref={ref}
className={cn(
"relative h-4 w-full overflow-hidden rounded-full bg-secondary",
className
)}
{...props}
>
<ProgressPrimitive.Indicator
className="h-full w-full flex-1 bg-primary transition-all"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/>
</ProgressPrimitive.Root>
))
Progress.displayName = ProgressPrimitive.Root.displayName
export { Progress }

View File

@ -0,0 +1,93 @@
import React, { createContext, useContext, useState } from "react";
import { cn } from "~/lib/utils";
interface TabsContextType {
value: string;
onValueChange: (value: string) => void;
}
const TabsContext = createContext<TabsContextType | undefined>(undefined);
interface TabsProps {
defaultValue?: string;
value?: string;
onValueChange?: (value: string) => void;
className?: string;
children: React.ReactNode;
}
export function Tabs({ defaultValue, value, onValueChange, className, children }: TabsProps) {
const [internalValue, setInternalValue] = useState(defaultValue || "");
const currentValue = value ?? internalValue;
const handleValueChange = onValueChange ?? setInternalValue;
return (
<TabsContext.Provider value={{ value: currentValue, onValueChange: handleValueChange }}>
<div className={cn("w-full", className)}>
{children}
</div>
</TabsContext.Provider>
);
}
interface TabsListProps {
className?: string;
children: React.ReactNode;
}
export function TabsList({ className, children }: TabsListProps) {
return (
<div className={cn("inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", className)}>
{children}
</div>
);
}
interface TabsTriggerProps {
value: string;
className?: string;
disabled?: boolean;
children: React.ReactNode;
}
export function TabsTrigger({ value, className, disabled, children }: TabsTriggerProps) {
const context = useContext(TabsContext);
if (!context) throw new Error("TabsTrigger must be used within Tabs");
const isActive = context.value === value;
return (
<button
type="button"
disabled={disabled}
onClick={() => !disabled && context.onValueChange(value)}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
isActive ? "bg-background text-foreground shadow-sm" : "hover:bg-muted/50",
className
)}
>
{children}
</button>
);
}
interface TabsContentProps {
value: string;
className?: string;
children: React.ReactNode;
}
export function TabsContent({ value, className, children }: TabsContentProps) {
const context = useContext(TabsContext);
if (!context) throw new Error("TabsContent must be used within Tabs");
if (context.value !== value) return null;
return (
<div className={cn("mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", className)}>
{children}
</div>
);
}

View File

@ -144,7 +144,7 @@ class ApiService {
} }
// Innovation process function call wrapper // Innovation process function call wrapper
public async callInnovationProcess<T = any>(payload: any) { public async call<T = any>(payload: any) {
const url = "https://inogen-back.pelekan.org/api/call"; const url = "https://inogen-back.pelekan.org/api/call";
return this.postAbsolute<T>(url, payload); return this.postAbsolute<T>(url, payload);
} }

View File

@ -13,8 +13,10 @@
"@radix-ui/react-dialog": "^1.1.14", "@radix-ui/react-dialog": "^1.1.14",
"@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-label": "^2.0.2", "@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-progress": "^1.1.7",
"@radix-ui/react-select": "^2.2.5", "@radix-ui/react-select": "^2.2.5",
"@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-tabs": "^1.1.13",
"@react-router/node": "^7.7.0", "@react-router/node": "^7.7.0",
"@react-router/serve": "^7.7.1", "@react-router/serve": "^7.7.1",
"@types/d3": "^7.4.3", "@types/d3": "^7.4.3",
@ -30,7 +32,7 @@
"react-dom": "^19.1.0", "react-dom": "^19.1.0",
"react-hot-toast": "^2.5.2", "react-hot-toast": "^2.5.2",
"react-router": "^7.7.0", "react-router": "^7.7.0",
"recharts": "^3.1.2", "recharts": "^2.15.4",
"tailwind-merge": "^3.3.1" "tailwind-merge": "^3.3.1"
}, },
"devDependencies": { "devDependencies": {

View File

@ -20,12 +20,18 @@ importers:
'@radix-ui/react-label': '@radix-ui/react-label':
specifier: ^2.0.2 specifier: ^2.0.2
version: 2.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) version: 2.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-progress':
specifier: ^1.1.7
version: 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-select': '@radix-ui/react-select':
specifier: ^2.2.5 specifier: ^2.2.5
version: 2.2.5(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) version: 2.2.5(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-slot': '@radix-ui/react-slot':
specifier: ^1.0.2 specifier: ^1.0.2
version: 1.2.3(@types/react@19.1.8)(react@19.1.0) version: 1.2.3(@types/react@19.1.8)(react@19.1.0)
'@radix-ui/react-tabs':
specifier: ^1.1.13
version: 1.1.13(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@react-router/node': '@react-router/node':
specifier: ^7.7.0 specifier: ^7.7.0
version: 7.7.0(react-router@7.7.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(typescript@5.8.3) version: 7.7.0(react-router@7.7.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(typescript@5.8.3)
@ -72,8 +78,8 @@ importers:
specifier: ^7.7.0 specifier: ^7.7.0
version: 7.7.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) version: 7.7.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
recharts: recharts:
specifier: ^3.1.2 specifier: ^2.15.4
version: 3.1.2(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react-is@19.1.1)(react@19.1.0)(redux@5.0.1) version: 2.15.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
tailwind-merge: tailwind-merge:
specifier: ^3.3.1 specifier: ^3.3.1
version: 3.3.1 version: 3.3.1
@ -232,6 +238,10 @@ packages:
peerDependencies: peerDependencies:
'@babel/core': ^7.0.0-0 '@babel/core': ^7.0.0-0
'@babel/runtime@7.28.3':
resolution: {integrity: sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==}
engines: {node: '>=6.9.0'}
'@babel/template@7.27.2': '@babel/template@7.27.2':
resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
@ -464,6 +474,9 @@ packages:
'@radix-ui/primitive@1.1.2': '@radix-ui/primitive@1.1.2':
resolution: {integrity: sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==} resolution: {integrity: sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==}
'@radix-ui/primitive@1.1.3':
resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==}
'@radix-ui/react-arrow@1.1.7': '@radix-ui/react-arrow@1.1.7':
resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==}
peerDependencies: peerDependencies:
@ -665,6 +678,19 @@ packages:
'@types/react-dom': '@types/react-dom':
optional: true optional: true
'@radix-ui/react-presence@1.1.5':
resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-primitive@2.1.3': '@radix-ui/react-primitive@2.1.3':
resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==}
peerDependencies: peerDependencies:
@ -678,6 +704,19 @@ packages:
'@types/react-dom': '@types/react-dom':
optional: true optional: true
'@radix-ui/react-progress@1.1.7':
resolution: {integrity: sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-roving-focus@1.1.10': '@radix-ui/react-roving-focus@1.1.10':
resolution: {integrity: sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==} resolution: {integrity: sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==}
peerDependencies: peerDependencies:
@ -691,6 +730,19 @@ packages:
'@types/react-dom': '@types/react-dom':
optional: true optional: true
'@radix-ui/react-roving-focus@1.1.11':
resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-select@2.2.5': '@radix-ui/react-select@2.2.5':
resolution: {integrity: sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA==} resolution: {integrity: sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA==}
peerDependencies: peerDependencies:
@ -713,6 +765,19 @@ packages:
'@types/react': '@types/react':
optional: true optional: true
'@radix-ui/react-tabs@1.1.13':
resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-use-callback-ref@1.1.1': '@radix-ui/react-use-callback-ref@1.1.1':
resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==}
peerDependencies: peerDependencies:
@ -857,17 +922,6 @@ packages:
peerDependencies: peerDependencies:
react-router: 7.8.0 react-router: 7.8.0
'@reduxjs/toolkit@2.8.2':
resolution: {integrity: sha512-MYlOhQ0sLdw4ud48FoC5w0dH9VfWQjtCjreKwYTT3l+r427qYC5Y8PihNutepr8XrNaBUDQo9khWUwQxZaqt5A==}
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
'@rollup/rollup-android-arm-eabi@4.45.1': '@rollup/rollup-android-arm-eabi@4.45.1':
resolution: {integrity: sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==} resolution: {integrity: sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==}
cpu: [arm] cpu: [arm]
@ -968,12 +1022,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@standard-schema/spec@1.0.0':
resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
'@standard-schema/utils@0.3.0':
resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==}
'@tailwindcss/node@4.1.11': '@tailwindcss/node@4.1.11':
resolution: {integrity: sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==} resolution: {integrity: sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==}
@ -1174,9 +1222,6 @@ packages:
'@types/react@19.1.8': '@types/react@19.1.8':
resolution: {integrity: sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==} resolution: {integrity: sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==}
'@types/use-sync-external-store@0.0.6':
resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==}
accepts@1.3.8: accepts@1.3.8:
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
@ -1491,6 +1536,9 @@ packages:
detect-node-es@1.1.0: detect-node-es@1.1.0:
resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
dom-helpers@5.2.1:
resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
dunder-proto@1.0.1: dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -1540,9 +1588,6 @@ packages:
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
es-toolkit@1.39.9:
resolution: {integrity: sha512-9OtbkZmTA2Qc9groyA1PUNeb6knVTkvB2RSdr/LcJXDL8IdEakaxwXLHXa7VX/Wj0GmdMJPR3WhnPGhiP3E+qg==}
esbuild@0.25.8: esbuild@0.25.8:
resolution: {integrity: sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==} resolution: {integrity: sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -1559,8 +1604,8 @@ packages:
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
eventemitter3@5.0.1: eventemitter3@4.0.7:
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
events@3.3.0: events@3.3.0:
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
@ -1574,6 +1619,10 @@ packages:
resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==}
engines: {node: '>= 0.10.0'} engines: {node: '>= 0.10.0'}
fast-equals@5.2.2:
resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==}
engines: {node: '>=6.0.0'}
fdir@6.4.6: fdir@6.4.6:
resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==}
peerDependencies: peerDependencies:
@ -1677,9 +1726,6 @@ packages:
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
immer@10.1.1:
resolution: {integrity: sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==}
inherits@2.0.4: inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
@ -1800,6 +1846,10 @@ packages:
lodash@4.17.21: lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
loose-envify@1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
lru-cache@10.4.3: lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
@ -1922,6 +1972,10 @@ packages:
resolution: {integrity: sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==} resolution: {integrity: sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
object-inspect@1.13.4: object-inspect@1.13.4:
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -1994,6 +2048,9 @@ packages:
resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==}
engines: {node: '>=10'} engines: {node: '>=10'}
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
proxy-addr@2.0.7: proxy-addr@2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'} engines: {node: '>= 0.10'}
@ -2022,20 +2079,11 @@ packages:
react: '>=16' react: '>=16'
react-dom: '>=16' react-dom: '>=16'
react-is@19.1.1: react-is@16.13.1:
resolution: {integrity: sha512-tr41fA15Vn8p4X9ntI+yCyeGSf1TlYaY5vlTZfQmeLBrFo3psOPX6HhTDnFNL9uj3EhP0KAQ80cugCl4b4BERA==} resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
react-redux@9.2.0: react-is@18.3.1:
resolution: {integrity: sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==} resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
peerDependencies:
'@types/react': ^18.2.25 || ^19
react: ^18.0 || ^19
redux: ^5.0.0
peerDependenciesMeta:
'@types/react':
optional: true
redux:
optional: true
react-refresh@0.14.2: react-refresh@0.14.2:
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
@ -2071,6 +2119,12 @@ packages:
react-dom: react-dom:
optional: true optional: true
react-smooth@4.0.4:
resolution: {integrity: sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==}
peerDependencies:
react: ^16.8.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-style-singleton@2.2.3: react-style-singleton@2.2.3:
resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -2081,6 +2135,12 @@ packages:
'@types/react': '@types/react':
optional: true optional: true
react-transition-group@4.4.5:
resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==}
peerDependencies:
react: '>=16.6.0'
react-dom: '>=16.6.0'
react@19.1.0: react@19.1.0:
resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -2089,24 +2149,15 @@ packages:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'} engines: {node: '>= 14.18.0'}
recharts@3.1.2: recharts-scale@0.4.5:
resolution: {integrity: sha512-vhNbYwaxNbk/IATK0Ki29k3qvTkGqwvCgyQAQ9MavvvBwjvKnMTswdbklJpcOAoMPN/qxF3Lyqob0zO+ZXkZ4g==} resolution: {integrity: sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==}
engines: {node: '>=18'}
recharts@2.15.4:
resolution: {integrity: sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==}
engines: {node: '>=14'}
peerDependencies: peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-is: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
redux-thunk@3.1.0:
resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==}
peerDependencies:
redux: ^5.0.0
redux@5.0.1:
resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==}
reselect@5.1.1:
resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==}
retry@0.12.0: retry@0.12.0:
resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==}
@ -2312,11 +2363,6 @@ packages:
'@types/react': '@types/react':
optional: true optional: true
use-sync-external-store@1.5.0:
resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
utils-merge@1.0.1: utils-merge@1.0.1:
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
engines: {node: '>= 0.4.0'} engines: {node: '>= 0.4.0'}
@ -2340,8 +2386,8 @@ packages:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
victory-vendor@37.3.6: victory-vendor@36.9.2:
resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==} resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==}
vite-node@3.2.4: vite-node@3.2.4:
resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
@ -2591,6 +2637,8 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@babel/runtime@7.28.3': {}
'@babel/template@7.27.2': '@babel/template@7.27.2':
dependencies: dependencies:
'@babel/code-frame': 7.27.1 '@babel/code-frame': 7.27.1
@ -2776,6 +2824,8 @@ snapshots:
'@radix-ui/primitive@1.1.2': {} '@radix-ui/primitive@1.1.2': {}
'@radix-ui/primitive@1.1.3': {}
'@radix-ui/react-arrow@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies: dependencies:
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@ -2978,6 +3028,16 @@ snapshots:
'@types/react': 19.1.8 '@types/react': 19.1.8
'@types/react-dom': 19.1.6(@types/react@19.1.8) '@types/react-dom': 19.1.6(@types/react@19.1.8)
'@radix-ui/react-presence@1.1.5(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0)
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.8)(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.8
'@types/react-dom': 19.1.6(@types/react@19.1.8)
'@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies: dependencies:
'@radix-ui/react-slot': 1.2.3(@types/react@19.1.8)(react@19.1.0) '@radix-ui/react-slot': 1.2.3(@types/react@19.1.8)(react@19.1.0)
@ -2987,6 +3047,16 @@ snapshots:
'@types/react': 19.1.8 '@types/react': 19.1.8
'@types/react-dom': 19.1.6(@types/react@19.1.8) '@types/react-dom': 19.1.6(@types/react@19.1.8)
'@radix-ui/react-progress@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/react-context': 1.1.2(@types/react@19.1.8)(react@19.1.0)
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.8
'@types/react-dom': 19.1.6(@types/react@19.1.8)
'@radix-ui/react-roving-focus@1.1.10(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': '@radix-ui/react-roving-focus@1.1.10(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies: dependencies:
'@radix-ui/primitive': 1.1.2 '@radix-ui/primitive': 1.1.2
@ -3004,6 +3074,23 @@ snapshots:
'@types/react': 19.1.8 '@types/react': 19.1.8
'@types/react-dom': 19.1.6(@types/react@19.1.8) '@types/react-dom': 19.1.6(@types/react@19.1.8)
'@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.3
'@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.8)(react@19.1.0)
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.8)(react@19.1.0)
'@radix-ui/react-id': 1.1.1(@types/react@19.1.8)(react@19.1.0)
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.8)(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.8)(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.8
'@types/react-dom': 19.1.6(@types/react@19.1.8)
'@radix-ui/react-select@2.2.5(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': '@radix-ui/react-select@2.2.5(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies: dependencies:
'@radix-ui/number': 1.1.1 '@radix-ui/number': 1.1.1
@ -3040,6 +3127,22 @@ snapshots:
optionalDependencies: optionalDependencies:
'@types/react': 19.1.8 '@types/react': 19.1.8
'@radix-ui/react-tabs@1.1.13(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.3
'@radix-ui/react-context': 1.1.2(@types/react@19.1.8)(react@19.1.0)
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.8)(react@19.1.0)
'@radix-ui/react-id': 1.1.1(@types/react@19.1.8)(react@19.1.0)
'@radix-ui/react-presence': 1.1.5(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.8)(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.8
'@types/react-dom': 19.1.6(@types/react@19.1.8)
'@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.1.8)(react@19.1.0)': '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.1.8)(react@19.1.0)':
dependencies: dependencies:
react: 19.1.0 react: 19.1.0
@ -3191,18 +3294,6 @@ snapshots:
- supports-color - supports-color
- typescript - typescript
'@reduxjs/toolkit@2.8.2(react-redux@9.2.0(@types/react@19.1.8)(react@19.1.0)(redux@5.0.1))(react@19.1.0)':
dependencies:
'@standard-schema/spec': 1.0.0
'@standard-schema/utils': 0.3.0
immer: 10.1.1
redux: 5.0.1
redux-thunk: 3.1.0(redux@5.0.1)
reselect: 5.1.1
optionalDependencies:
react: 19.1.0
react-redux: 9.2.0(@types/react@19.1.8)(react@19.1.0)(redux@5.0.1)
'@rollup/rollup-android-arm-eabi@4.45.1': '@rollup/rollup-android-arm-eabi@4.45.1':
optional: true optional: true
@ -3263,10 +3354,6 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.45.1': '@rollup/rollup-win32-x64-msvc@4.45.1':
optional: true optional: true
'@standard-schema/spec@1.0.0': {}
'@standard-schema/utils@0.3.0': {}
'@tailwindcss/node@4.1.11': '@tailwindcss/node@4.1.11':
dependencies: dependencies:
'@ampproject/remapping': 2.3.0 '@ampproject/remapping': 2.3.0
@ -3471,8 +3558,6 @@ snapshots:
dependencies: dependencies:
csstype: 3.1.3 csstype: 3.1.3
'@types/use-sync-external-store@0.0.6': {}
accepts@1.3.8: accepts@1.3.8:
dependencies: dependencies:
mime-types: 2.1.35 mime-types: 2.1.35
@ -3795,6 +3880,11 @@ snapshots:
detect-node-es@1.1.0: {} detect-node-es@1.1.0: {}
dom-helpers@5.2.1:
dependencies:
'@babel/runtime': 7.28.3
csstype: 3.1.3
dunder-proto@1.0.1: dunder-proto@1.0.1:
dependencies: dependencies:
call-bind-apply-helpers: 1.0.2 call-bind-apply-helpers: 1.0.2
@ -3832,8 +3922,6 @@ snapshots:
dependencies: dependencies:
es-errors: 1.3.0 es-errors: 1.3.0
es-toolkit@1.39.9: {}
esbuild@0.25.8: esbuild@0.25.8:
optionalDependencies: optionalDependencies:
'@esbuild/aix-ppc64': 0.25.8 '@esbuild/aix-ppc64': 0.25.8
@ -3869,7 +3957,7 @@ snapshots:
etag@1.8.1: {} etag@1.8.1: {}
eventemitter3@5.0.1: {} eventemitter3@4.0.7: {}
events@3.3.0: {} events@3.3.0: {}
@ -3911,6 +3999,8 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
fast-equals@5.2.2: {}
fdir@6.4.6(picomatch@4.0.3): fdir@6.4.6(picomatch@4.0.3):
optionalDependencies: optionalDependencies:
picomatch: 4.0.3 picomatch: 4.0.3
@ -4017,8 +4107,6 @@ snapshots:
dependencies: dependencies:
safer-buffer: 2.1.2 safer-buffer: 2.1.2
immer@10.1.1: {}
inherits@2.0.4: {} inherits@2.0.4: {}
internmap@2.0.3: {} internmap@2.0.3: {}
@ -4100,6 +4188,10 @@ snapshots:
lodash@4.17.21: {} lodash@4.17.21: {}
loose-envify@1.4.0:
dependencies:
js-tokens: 4.0.0
lru-cache@10.4.3: {} lru-cache@10.4.3: {}
lru-cache@5.1.1: lru-cache@5.1.1:
@ -4207,6 +4299,8 @@ snapshots:
npm-package-arg: 10.1.0 npm-package-arg: 10.1.0
semver: 7.7.2 semver: 7.7.2
object-assign@4.1.1: {}
object-inspect@1.13.4: {} object-inspect@1.13.4: {}
on-finished@2.3.0: on-finished@2.3.0:
@ -4257,6 +4351,12 @@ snapshots:
err-code: 2.0.3 err-code: 2.0.3
retry: 0.12.0 retry: 0.12.0
prop-types@15.8.1:
dependencies:
loose-envify: 1.4.0
object-assign: 4.1.1
react-is: 16.13.1
proxy-addr@2.0.7: proxy-addr@2.0.7:
dependencies: dependencies:
forwarded: 0.2.0 forwarded: 0.2.0
@ -4287,16 +4387,9 @@ snapshots:
react: 19.1.0 react: 19.1.0
react-dom: 19.1.0(react@19.1.0) react-dom: 19.1.0(react@19.1.0)
react-is@19.1.1: {} react-is@16.13.1: {}
react-redux@9.2.0(@types/react@19.1.8)(react@19.1.0)(redux@5.0.1): react-is@18.3.1: {}
dependencies:
'@types/use-sync-external-store': 0.0.6
react: 19.1.0
use-sync-external-store: 1.5.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.8
redux: 5.0.1
react-refresh@0.14.2: {} react-refresh@0.14.2: {}
@ -4327,6 +4420,14 @@ snapshots:
optionalDependencies: optionalDependencies:
react-dom: 19.1.0(react@19.1.0) react-dom: 19.1.0(react@19.1.0)
react-smooth@4.0.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
fast-equals: 5.2.2
prop-types: 15.8.1
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
react-transition-group: 4.4.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react-style-singleton@2.2.3(@types/react@19.1.8)(react@19.1.0): react-style-singleton@2.2.3(@types/react@19.1.8)(react@19.1.0):
dependencies: dependencies:
get-nonce: 1.0.1 get-nonce: 1.0.1
@ -4335,37 +4436,35 @@ snapshots:
optionalDependencies: optionalDependencies:
'@types/react': 19.1.8 '@types/react': 19.1.8
react-transition-group@4.4.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@babel/runtime': 7.28.3
dom-helpers: 5.2.1
loose-envify: 1.4.0
prop-types: 15.8.1
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
react@19.1.0: {} react@19.1.0: {}
readdirp@4.1.2: {} readdirp@4.1.2: {}
recharts@3.1.2(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react-is@19.1.1)(react@19.1.0)(redux@5.0.1): recharts-scale@0.4.5:
dependencies: dependencies:
'@reduxjs/toolkit': 2.8.2(react-redux@9.2.0(@types/react@19.1.8)(react@19.1.0)(redux@5.0.1))(react@19.1.0)
clsx: 2.1.1
decimal.js-light: 2.5.1 decimal.js-light: 2.5.1
es-toolkit: 1.39.9
eventemitter3: 5.0.1 recharts@2.15.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
immer: 10.1.1 dependencies:
clsx: 2.1.1
eventemitter3: 4.0.7
lodash: 4.17.21
react: 19.1.0 react: 19.1.0
react-dom: 19.1.0(react@19.1.0) react-dom: 19.1.0(react@19.1.0)
react-is: 19.1.1 react-is: 18.3.1
react-redux: 9.2.0(@types/react@19.1.8)(react@19.1.0)(redux@5.0.1) react-smooth: 4.0.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
reselect: 5.1.1 recharts-scale: 0.4.5
tiny-invariant: 1.3.3 tiny-invariant: 1.3.3
use-sync-external-store: 1.5.0(react@19.1.0) victory-vendor: 36.9.2
victory-vendor: 37.3.6
transitivePeerDependencies:
- '@types/react'
- redux
redux-thunk@3.1.0(redux@5.0.1):
dependencies:
redux: 5.0.1
redux@5.0.1: {}
reselect@5.1.1: {}
retry@0.12.0: {} retry@0.12.0: {}
@ -4587,10 +4686,6 @@ snapshots:
optionalDependencies: optionalDependencies:
'@types/react': 19.1.8 '@types/react': 19.1.8
use-sync-external-store@1.5.0(react@19.1.0):
dependencies:
react: 19.1.0
utils-merge@1.0.1: {} utils-merge@1.0.1: {}
valibot@0.41.0(typescript@5.8.3): valibot@0.41.0(typescript@5.8.3):
@ -4606,7 +4701,7 @@ snapshots:
vary@1.1.2: {} vary@1.1.2: {}
victory-vendor@37.3.6: victory-vendor@36.9.2:
dependencies: dependencies:
'@types/d3-array': 3.2.1 '@types/d3-array': 3.2.1
'@types/d3-ease': 3.0.2 '@types/d3-ease': 3.0.2