feat: compelete page

This commit is contained in:
mehrdad_adabi 2025-08-29 22:02:44 +03:30 committed by Saeed Abadiyan
parent 768fe2226b
commit 20963d0ea3
2 changed files with 500 additions and 438 deletions

View File

@ -121,7 +121,7 @@ export function ProcessInnovationPage() {
direction: "asc", direction: "asc",
}); });
const [selectedProjects, setSelectedProjects] = useState<Set<string>>( const [selectedProjects, setSelectedProjects] = useState<Set<string>>(
new Set(), new Set()
); );
const [detailsDialogOpen, setDetailsDialogOpen] = useState(false); const [detailsDialogOpen, setDetailsDialogOpen] = useState(false);
const [selectedProjectDetails, setSelectedProjectDetails] = const [selectedProjectDetails, setSelectedProjectDetails] =
@ -167,7 +167,7 @@ export function ProcessInnovationPage() {
title: "جلوگیری از توقفات تولید", title: "جلوگیری از توقفات تولید",
value: formatNumber( value: formatNumber(
stats.productionStopsPreventionSum.toFixed?.(1) ?? stats.productionStopsPreventionSum.toFixed?.(1) ??
stats.productionStopsPreventionSum, stats.productionStopsPreventionSum
), ),
description: "تن افزایش یافته", description: "تن افزایش یافته",
icon: <CirclePause />, icon: <CirclePause />,
@ -186,7 +186,7 @@ export function ProcessInnovationPage() {
id: "currency-reduction", id: "currency-reduction",
title: "کاهش ارز بری", title: "کاهش ارز بری",
value: formatNumber( value: formatNumber(
stats.currencyReductionSum.toFixed?.(0) ?? stats.currencyReductionSum, stats.currencyReductionSum.toFixed?.(0) ?? stats.currencyReductionSum
), ),
description: "دلار کاهش یافته", description: "دلار کاهش یافته",
icon: <DollarSign />, icon: <DollarSign />,
@ -197,7 +197,7 @@ export function ProcessInnovationPage() {
title: "کاهش خرابی های پرتکرار", title: "کاهش خرابی های پرتکرار",
value: formatNumber( value: formatNumber(
stats.frequentFailuresReductionSum.toFixed?.(1) ?? stats.frequentFailuresReductionSum.toFixed?.(1) ??
stats.frequentFailuresReductionSum, stats.frequentFailuresReductionSum
), ),
description: "مجموع درصد کاهش خرابی", description: "مجموع درصد کاهش خرابی",
icon: <Wrench />, icon: <Wrench />,
@ -400,7 +400,7 @@ export function ProcessInnovationPage() {
if (typeof payload === "string") { if (typeof payload === "string") {
try { try {
payload = JSON.parse(payload); payload = JSON.parse(payload);
} catch { } } catch {}
} }
const parseNum = (v: unknown): number => { const parseNum = (v: unknown): number => {
@ -418,22 +418,22 @@ export function ProcessInnovationPage() {
totalProjects: parseNum(payload?.count_innovation_process_projects), totalProjects: parseNum(payload?.count_innovation_process_projects),
averageScore: parseNum(payload?.average_project_score), averageScore: parseNum(payload?.average_project_score),
productionStopsPreventionSum: parseNum( productionStopsPreventionSum: parseNum(
payload?.sum_stopping_production, payload?.sum_stopping_production
), ),
bottleneckRemovalCount: parseNum(payload?.count_throat_removal), bottleneckRemovalCount: parseNum(payload?.count_throat_removal),
currencyReductionSum: parseNum(payload?.sum_reduction_value_currency), currencyReductionSum: parseNum(payload?.sum_reduction_value_currency),
frequentFailuresReductionSum: parseNum( frequentFailuresReductionSum: parseNum(
payload?.sum_reducing_breakdowns, payload?.sum_reducing_breakdowns
), ),
percentProductionStops: parseNum( percentProductionStops: parseNum(
payload?.percent_sum_stopping_production, payload?.percent_sum_stopping_production
), ),
percentBottleneckRemoval: parseNum(payload?.percent_throat_removal), percentBottleneckRemoval: parseNum(payload?.percent_throat_removal),
percentCurrencyReduction: parseNum( percentCurrencyReduction: parseNum(
payload?.percent_reduction_value_currency, payload?.percent_reduction_value_currency
), ),
percentFailuresReduction: parseNum( percentFailuresReduction: parseNum(
payload?.percent_reducing_breakdowns, payload?.percent_reducing_breakdowns
), ),
}; };
@ -573,73 +573,73 @@ export function ProcessInnovationPage() {
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
{loading || statsLoading {loading || statsLoading
? // Loading skeleton for stats cards - matching new design ? // Loading skeleton for stats cards - matching new design
Array.from({ length: 4 }).map((_, index) => ( Array.from({ length: 4 }).map((_, index) => (
<Card <Card
key={`skeleton-${index}`} key={`skeleton-${index}`}
className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-2xl overflow-hidden" className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-2xl overflow-hidden"
> >
<CardContent className="p-2"> <CardContent className="p-2">
<div className="flex flex-col justify-between gap-2"> <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"> <div className="flex justify-between items-center border-b-2 mx-4 border-gray-500/20">
<div <div
className="h-6 bg-gray-600 rounded animate-pulse" className="h-6 bg-gray-600 rounded animate-pulse"
style={{ width: "60%" }} style={{ width: "60%" }}
/> />
<div className="p-3 bg-emerald-500/20 rounded-full w-fit"> <div className="p-3 bg-emerald-500/20 rounded-full w-fit">
<div className="w-6 h-6 bg-gray-600 rounded animate-pulse" /> <div className="w-6 h-6 bg-gray-600 rounded animate-pulse" />
</div>
</div>
<div className="flex items-center justify-center flex-col p-1">
<div
className="h-8 bg-gray-600 rounded mb-1 animate-pulse"
style={{ width: "40%" }}
/>
<div
className="h-4 bg-gray-600 rounded animate-pulse"
style={{ width: "80%" }}
/>
</div> </div>
</div> </div>
<div className="flex items-center justify-center flex-col p-1"> </CardContent>
<div </Card>
className="h-8 bg-gray-600 rounded mb-1 animate-pulse" ))
style={{ width: "40%" }}
/>
<div
className="h-4 bg-gray-600 rounded animate-pulse"
style={{ width: "80%" }}
/>
</div>
</div>
</CardContent>
</Card>
))
: statsCards.map((card) => ( : statsCards.map((card) => (
<Card <Card
key={card.id} key={card.id}
className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50" className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50"
> >
<CardContent className="p-2"> <CardContent className="p-2">
<div className="flex flex-col justify-between gap-2"> <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"> <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 className="text-lg font-bold text-white font-persian">
{card.title} {card.title}
</h3> </h3>
<div <div
className={`p-3 gird placeitems-center rounded-full w-fit `} className={`p-3 gird placeitems-center rounded-full w-fit `}
> >
{card.icon} {card.icon}
</div>
</div>
<div className="flex items-center justify-center flex-col p-1">
<p
className={`text-3xl font-bold ${card.color} mb-1`}
>
{card.value}
</p>
<p className="text-sm text-gray-300 font-persian">
{card.description}
</p>
</div> </div>
</div> </div>
<div className="flex items-center justify-center flex-col p-1"> </CardContent>
<p </Card>
className={`text-3xl font-bold ${card.color} mb-1`} ))}
>
{card.value}
</p>
<p className="text-sm text-gray-300 font-persian">
{card.description}
</p>
</div>
</div>
</CardContent>
</Card>
))}
</div> </div>
</div> </div>
{/* Process Impacts Chart */} {/* Process Impacts Chart */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-2xl w-full overflow-hidden"> <Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-2xl w-full overflow-hidden">
<CardContent > <CardContent>
<CustomBarChart <CustomBarChart
title="تاثیرات فرآیندی به صورت درصد مقایسه ای" title="تاثیرات فرآیندی به صورت درصد مقایسه ای"
loading={statsLoading} loading={statsLoading}
@ -840,8 +840,8 @@ export function ProcessInnovationPage() {
<div className="font-bold"> <div className="font-bold">
{formatNumber( {formatNumber(
((stats.averageScore ?? 0) as number).toFixed?.(1) ?? ((stats.averageScore ?? 0) as number).toFixed?.(1) ??
stats.averageScore ?? stats.averageScore ??
0, 0
)} )}
</div> </div>
</div> </div>
@ -881,9 +881,9 @@ export function ProcessInnovationPage() {
<span className="text-white font-bold font-persian"> <span className="text-white font-bold font-persian">
{selectedProjectDetails?.start_date {selectedProjectDetails?.start_date
? moment( ? moment(
selectedProjectDetails?.start_date, selectedProjectDetails?.start_date,
"YYYY-MM-DD", "YYYY-MM-DD"
).format("YYYY/MM/DD") ).format("YYYY/MM/DD")
: "-"} : "-"}
</span> </span>
</div> </div>
@ -896,9 +896,9 @@ export function ProcessInnovationPage() {
<span className="text-white font-bold font-persian"> <span className="text-white font-bold font-persian">
{selectedProjectDetails?.done_date {selectedProjectDetails?.done_date
? moment( ? moment(
selectedProjectDetails?.done_date, selectedProjectDetails?.done_date,
"YYYY-MM-DD", "YYYY-MM-DD"
).format("YYYY/MM/DD") ).format("YYYY/MM/DD")
: "-"} : "-"}
</span> </span>
</div> </div>
@ -913,9 +913,9 @@ export function ProcessInnovationPage() {
Number( Number(
selectedProjectDetails?.approved_budget.replaceAll( selectedProjectDetails?.approved_budget.replaceAll(
",", ",",
"", ""
), )
), )
) || "-"} ) || "-"}
</span> </span>
</div> </div>