Compare commits

..

No commits in common. "5d550217db9ff6102916674ca374a958e1585487" and "0fed828d77c28aa172d6ca377ca4d8f528f18dc2" have entirely different histories.

15 changed files with 132 additions and 194 deletions

View File

@ -1,3 +1,4 @@
import jalaali from "jalaali-js";
import { Book, CheckCircle } from "lucide-react"; import { Book, CheckCircle } from "lucide-react";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
@ -15,7 +16,6 @@ import { ChartContainer } from "~/components/ui/chart";
import { MetricCard } from "~/components/ui/metric-card"; import { MetricCard } from "~/components/ui/metric-card";
import { Progress } from "~/components/ui/progress"; import { Progress } from "~/components/ui/progress";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs";
import { useStoredDate } from "~/hooks/useStoredDate";
import apiService from "~/lib/api"; import apiService from "~/lib/api";
import { EventBus, formatNumber } from "~/lib/utils"; import { EventBus, formatNumber } from "~/lib/utils";
import type { CalendarDate } from "~/types/util.type"; import type { CalendarDate } from "~/types/util.type";
@ -25,6 +25,7 @@ import { InteractiveBarChart } from "./interactive-bar-chart";
import { DashboardLayout } from "./layout"; import { DashboardLayout } from "./layout";
export function DashboardHome() { export function DashboardHome() {
const { jy } = jalaali.toJalaali(new Date());
const [dashboardData, setDashboardData] = useState<any | null>(null); const [dashboardData, setDashboardData] = useState<any | null>(null);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
@ -41,7 +42,10 @@ export function DashboardHome() {
}[] }[]
>([]); >([]);
const [date, setDate] = useStoredDate(); const [date, setDate] = useState<CalendarDate>({
start: `${jy}/01/01`,
end: `${jy}/12/30`,
});
useEffect(() => { useEffect(() => {
EventBus.on("dateSelected", (date: CalendarDate) => { EventBus.on("dateSelected", (date: CalendarDate) => {
@ -50,7 +54,7 @@ export function DashboardHome() {
}, []); }, []);
useEffect(() => { useEffect(() => {
if (date?.end && date?.start) fetchDashboardData(); fetchDashboardData();
}, [date]); }, [date]);
const fetchDashboardData = async () => { const fetchDashboardData = async () => {

View File

@ -65,7 +65,7 @@ const monthList: Array<MonthItem> = [
id: "month-4", id: "month-4",
label: "زمستان", label: "زمستان",
start: "10/01", start: "10/01",
end: "12/30", end: "12/29",
}, },
]; ];
@ -87,34 +87,12 @@ export function Header({
until: jy, until: jy,
}); });
const [selectedDate, setSelectedDate] = useState<CurrentDay>({}); const [selectedDate, setSelectedDate] = useState<CurrentDay>({
sinceMonth: "بهار",
useEffect(() => { fromMonth: "زمستان",
const storedDate = localStorage.getItem("dateSelected"); start: `${currentYear.since}/01/01`,
if (storedDate) { end: `${currentYear.until}/12/30`,
const parsedDate = JSON.parse(storedDate); });
setSelectedDate(parsedDate);
const sinceYear = parsedDate.start
? parseInt(parsedDate.start.split("/")[0], 10)
: jy;
const untilYear = parsedDate.end
? parseInt(parsedDate.end.split("/")[0], 10)
: jy;
setCurrentYear({ since: sinceYear, until: untilYear });
} else {
const defaultDate = {
sinceMonth: "بهار",
fromMonth: "زمستان",
start: `${jy}/01/01`,
end: `${jy}/12/30`,
};
setSelectedDate(defaultDate);
localStorage.setItem("dateSelected", JSON.stringify(defaultDate));
setCurrentYear({ since: jy, until: jy });
}
}, []);
const redirectHandler = async () => { const redirectHandler = async () => {
try { try {
@ -141,7 +119,6 @@ export function Header({
start: `${newSince}/${selectedDate.start?.split("/").slice(1).join("/")}`, start: `${newSince}/${selectedDate.start?.split("/").slice(1).join("/")}`,
}; };
setSelectedDate(updatedDate); setSelectedDate(updatedDate);
localStorage.setItem("dateSelected", JSON.stringify(updatedDate));
EventBus.emit("dateSelected", updatedDate); EventBus.emit("dateSelected", updatedDate);
}; };
@ -155,7 +132,6 @@ export function Header({
sinceMonth: val.label, sinceMonth: val.label,
}; };
setSelectedDate(data); setSelectedDate(data);
localStorage.setItem("dateSelected", JSON.stringify(data));
EventBus.emit("dateSelected", data); EventBus.emit("dateSelected", data);
}; };
@ -174,7 +150,6 @@ export function Header({
end: `${newUntil}/${selectedDate.end?.split("/").slice(1).join("/")}`, end: `${newUntil}/${selectedDate.end?.split("/").slice(1).join("/")}`,
}; };
setSelectedDate(updatedDate); setSelectedDate(updatedDate);
localStorage.setItem("dateSelected", JSON.stringify(updatedDate));
EventBus.emit("dateSelected", updatedDate); EventBus.emit("dateSelected", updatedDate);
}; };
@ -188,7 +163,6 @@ export function Header({
fromMonth: val.label, fromMonth: val.label,
}; };
setSelectedDate(data); setSelectedDate(data);
localStorage.setItem("dateSelected", JSON.stringify(data));
EventBus.emit("dateSelected", data); EventBus.emit("dateSelected", data);
toggleCalendar(); toggleCalendar();
}; };

View File

@ -1,3 +1,4 @@
import jalaali from "jalaali-js";
import { import {
BrainCircuit, BrainCircuit,
ChevronDown, ChevronDown,
@ -33,7 +34,6 @@ import {
TableHeader, TableHeader,
TableRow, TableRow,
} from "~/components/ui/table"; } from "~/components/ui/table";
import { useStoredDate } from "~/hooks/useStoredDate";
import apiService from "~/lib/api"; import apiService from "~/lib/api";
import { EventBus, formatCurrency, formatNumber } from "~/lib/utils"; import { EventBus, formatCurrency, formatNumber } from "~/lib/utils";
import type { CalendarDate } from "~/types/util.type"; import type { CalendarDate } from "~/types/util.type";
@ -148,13 +148,18 @@ const columns = [
]; ];
export function DigitalInnovationPage() { export function DigitalInnovationPage() {
const { jy } = jalaali.toJalaali(new Date());
const [projects, setProjects] = useState<DigitalInnovationMetrics[]>([]); const [projects, setProjects] = useState<DigitalInnovationMetrics[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [loadingMore, setLoadingMore] = useState(false); const [loadingMore, setLoadingMore] = useState(false);
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [pageSize] = useState(20); const [pageSize] = useState(20);
const [hasMore, setHasMore] = useState(true); const [hasMore, setHasMore] = useState(true);
const [date, setDate] = useStoredDate(); // const [totalCount, setTotalCount] = useState(0);
const [date, setDate] = useState<CalendarDate>({
start: `${jy}/01/01`,
end: `${jy}/12/30`,
});
const [actualTotalCount, setActualTotalCount] = useState(0); const [actualTotalCount, setActualTotalCount] = useState(0);
const [statsLoading, setStatsLoading] = useState(false); const [statsLoading, setStatsLoading] = useState(false);
const [rating, setRating] = useState<ListItem[]>([]); const [rating, setRating] = useState<ListItem[]>([]);
@ -358,25 +363,10 @@ export function DigitalInnovationPage() {
} }
}, [hasMore, loading, loadingMore]); }, [hasMore, loading, loadingMore]);
// useEffect(() => {
// const storedDate = localStorage.getItem("dateSelected");
// if (storedDate) {
// setDate(JSON.parse(storedDate));
// } else {
// setDate({
// start: `${jy}/01/01`,
// end: `${jy}/12/30`,
// });
// }
// }, []);
useEffect(() => { useEffect(() => {
if (date?.start && date?.end) { fetchTable(true);
fetchTable(true); fetchTotalCount();
fetchTotalCount(); fetchStats();
fetchStats();
}
}, [sortConfig, date]); }, [sortConfig, date]);
useEffect(() => { useEffect(() => {
@ -388,7 +378,7 @@ export function DigitalInnovationPage() {
}, []); }, []);
useEffect(() => { useEffect(() => {
if (currentPage > 1 && date?.start && date?.end) { if (currentPage > 1) {
fetchTable(false); fetchTable(false);
} }
}, [currentPage]); }, [currentPage]);

View File

@ -1,3 +1,4 @@
// import moment from "moment-jalaali";
import { useCallback, useEffect, useRef, useState } from "react"; import { useCallback, useEffect, useRef, useState } from "react";
import { import {
Bar, Bar,
@ -27,6 +28,7 @@ import {
} from "~/components/ui/table"; } from "~/components/ui/table";
import { EventBus, formatNumber } from "~/lib/utils"; import { EventBus, formatNumber } from "~/lib/utils";
import jalaali from "jalaali-js";
import { import {
Building2, Building2,
ChevronDown, ChevronDown,
@ -42,16 +44,13 @@ import {
UsersIcon, UsersIcon,
Zap, Zap,
} from "lucide-react"; } from "lucide-react";
import moment from "moment-jalaali";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { useStoredDate } from "~/hooks/useStoredDate";
import apiService from "~/lib/api"; import apiService from "~/lib/api";
import { formatCurrency } from "~/lib/utils"; import { formatCurrency } from "~/lib/utils";
import type { CalendarDate } from "~/types/util.type"; import type { CalendarDate } from "~/types/util.type";
import DashboardLayout from "../layout"; import DashboardLayout from "../layout";
moment.loadPersian({ usePersianDigits: true }); // moment.loadPersian({ usePersianDigits: true });
interface GreenInnovationData { interface GreenInnovationData {
WorkflowID: string; WorkflowID: string;
approved_budget: string; approved_budget: string;
@ -160,6 +159,7 @@ const columns = [
]; ];
export function GreenInnovationPage() { export function GreenInnovationPage() {
const { jy } = jalaali.toJalaali(new Date());
const [projects, setProjects] = useState<GreenInnovationData[]>([]); const [projects, setProjects] = useState<GreenInnovationData[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [loadingMore, setLoadingMore] = useState(false); const [loadingMore, setLoadingMore] = useState(false);
@ -169,8 +169,10 @@ export function GreenInnovationPage() {
const [totalCount, setTotalCount] = useState(0); const [totalCount, setTotalCount] = useState(0);
const [actualTotalCount, setActualTotalCount] = useState(0); const [actualTotalCount, setActualTotalCount] = useState(0);
const [statsLoading, setStatsLoading] = useState(false); const [statsLoading, setStatsLoading] = useState(false);
const [date, setDate] = useStoredDate(); const [date, setDate] = useState<CalendarDate>({
start: `${jy}/01/01`,
end: `${jy}/12/30`,
});
const [stats, setStats] = useState<stateCounter>(); const [stats, setStats] = useState<stateCounter>();
const [sortConfig, setSortConfig] = useState<SortConfig>({ const [sortConfig, setSortConfig] = useState<SortConfig>({
field: "start_date", field: "start_date",
@ -374,14 +376,12 @@ export function GreenInnovationPage() {
}, [hasMore, loading]); }, [hasMore, loading]);
useEffect(() => { useEffect(() => {
if (date.end && date.start) { fetchProjects(true);
fetchProjects(true); fetchTotalCount();
fetchTotalCount();
}
}, [sortConfig, date]); }, [sortConfig, date]);
useEffect(() => { useEffect(() => {
if (date.end && date.start) fetchStats(); fetchStats();
}, [selectedProjects, date]); }, [selectedProjects, date]);
useEffect(() => { useEffect(() => {

View File

@ -19,6 +19,7 @@ import {
TableRow, TableRow,
} from "~/components/ui/table"; } from "~/components/ui/table";
import jalaali from "jalaali-js";
import { import {
ChevronDown, ChevronDown,
ChevronUp, ChevronUp,
@ -39,7 +40,6 @@ import {
ResponsiveContainer, ResponsiveContainer,
XAxis, XAxis,
} from "recharts"; } from "recharts";
import { useStoredDate } from "~/hooks/useStoredDate";
import apiService from "~/lib/api"; import apiService from "~/lib/api";
import { EventBus, formatCurrency, formatNumber } from "~/lib/utils"; import { EventBus, formatCurrency, formatNumber } from "~/lib/utils";
import type { CalendarDate } from "~/types/util.type"; import type { CalendarDate } from "~/types/util.type";
@ -179,6 +179,7 @@ const dialogChartData = [
]; ];
export function InnovationBuiltInsidePage() { export function InnovationBuiltInsidePage() {
const { jy } = jalaali.toJalaali(new Date());
const [projects, setProjects] = useState<innovationBuiltInDate[]>([]); const [projects, setProjects] = useState<innovationBuiltInDate[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [loadingMore, setLoadingMore] = useState(false); const [loadingMore, setLoadingMore] = useState(false);
@ -193,8 +194,10 @@ export function InnovationBuiltInsidePage() {
field: "start_date", field: "start_date",
direction: "asc", direction: "asc",
}); });
const [date, setDate] = useState<CalendarDate>({
const [date, setDate] = useStoredDate(); start: `${jy}/01/01`,
end: `${jy}/12/30`,
});
const [tblAvarage, setTblAvarage] = useState<number>(0); const [tblAvarage, setTblAvarage] = useState<number>(0);
const [selectedProjects, setSelectedProjects] = const [selectedProjects, setSelectedProjects] =
useState<Set<string | number>>(); useState<Set<string | number>>();
@ -433,11 +436,11 @@ export function InnovationBuiltInsidePage() {
}, []); }, []);
useEffect(() => { useEffect(() => {
if (date.start && date.end) fetchProjects(true); fetchProjects(true);
}, [sortConfig, date]); }, [sortConfig, date]);
useEffect(() => { useEffect(() => {
if (date.end && date.start) fetchStats(); fetchStats();
}, [selectedProjects, date]); }, [selectedProjects, date]);
useEffect(() => { useEffect(() => {
@ -721,7 +724,7 @@ export function InnovationBuiltInsidePage() {
return ( return (
<DashboardLayout title="نوآوری ساخت داخل"> <DashboardLayout title="نوآوری ساخت داخل">
<div className="space-y-4 justify-between gap-8 grid pl-6 sm:grid-cols-1 xl:grid-cols-[35%_65%]"> <div className="space-y-4 justify-between gap-8 grid pl-3.5 sm:grid-cols-1 xl:grid-cols-[35%_65%]">
{/* Stats Cards */} {/* Stats Cards */}
<div className="flex w-full mb-0"> <div className="flex w-full mb-0">
<div className="flex flex-col w-full justify-between gap-2"> <div className="flex flex-col w-full justify-between gap-2">

View File

@ -1,3 +1,4 @@
import jalaali from "jalaali-js";
import { import {
ChevronDown, ChevronDown,
ChevronUp, ChevronUp,
@ -42,7 +43,6 @@ import {
TableHeader, TableHeader,
TableRow, TableRow,
} from "~/components/ui/table"; } from "~/components/ui/table";
import { useStoredDate } from "~/hooks/useStoredDate";
import apiService from "~/lib/api"; import apiService from "~/lib/api";
import { EventBus, formatCurrency, formatNumber } from "~/lib/utils"; import { EventBus, formatCurrency, formatNumber } from "~/lib/utils";
import type { CalendarDate } from "~/types/util.type"; import type { CalendarDate } from "~/types/util.type";
@ -261,6 +261,7 @@ const VerticalBarChart = memo<{
const MemoizedVerticalBarChart = VerticalBarChart; const MemoizedVerticalBarChart = VerticalBarChart;
export function ManageIdeasTechPage() { export function ManageIdeasTechPage() {
const { jy } = jalaali.toJalaali(new Date());
const [ideas, setIdeas] = useState<IdeaData[]>([]); const [ideas, setIdeas] = useState<IdeaData[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [loadingMore, setLoadingMore] = useState(false); const [loadingMore, setLoadingMore] = useState(false);
@ -275,7 +276,10 @@ export function ManageIdeasTechPage() {
field: "idea_title", field: "idea_title",
direction: "asc", direction: "asc",
}); });
const [date, setDate] = useStoredDate(); const [date, setDate] = useState<CalendarDate>({
start: `${jy}/01/01`,
end: `${jy}/12/30`,
});
// People ranking state // People ranking state
const [peopleRanking, setPeopleRanking] = useState<PersonRanking[]>([]); const [peopleRanking, setPeopleRanking] = useState<PersonRanking[]>([]);
@ -413,13 +417,11 @@ export function ManageIdeasTechPage() {
}, []); }, []);
useEffect(() => { useEffect(() => {
if (date.end && date.start) { fetchIdeas(true);
fetchIdeas(true); fetchTotalCount();
fetchTotalCount(); fetchPeopleRanking();
fetchPeopleRanking(); fetchChartData();
fetchChartData(); fetchStatsData();
fetchStatsData();
}
}, [sortConfig, date]); }, [sortConfig, date]);
useEffect(() => { useEffect(() => {

View File

@ -1,3 +1,4 @@
import jalaali from "jalaali-js";
import { import {
Building2, Building2,
ChevronDown, ChevronDown,
@ -34,7 +35,6 @@ import {
TableHeader, TableHeader,
TableRow, TableRow,
} from "~/components/ui/table"; } from "~/components/ui/table";
import { useStoredDate } from "~/hooks/useStoredDate";
import apiService from "~/lib/api"; import apiService from "~/lib/api";
import { EventBus, formatNumber } from "~/lib/utils"; import { EventBus, formatNumber } from "~/lib/utils";
import type { CalendarDate } from "~/types/util.type"; import type { CalendarDate } from "~/types/util.type";
@ -119,13 +119,18 @@ const columns = [
]; ];
export function ProcessInnovationPage() { export function ProcessInnovationPage() {
const { jy } = jalaali.toJalaali(new Date());
const [projects, setProjects] = useState<ProcessInnovationData[]>([]); const [projects, setProjects] = useState<ProcessInnovationData[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [loadingMore, setLoadingMore] = useState(false); const [loadingMore, setLoadingMore] = useState(false);
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [pageSize] = useState(20); const [pageSize] = useState(20);
const [hasMore, setHasMore] = useState(true); const [hasMore, setHasMore] = useState(true);
const [date, setDate] = useStoredDate(); // const [totalCount, setTotalCount] = useState(0);
const [date, setDate] = useState<CalendarDate>({
start: `${jy}/01/01`,
end: `${jy}/12/30`,
});
const [actualTotalCount, setActualTotalCount] = useState(0); const [actualTotalCount, setActualTotalCount] = useState(0);
const [statsLoading, setStatsLoading] = useState(false); const [statsLoading, setStatsLoading] = useState(false);
const [stats, setStats] = useState<InnovationStats>({ const [stats, setStats] = useState<InnovationStats>({
@ -340,14 +345,12 @@ export function ProcessInnovationPage() {
}, []); }, []);
useEffect(() => { useEffect(() => {
if (date?.start && date?.end) { fetchProjects(true);
fetchProjects(true); fetchTotalCount();
fetchTotalCount();
}
}, [sortConfig, date]); }, [sortConfig, date]);
useEffect(() => { useEffect(() => {
if (date?.start && date?.end) fetchStats(); fetchStats();
}, [selectedProjects, date]); }, [selectedProjects, date]);
useEffect(() => { useEffect(() => {

View File

@ -14,6 +14,7 @@ import {
PopoverTrigger, PopoverTrigger,
} from "~/components/ui/popover"; } from "~/components/ui/popover";
import jalaali from "jalaali-js";
import { import {
CartesianGrid, CartesianGrid,
Legend, Legend,
@ -41,7 +42,6 @@ import {
TableRow, TableRow,
} from "~/components/ui/table"; } from "~/components/ui/table";
import { Tooltip as TooltipSh, TooltipTrigger } from "~/components/ui/tooltip"; import { Tooltip as TooltipSh, TooltipTrigger } from "~/components/ui/tooltip";
import { useStoredDate } from "~/hooks/useStoredDate";
import apiService from "~/lib/api"; import apiService from "~/lib/api";
import { EventBus, formatNumber, handleDataValue } from "~/lib/utils"; import { EventBus, formatNumber, handleDataValue } from "~/lib/utils";
import type { CalendarDate } from "~/types/util.type"; import type { CalendarDate } from "~/types/util.type";
@ -199,6 +199,7 @@ export default function Timeline(valueTimeLine: string) {
export function ProductInnovationPage() { export function ProductInnovationPage() {
// const [showPopup, setShowPopup] = useState(false); // const [showPopup, setShowPopup] = useState(false);
const { jy } = jalaali.toJalaali(new Date());
const [projects, setProjects] = useState<ProductInnovationData[]>([]); const [projects, setProjects] = useState<ProductInnovationData[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [loadingMore, setLoadingMore] = useState(false); const [loadingMore, setLoadingMore] = useState(false);
@ -263,8 +264,10 @@ export function ProductInnovationPage() {
}, },
}); });
const [date, setDate] = useStoredDate(); const [date, setDate] = useState<CalendarDate>({
start: `${jy}/01/01`,
end: `${jy}/12/30`,
});
const observerRef = useRef<HTMLDivElement>(null); const observerRef = useRef<HTMLDivElement>(null);
const fetchingRef = useRef(false); const fetchingRef = useRef(false);
@ -517,11 +520,11 @@ export function ProductInnovationPage() {
}, []); }, []);
useEffect(() => { useEffect(() => {
if (date.end && date.start) fetchProjects(true); fetchProjects(true);
}, [sortConfig, date]); }, [sortConfig, date]);
useEffect(() => { useEffect(() => {
if (date.end && date.start) fetchStats(); fetchStats();
}, [date]); }, [date]);
useEffect(() => { useEffect(() => {

View File

@ -1,3 +1,4 @@
import jalaali from "jalaali-js";
import { ChevronDown, ChevronUp, RefreshCw } from "lucide-react"; import { ChevronDown, ChevronUp, RefreshCw } from "lucide-react";
import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
@ -12,7 +13,6 @@ import {
TableHeader, TableHeader,
TableRow, TableRow,
} from "~/components/ui/table"; } from "~/components/ui/table";
import { useStoredDate } from "~/hooks/useStoredDate";
import apiService from "~/lib/api"; import apiService from "~/lib/api";
import { EventBus, formatCurrency, formatNumber } from "~/lib/utils"; import { EventBus, formatCurrency, formatNumber } from "~/lib/utils";
import type { CalendarDate } from "~/types/util.type"; import type { CalendarDate } from "~/types/util.type";
@ -154,6 +154,7 @@ const columns: ColumnDef[] = [
]; ];
export function ProjectManagementPage() { export function ProjectManagementPage() {
const { jy } = jalaali.toJalaali(new Date());
const [projects, setProjects] = useState<ProjectData[]>([]); const [projects, setProjects] = useState<ProjectData[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [loadingMore, setLoadingMore] = useState(false); const [loadingMore, setLoadingMore] = useState(false);
@ -170,12 +171,10 @@ export function ProjectManagementPage() {
const fetchingRef = useRef(false); const fetchingRef = useRef(false);
const scrollTimeoutRef = useRef<NodeJS.Timeout | null>(null); const scrollTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const scrollContainerRef = useRef<HTMLDivElement>(null); const scrollContainerRef = useRef<HTMLDivElement>(null);
// const [date, setDate] = useState<CalendarDate>({ const [date, setDate] = useState<CalendarDate>({
// start: `${jy}/01/01`, start: `${jy}/01/01`,
// end: `${jy}/12/30`, end: `${jy}/12/30`,
// }); });
const [date, setDate] = useStoredDate();
const fetchProjects = async (reset = false) => { const fetchProjects = async (reset = false) => {
// Prevent concurrent API calls // Prevent concurrent API calls
@ -289,10 +288,8 @@ export function ProjectManagementPage() {
}, [hasMore, loading, loadingMore]); }, [hasMore, loading, loadingMore]);
useEffect(() => { useEffect(() => {
if (date.end && date.start) { fetchProjects(true);
fetchProjects(true); fetchTotalCount();
fetchTotalCount();
}
}, [sortConfig, date]); }, [sortConfig, date]);
useEffect(() => { useEffect(() => {

View File

@ -1,3 +1,4 @@
import jalaali from "jalaali-js";
import { useEffect, useReducer, useRef, useState } from "react"; import { useEffect, useReducer, useRef, useState } from "react";
import { import {
Bar, Bar,
@ -11,7 +12,6 @@ import {
} from "recharts"; } from "recharts";
import { Dialog, DialogContent, DialogHeader } from "~/components/ui/dialog"; import { Dialog, DialogContent, DialogHeader } from "~/components/ui/dialog";
import { Skeleton } from "~/components/ui/skeleton"; import { Skeleton } from "~/components/ui/skeleton";
import { useStoredDate } from "~/hooks/useStoredDate";
import apiService from "~/lib/api"; import apiService from "~/lib/api";
import { EventBus, formatNumber } from "~/lib/utils"; import { EventBus, formatNumber } from "~/lib/utils";
import type { CalendarDate } from "~/types/util.type"; import type { CalendarDate } from "~/types/util.type";
@ -118,6 +118,7 @@ export function StrategicAlignmentPopup({
open, open,
onOpenChange, onOpenChange,
}: StrategicAlignmentPopupProps) { }: StrategicAlignmentPopupProps) {
const { jy } = jalaali.toJalaali(new Date());
const [data, setData] = useState<StrategicAlignmentData[]>([]); const [data, setData] = useState<StrategicAlignmentData[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const contentRef = useRef<HTMLDivElement | null>(null); const contentRef = useRef<HTMLDivElement | null>(null);
@ -127,8 +128,10 @@ export function StrategicAlignmentPopup({
dropDownItems: [], dropDownItems: [],
}); });
const [date, setDate] = useStoredDate(); const [date, setDate] = useState<CalendarDate>({
start: `${jy}/01/01`,
end: `${jy}/12/30`,
});
useEffect(() => { useEffect(() => {
if (open) { if (open) {
fetchData(); fetchData();

View File

@ -12,7 +12,6 @@ import {
} from "recharts"; } from "recharts";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import { CustomBarChart } from "~/components/ui/custom-bar-chart"; import { CustomBarChart } from "~/components/ui/custom-bar-chart";
import { useStoredDate } from "~/hooks/useStoredDate";
import apiService from "~/lib/api"; import apiService from "~/lib/api";
import { EventBus, formatNumber } from "~/lib/utils"; import { EventBus, formatNumber } from "~/lib/utils";
import type { CalendarDate } from "~/types/util.type"; import type { CalendarDate } from "~/types/util.type";
@ -64,9 +63,7 @@ export function InfoPanel({ selectedCompany }: InfoPanelProps) {
const [counts, setCounts] = useState<EcosystemCounts | null>(null); const [counts, setCounts] = useState<EcosystemCounts | null>(null);
const [processData, setProcessData] = useState<ProcessActorsData[]>([]); const [processData, setProcessData] = useState<ProcessActorsData[]>([]);
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
// const [date, setDate] = useState<CalendarDate>(); const [date, setDate] = useState<CalendarDate>();
const [date, setDate] = useStoredDate();
useEffect(() => { useEffect(() => {
EventBus.on("dateSelected", (date: CalendarDate) => { EventBus.on("dateSelected", (date: CalendarDate) => {
if (date) { if (date) {
@ -76,7 +73,7 @@ export function InfoPanel({ selectedCompany }: InfoPanelProps) {
}, []); }, []);
useEffect(() => { useEffect(() => {
if (date.end && date.start) fetchCounts(); fetchCounts();
}, [date]); }, [date]);
const fetchCounts = async () => { const fetchCounts = async () => {

View File

@ -1,6 +1,5 @@
import * as d3 from "d3"; import * as d3 from "d3";
import { useCallback, useEffect, useRef, useState } from "react"; import { useCallback, useEffect, useRef, useState } from "react";
import { useStoredDate } from "~/hooks/useStoredDate";
import { EventBus } from "~/lib/utils"; import { EventBus } from "~/lib/utils";
import type { CalendarDate } from "~/types/util.type"; import type { CalendarDate } from "~/types/util.type";
import { useAuth } from "../../contexts/auth-context"; import { useAuth } from "../../contexts/auth-context";
@ -74,9 +73,7 @@ export function NetworkGraph({
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const { token } = useAuth(); const { token } = useAuth();
// const [date, setDate] = useState<CalendarDate>(); const [date, setDate] = useState<CalendarDate>();
const [date, setDate] = useStoredDate();
useEffect(() => { useEffect(() => {
EventBus.on("dateSelected", (date: CalendarDate) => { EventBus.on("dateSelected", (date: CalendarDate) => {
if (date) { if (date) {
@ -123,10 +120,7 @@ export function NetworkGraph({
setIsLoading(true); setIsLoading(true);
try { try {
const res = await apiService.call<any[]>({ const res = await apiService.call<any[]>({
graph_production_function: { graph_production_function: {},
start_date: date.start || null,
end_date: date.end || null,
},
}); });
if (aborted) return; if (aborted) return;
@ -490,37 +484,35 @@ export function NetworkGraph({
onLoadingChange?.(true); onLoadingChange?.(true);
try { try {
if (date.start && date.end) { const res = await callAPI(d.stageid);
const res = await callAPI(d.stageid); const responseData = JSON.parse(res.data);
const responseData = JSON.parse(res.data); const fieldValues =
const fieldValues = JSON.parse(responseData?.getvalue)?.[0]?.FieldValues || [];
JSON.parse(responseData?.getvalue)?.[0]?.FieldValues || [];
const filteredFields = fieldValues.filter( const filteredFields = fieldValues.filter(
(field: any) => (field: any) =>
!["image", "img", "full_name", "about_collaboration"].includes( !["image", "img", "full_name", "about_collaboration"].includes(
field.F.toLowerCase() field.F.toLowerCase()
) )
); );
const descriptionField = fieldValues.find( const descriptionField = fieldValues.find(
(field: any) => (field: any) =>
field.F.toLowerCase().includes("description") || field.F.toLowerCase().includes("description") ||
field.F.toLowerCase().includes("about_collaboration") || field.F.toLowerCase().includes("about_collaboration") ||
field.F.toLowerCase().includes("about") field.F.toLowerCase().includes("about")
); );
const companyDetails: CompanyDetails = { const companyDetails: CompanyDetails = {
id: d.id, id: d.id,
label: d.label, label: d.label,
category: d.category, category: d.category,
stageid: d.stageid, stageid: d.stageid,
fields: filteredFields, fields: filteredFields,
description: descriptionField?.V || undefined, description: descriptionField?.V || undefined,
}; };
onNodeClick(companyDetails); onNodeClick(companyDetails);
}
} catch (error) { } catch (error) {
console.error("Failed to fetch company details:", error); console.error("Failed to fetch company details:", error);
// Keep the basic details already shown // Keep the basic details already shown
@ -549,7 +541,7 @@ export function NetworkGraph({
return () => { return () => {
simulation.stop(); simulation.stop();
}; };
}, [nodes, links, isLoading, isMounted, onNodeClick, callAPI, date]); }, [nodes, links, isLoading, isMounted, onNodeClick, callAPI]);
if (error) { if (error) {
return ( return (

View File

@ -1,27 +0,0 @@
import jalaali from "jalaali-js";
import { useEffect, useState } from "react";
import type { CalendarDate } from "~/types/util.type";
const { jy } = jalaali.toJalaali(new Date());
export function useStoredDate(): [
CalendarDate,
React.Dispatch<React.SetStateAction<CalendarDate>>,
] {
const [date, setDate] = useState<CalendarDate>({});
useEffect(() => {
const storedDate = localStorage.getItem("dateSelected");
if (storedDate) {
setDate(JSON.parse(storedDate));
} else {
setDate({
start: `${jy}/01/01`,
end: `${jy}/12/30`,
});
}
}, [jy]);
return [date, setDate];
}

View File

@ -1,26 +1,28 @@
import moment from "moment-jalaali"; import type { Route } from "./+types/ecosystem";
import React from "react"; import React from "react";
import { ProtectedRoute } from "~/components/auth/protected-route"; import { ProtectedRoute } from "~/components/auth/protected-route";
import { DashboardLayout } from "~/components/dashboard/layout"; import { DashboardLayout } from "~/components/dashboard/layout";
import { InfoPanel } from "~/components/ecosystem/info-panel"; import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import { NetworkGraph } from "~/components/ecosystem/network-graph";
import { Card, CardContent } from "~/components/ui/card";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
DialogDescription,
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
} from "~/components/ui/dialog"; } from "~/components/ui/dialog";
import { NetworkGraph } from "~/components/ecosystem/network-graph";
import { InfoPanel } from "~/components/ecosystem/info-panel";
import { useAuth } from "~/contexts/auth-context"; import { useAuth } from "~/contexts/auth-context";
import type { Route } from "./+types/ecosystem"; import moment from "moment-jalaali";
// Get API base URL at module level to avoid process.env access in browser // Get API base URL at module level to avoid process.env access in browser
const API_BASE_URL = const API_BASE_URL =
import.meta.env.VITE_API_URL || "https://inogen-back.pelekan.org/api"; import.meta.env.VITE_API_URL || "https://inogen-back.pelekan.org/api";
// Import the CompanyDetails type // Import the CompanyDetails type
import { Hexagon } from "lucide-react";
import type { CompanyDetails } from "~/components/ecosystem/network-graph"; import type { CompanyDetails } from "~/components/ecosystem/network-graph";
import { formatNumber } from "~/lib/utils";
import { Hexagon } from "lucide-react";
export function meta({}: Route.MetaArgs) { export function meta({}: Route.MetaArgs) {
return [ return [
@ -87,10 +89,7 @@ export default function EcosystemPage() {
<div className="lg:col-span-8 h-full"> <div className="lg:col-span-8 h-full">
<Card className="h-full overflow-hidden bg-transparent border-[#3F415A]"> <Card className="h-full overflow-hidden bg-transparent border-[#3F415A]">
<CardContent className="p-0 h-full bg-transparent"> <CardContent className="p-0 h-full bg-transparent">
<NetworkGraph <NetworkGraph onNodeClick={handleNodeClick} onLoadingChange={handleLoadingChange} />
onNodeClick={handleNodeClick}
onLoadingChange={handleLoadingChange}
/>
</CardContent> </CardContent>
</Card> </Card>
</div> </div>
@ -225,11 +224,9 @@ export default function EcosystemPage() {
</span> </span>
<span className="text-right min-w-1/3"> <span className="text-right min-w-1/3">
<span className="font-persian text-sm font-normal text-right"> <span className="font-persian text-sm font-normal text-right">
{handleValue(field.V)} {handleValue(field.V)}
{field.U && ( {field.U && <span className="mr-1">({field.U})</span>}
<span className="mr-1">({field.U})</span> </span>
)}
</span>
</span> </span>
</div> </div>
))} ))}

View File

@ -1,6 +1,6 @@
export interface CalendarDate { export interface CalendarDate {
start?: string; start: string;
end?: string; end: string;
sinceMonth?: string; sinceMonth?: string;
untilMonth?: string; untilMonth?: string;
} }