feat: contineu developing page innterbal-innovation
This commit is contained in:
parent
49f018e56f
commit
73f960b56a
|
|
@ -1168,26 +1168,6 @@ export function GreenInnovationPage() {
|
|||
{selectedProjectDetails?.observer || "-"}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* <div className="flex items-center justify-between">
|
||||
<h4 className="font-medium text-gray-300 font-persian mb-2 flex items-center gap-1">
|
||||
<Radar className="h-4 text-green-500" />
|
||||
حوزه کاری :
|
||||
</h4>
|
||||
<span className="text-white font-bold font-persian">
|
||||
{selectedProjectDetails?.observer || "-"}
|
||||
</span>
|
||||
</div> */}
|
||||
|
||||
{/* <div className="flex items-center justify-between">
|
||||
<h4 className="font-medium text-gray-300 font-persian mb-2 flex items-center gap-1">
|
||||
<Cog className="h-4 text-green-500" />
|
||||
صنعت :
|
||||
</h4>
|
||||
<span className="text-white font-bold font-persian">
|
||||
{selectedProjectDetails?.observer || "-"}
|
||||
</span>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
|
|
|
|||
|
|
@ -23,28 +23,27 @@ import apiService from "~/lib/api";
|
|||
import toast from "react-hot-toast";
|
||||
import {
|
||||
FilterIcon,
|
||||
Key,
|
||||
Sparkle,
|
||||
Zap,
|
||||
Flame,
|
||||
Building2,
|
||||
PickaxeIcon,
|
||||
UsersIcon,
|
||||
UserIcon,
|
||||
RefreshCw,
|
||||
ChevronUp,
|
||||
ChevronDown,
|
||||
Handshake,
|
||||
CodeXml,
|
||||
SquareUser,
|
||||
Users,
|
||||
User,
|
||||
} from "lucide-react";
|
||||
import DashboardLayout from "../layout";
|
||||
import { LineChart, CartesianGrid, Legend, Line, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis, Customized } from "recharts";
|
||||
|
||||
moment.loadPersian({ usePersianDigits: true });
|
||||
interface GreenInnovationData {
|
||||
WorkflowID: string;
|
||||
|
||||
interface innovationBuiltInDate {
|
||||
WorkflowID: number;
|
||||
approved_budget: string;
|
||||
done_date: string | null;
|
||||
observer: string;
|
||||
project_description: string;
|
||||
project_id: string;
|
||||
project_id: number | null;
|
||||
project_no: string;
|
||||
project_rating: string;
|
||||
project_status: string;
|
||||
|
|
@ -52,6 +51,25 @@ interface GreenInnovationData {
|
|||
title: string;
|
||||
}
|
||||
|
||||
interface DialogInfo {
|
||||
WorkflowID: number
|
||||
collaboration_model: string; // مشارکت استراتژیک
|
||||
complexity_level: string; // فناوری سطح متوسط
|
||||
developer_team_role: string; // نظارت
|
||||
number_employees_involved: number | null; // ممکن است null باشد
|
||||
participants_full_name: string; // مریم احمدی
|
||||
project_description: string; // توضیحات پروژه
|
||||
project_id: string; // "20922"
|
||||
project_no: string; // "13"
|
||||
project_rating: string; // "68" (اگر میخوای عدد باشد: number)
|
||||
project_status: string; // پروپوزال
|
||||
role_company_staff: string | null; // ممکن است null باشد
|
||||
technology_maturity_level: string; // مرحله بلوغ
|
||||
title: string; // عنوان پروژه
|
||||
technology_params?: Array<TechnologyParameter>
|
||||
}
|
||||
|
||||
|
||||
interface SortConfig {
|
||||
field: string;
|
||||
direction: "asc" | "desc";
|
||||
|
|
@ -112,28 +130,11 @@ interface InnovationStats {
|
|||
resolved_bottleneck_count: number;
|
||||
}
|
||||
|
||||
interface Params {
|
||||
icon: any;
|
||||
label: string;
|
||||
value: number;
|
||||
suffix: string;
|
||||
percent: number;
|
||||
}
|
||||
interface RecycleParams {
|
||||
water: Params;
|
||||
food: Params;
|
||||
power: Params;
|
||||
oil: Params;
|
||||
}
|
||||
|
||||
interface stateCounter {
|
||||
totalProjects: number;
|
||||
}
|
||||
|
||||
interface ChartDataItem {
|
||||
name: string;
|
||||
pv: any; // actual value
|
||||
amt: number; // max value or target
|
||||
interface TechnologyParameter {
|
||||
WorkflowID: number;
|
||||
domestic_technology_parameter_value: string;
|
||||
foreign_technology_parameter_value: string;
|
||||
technology_parameter_title: string;
|
||||
}
|
||||
|
||||
enum projectStatus {
|
||||
|
|
@ -164,8 +165,16 @@ const columns = [
|
|||
{ key: "details", label: "جزئیات پروژه", sortable: false, width: "140px" },
|
||||
];
|
||||
|
||||
const data = [
|
||||
{ name: 'افول', value: 10 },
|
||||
{ name: 'رشد', value: 20 },
|
||||
{ name: 'بلوغ', value: 15 },
|
||||
{ name: 'معرفی', value: 25 },
|
||||
|
||||
];
|
||||
|
||||
export function InnovationBuiltInsidePage() {
|
||||
const [projects, setProjects] = useState<GreenInnovationData[]>([]);
|
||||
const [projects, setProjects] = useState<innovationBuiltInDate[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [loadingMore, setLoadingMore] = useState(false);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
|
|
@ -174,7 +183,7 @@ export function InnovationBuiltInsidePage() {
|
|||
const [totalCount, setTotalCount] = useState(0);
|
||||
const [actualTotalCount, setActualTotalCount] = useState(0);
|
||||
const [statsLoading, setStatsLoading] = useState(false);
|
||||
const [stats, setStats] = useState<stateCounter>();
|
||||
// const [stats, setStats] = useState<stateCounter>();
|
||||
const [sortConfig, setSortConfig] = useState<SortConfig>({
|
||||
field: "start_date",
|
||||
direction: "asc",
|
||||
|
|
@ -185,11 +194,9 @@ export function InnovationBuiltInsidePage() {
|
|||
);
|
||||
const [detailsDialogOpen, setDetailsDialogOpen] = useState(false);
|
||||
const [selectedProjectDetails, setSelectedProjectDetails] =
|
||||
useState<GreenInnovationData | null>(null);
|
||||
useState<DialogInfo>();
|
||||
|
||||
const [innovationMetric, setInnovationMetric] = useState({
|
||||
|
||||
})
|
||||
|
||||
const [sustainabilityStats, setSustainabilityStats] = useState<StatsCard>({
|
||||
currencySaving: {
|
||||
|
|
@ -242,6 +249,8 @@ export function InnovationBuiltInsidePage() {
|
|||
})
|
||||
|
||||
|
||||
const [showDialogItems, setShowDialogItems] = useState<boolean>(false)
|
||||
|
||||
const [countOfHighTech, setCountOfHighTech] = useState(0)
|
||||
|
||||
const observerRef = useRef<HTMLDivElement>(null);
|
||||
|
|
@ -257,11 +266,20 @@ export function InnovationBuiltInsidePage() {
|
|||
setSelectedProjects(newSelected);
|
||||
};
|
||||
|
||||
const handleProjectDetails = (project: GreenInnovationData) => {
|
||||
setSelectedProjectDetails(project);
|
||||
const handleProjectDetails = async (project: DialogInfo) => {
|
||||
setShowDialogItems(true)
|
||||
setDetailsDialogOpen(true);
|
||||
|
||||
setSelectedProjectDetails(project);
|
||||
await fetchDialogTbl(project.WorkflowID)
|
||||
setTimeout(() => {
|
||||
setShowDialogItems(false)
|
||||
calculateProgressBar(+project.project_rating)
|
||||
}, 500);
|
||||
};
|
||||
|
||||
|
||||
|
||||
const formatNumber = (value: string | number) => {
|
||||
if (!value) return "0";
|
||||
const numericValue = typeof value === "string" ? parseFloat(value) : value;
|
||||
|
|
@ -292,10 +310,13 @@ export function InnovationBuiltInsidePage() {
|
|||
"project_status",
|
||||
"project_rating",
|
||||
"project_description",
|
||||
"start_date",
|
||||
"done_date",
|
||||
"approved_budget",
|
||||
"observer"
|
||||
"complexity_level",
|
||||
"collaboration_model",
|
||||
"developer_team_role",
|
||||
"role_company_staff",
|
||||
"number_employees_involved",
|
||||
"participants_full_name",
|
||||
"technology_maturity_level"
|
||||
],
|
||||
Sorts: [[sortConfig.field, sortConfig.direction]],
|
||||
Conditions: [["type_of_innovation", "=", "نوآوری ساخت داخل"]],
|
||||
|
|
@ -360,6 +381,43 @@ export function InnovationBuiltInsidePage() {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
const fetchDialogTbl = async (tblId: number) => {
|
||||
try {
|
||||
const response = await apiService.select({
|
||||
ProcessName: "technology_parameter",
|
||||
OutputFields: [
|
||||
"technology_parameter_title",
|
||||
"domestic_technology_parameter_value",
|
||||
"foreign_technology_parameter_value"
|
||||
],
|
||||
Conditions: [["project_id", "=", tblId]],
|
||||
});
|
||||
if (response.state === 0) {
|
||||
const dataString = response.data;
|
||||
if (dataString && typeof dataString === "string") {
|
||||
const parsedData = JSON.parse(dataString);
|
||||
setSelectedProjectDetails((prev: any) => ({
|
||||
...prev,
|
||||
technology_params: parsedData
|
||||
}));
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching projects:", error);
|
||||
toast.error("خطا در دریافت اطلاعات پروژهها");
|
||||
}
|
||||
};
|
||||
|
||||
const calculateProgressBar = (val: number) => {
|
||||
const pointer = document.getElementsByClassName('progressBarPointer')[0] as HTMLElement;
|
||||
if (!pointer) return;
|
||||
|
||||
const leftValue = val !== 0 ? `calc(${val}% - 100px)` : `calc(0% - 40px)`;
|
||||
|
||||
pointer.style.left = leftValue;
|
||||
};
|
||||
|
||||
const loadMore = useCallback(() => {
|
||||
if (!loadingMore && hasMore && !loading) {
|
||||
setCurrentPage((prev) => prev + 1);
|
||||
|
|
@ -368,7 +426,6 @@ export function InnovationBuiltInsidePage() {
|
|||
|
||||
useEffect(() => {
|
||||
fetchProjects(true);
|
||||
fetchTotalCount();
|
||||
fetchStats();
|
||||
}, [sortConfig, selectedProjects]);
|
||||
|
||||
|
|
@ -418,34 +475,7 @@ export function InnovationBuiltInsidePage() {
|
|||
setHasMore(true);
|
||||
};
|
||||
|
||||
const fetchTotalCount = async () => {
|
||||
try {
|
||||
const response = await apiService.select({
|
||||
ProcessName: "project",
|
||||
OutputFields: ["count(project_no)"],
|
||||
Conditions: [["type_of_innovation", "=", "نوآوری سبز"]],
|
||||
});
|
||||
if (response.state === 0) {
|
||||
const dataString = response.data;
|
||||
if (dataString && typeof dataString === "string") {
|
||||
try {
|
||||
const parsedData = JSON.parse(dataString);
|
||||
if (Array.isArray(parsedData) && parsedData[0]) {
|
||||
const count = parsedData[0].project_no_count || 0;
|
||||
// Keep stats in sync if backend stats not yet loaded
|
||||
setStats((prev) => ({ ...prev, totalProjects: count }));
|
||||
}
|
||||
} catch (parseError) {
|
||||
console.error("Error parsing count data:", parseError);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching total count:", error);
|
||||
}
|
||||
};
|
||||
|
||||
// Fetch aggregated stats from backend call API (innovation_process_function)
|
||||
const fetchStats = async () => {
|
||||
try {
|
||||
setStatsLoading(true);
|
||||
|
|
@ -561,8 +591,8 @@ export function InnovationBuiltInsidePage() {
|
|||
setCountOfHighTech(normalized.countOfHighTech)
|
||||
};
|
||||
|
||||
const renderCellContent = (item: GreenInnovationData, column: any) => {
|
||||
const value = item[column.key as keyof GreenInnovationData];
|
||||
const renderCellContent = (item: innovationBuiltInDate, column: any) => {
|
||||
const value = item[column.key as keyof innovationBuiltInDate];
|
||||
|
||||
switch (column.key) {
|
||||
case "select":
|
||||
|
|
@ -654,12 +684,6 @@ export function InnovationBuiltInsidePage() {
|
|||
return el;
|
||||
};
|
||||
|
||||
// const [chartData, setChartData] = useState<Array<ChartDataItem>>([
|
||||
// { name: recycleParams.water.label, pv: 70, amt: 80 },
|
||||
// { name: recycleParams.power.label, pv: 45, amt: 60 },
|
||||
// { name: recycleParams.oil.label, pv: 90, amt: 75 },
|
||||
// { name: recycleParams.food.label, pv: 30, amt: 50 },
|
||||
// ]);
|
||||
|
||||
return (
|
||||
<DashboardLayout title="نوآوری ساخت داخل">
|
||||
|
|
@ -807,8 +831,6 @@ export function InnovationBuiltInsidePage() {
|
|||
</Card>
|
||||
}
|
||||
|
||||
|
||||
|
||||
{
|
||||
loading ? <div className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] h-30 rounded-lg backdrop-blur-sm border border-gray-700/50 animate-pulse mt-4">
|
||||
<div className="h-full flex flex-row justify-between p-6 items-center w-4/5 m-auto">
|
||||
|
|
@ -959,110 +981,283 @@ export function InnovationBuiltInsidePage() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Project Details Dialog */}
|
||||
<Dialog open={detailsDialogOpen} onOpenChange={setDetailsDialogOpen}>
|
||||
<DialogContent className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] max-w-4xl overflow-y-auto">
|
||||
<DialogContent className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] max-w-5xl overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-white mr-4 border-b-2 border-gray-600 pb-4 font-persian text-right">
|
||||
شرح پروژه
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="space-y-4 flex justify-between text-right px-6">
|
||||
{/* Project Description */}
|
||||
<div className="flex-[4] border-l-2 border-gray-600">
|
||||
<div className="flex justify-between text-right px-4">
|
||||
<div className="flex-[4] border-l-2 border-gray-600 pl-8">
|
||||
|
||||
{
|
||||
showDialogItems ? <div className="animate-pulse flex flex-col gap-2">
|
||||
<div className="flex flex-col gap-2 mt-2">
|
||||
<div className="h-4 w-full bg-gray-600 rounded"></div>
|
||||
<div className="h-4 w-5/6 bg-gray-600 rounded"></div>
|
||||
<div className="h-4 w-11/12 bg-gray-600 rounded"></div>
|
||||
</div>
|
||||
</div> : <div>
|
||||
<h2 className="font-bold">{selectedProjectDetails?.title}</h2>
|
||||
<p className="text-gray-300 font-persian px-1 mt-2">
|
||||
<p className="text-gray-300 font-persian mt-2 text-justify">
|
||||
{selectedProjectDetails?.project_description || "-"}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
<h2 className="font-bold my-6">دانش فنی محصول جدید</h2>
|
||||
{
|
||||
showDialogItems ? <div className="newProductTechKnowledge flex flex-col gap-4 h-max w-full animate-pulse">
|
||||
<div className="w-max relative">
|
||||
<div className="range flex flex-row-reverse rounded-xl overflow-hidden justify-center">
|
||||
<div className="bg-gray-500 w-28 h-10 p-4 text-center flex items-center justify-center">
|
||||
</div>
|
||||
<div className="bg-gray-400 w-28 h-10 p-4 text-center flex items-center justify-center">
|
||||
</div>
|
||||
<div className="bg-gray-300 w-28 h-10 p-4 text-center flex items-center justify-center">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="progressBarPointer absolute z-[200] top-0.5 left-0.5">
|
||||
<div className="flex flex-col justify-center items-center">
|
||||
<span className="block w-0.5 h-14 bg-gray-400"></span>
|
||||
<span className="text-gray-400 border border-gray-400 p-1 px-2 text-xs rounded-lg">
|
||||
سطح تکنولوژی
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> : <div className="newProductTechKnowledge flex flex-col gap-4 h-max w-full ">
|
||||
<div className="w-max relative transition-all duration-300">
|
||||
<div className="range flex flex-row-reverse rounded-xl overflow-hidden justify-center">
|
||||
<div className="bg-emerald-700 w-28 h-10 p-4 text-center text-sm flex items-center justify-center">
|
||||
<span className="text-gray-700">سطح پایین</span>
|
||||
</div>
|
||||
<div className="bg-emerald-600 w-28 h-10 p-4 text-center text-sm flex items-center justify-center">
|
||||
<span className="text-gray-700">سطح متوسط</span>
|
||||
</div>
|
||||
<div className="bg-emerald-400 w-28 h-10 p-4 text-center text-sm flex items-center justify-center">
|
||||
<span className="text-gray-700">سطح بالا</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className='progressBarPointer absolute z-[200] top-0.5 transition-all duration-300'>
|
||||
<div className="flex flex-col justify-center items-center">
|
||||
<span className="block w-0.5 h-14 bg-white"></span>
|
||||
<span className="text-white border border-white p-1 px-2 text-xs rounded-lg"> سطح تکنولوژی</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div className="flex flex-col gap-5 mt-20">
|
||||
<h2 className="font-bold">مشارکت در پروژه</h2>
|
||||
{
|
||||
showDialogItems ? <div className="space-y-3">
|
||||
{[...Array(4)].map((_, i) => (
|
||||
<div key={i} className="flex flex-row gap-2 items-center">
|
||||
<div className="h-5 w-5 bg-gray-500 rounded-full"></div>
|
||||
<div className="flex flex-row justify-between w-full gap-2">
|
||||
<div className="h-4 w-24 bg-gray-600 rounded"></div>
|
||||
<div className="h-4 w-20 bg-gray-500 rounded"></div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div> : <div className="flex flex-col gap-5">
|
||||
<div className="content flex flex-col gap-3 w-5/6">
|
||||
<div className="flex flex-row gap-2 w-full">
|
||||
<Handshake className="text-emerald-500 w-5" />
|
||||
<div className="flex flex-row justify-between w-full">
|
||||
<span>مدل همکاری:</span>
|
||||
<span>{selectedProjectDetails?.collaboration_model}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row gap-2 w-full">
|
||||
<CodeXml className="text-emerald-500 w-5" />
|
||||
<div className="flex flex-row justify-between w-full">
|
||||
<span>نقش تیم توسعه دهنده:</span>
|
||||
<span>{selectedProjectDetails?.developer_team_role}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row gap-2 w-full">
|
||||
<SquareUser className="text-emerald-500 w-5" />
|
||||
<div className="flex flex-row justify-between w-full">
|
||||
<span>نقش کارکنان شرکت: </span>
|
||||
<span>نظارت کننده</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row gap-2 w-full">
|
||||
<Users className="text-emerald-500 w-5" />
|
||||
<div className="flex flex-row justify-between w-full">
|
||||
<span>تعداد کارکنان درگیر: </span>
|
||||
<span className="persian-font">{selectedProjectDetails?.number_employees_involved ?? 0}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row gap-2 w-full">
|
||||
<User className="text-emerald-500 w-5" />
|
||||
<div className="flex flex-col justify-between w-full gap-1">
|
||||
<span>لیست کارکنان : </span>
|
||||
<span className="pr-1">{selectedProjectDetails?.participants_full_name}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Project Details */}
|
||||
<div className="flex flex-[3] gap-2 flex-col px-4">
|
||||
<div className="font-bold text-right ">جزئیات پروژه</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<h4 className="font-medium text-gray-300 font-persian mb-2 flex items-center gap-1">
|
||||
<Building2 className="h-4 text-green-500" />
|
||||
زمان شروع:
|
||||
</h4>
|
||||
<span className="text-white font-bold font-persian">
|
||||
{selectedProjectDetails?.start_date
|
||||
? moment(
|
||||
selectedProjectDetails?.start_date,
|
||||
"YYYY-MM-DD"
|
||||
).format("YYYY/MM/DD")
|
||||
: "-"}
|
||||
</span>
|
||||
<div className="px-4 pl-0 flex flex-col gap-4 w-1/2">
|
||||
{
|
||||
showDialogItems ? <div className="flex flex-col gap-2 animate-pulse">
|
||||
{[...Array(5)].map((_, rowIndex) => (
|
||||
<div key={`skeleton-${rowIndex}`}>
|
||||
<div className="h-6 bg-gray-700 rounded"></div>
|
||||
</div>
|
||||
))}
|
||||
</div> : <div className="tbl rounded-xl overflow-hidden">
|
||||
<div className="grid grid-cols-3 bg-[#3F415A] text-white">
|
||||
<span className="text-md text-center p-3">شاخص مقایسه با نمونه خارجی</span>
|
||||
<span className="text-md text-center p-3">نمونه داخلی</span>
|
||||
<span className="text-md text-center p-3">نمونه خارجی</span>
|
||||
</div>
|
||||
<div className="flex flex-col divide-y divide-gray-600 overflow-auto max-h-[6rem]">
|
||||
{
|
||||
selectedProjectDetails?.technology_params?.map((el, index) => {
|
||||
return <div className="grid grid-cols-3 py-3" key={`technology-${index}-${el.WorkflowID}`}>
|
||||
<span className="text-center">{el.technology_parameter_title}</span>
|
||||
<div className="flex flex-row items-center gap-1 justify-center">
|
||||
<span>{el.domestic_technology_parameter_value}</span>
|
||||
<span className="text-sm text-gray-400">میلیون لیتر</span>
|
||||
</div>
|
||||
<div className="flex flex-row items-center gap-1 justify-center">
|
||||
<span>{el.foreign_technology_parameter_value}</span>
|
||||
<span className="text-sm text-gray-400">میلیون لیتر</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<h4 className="font-medium text-gray-300 font-persian mb-2 flex items-center gap-1">
|
||||
<PickaxeIcon className="h-4 text-green-500" />
|
||||
زمان پایان:
|
||||
</h4>
|
||||
<span className="text-white font-bold font-persian">
|
||||
{selectedProjectDetails?.done_date
|
||||
? moment(
|
||||
selectedProjectDetails?.done_date,
|
||||
"YYYY-MM-DD"
|
||||
).format("YYYY/MM/DD")
|
||||
: "-"}
|
||||
</span>
|
||||
})
|
||||
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div style={{ width: '100%', height: 400 }}>
|
||||
{
|
||||
showDialogItems ? <div className="relative h-96 w-full bg-gray-700 rounded-lg overflow-hidden animate-pulse">
|
||||
{[...Array(4)].map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="absolute left-0 w-full h-1 bg-gray-600 rounded"
|
||||
style={{
|
||||
top: `${20 + i * 20}%`,
|
||||
transform: `scaleX(${0.8 + i * 0.05})`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
{[...Array(5)].map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="absolute bg-gray-500 rounded-full"
|
||||
style={{
|
||||
width: '10px',
|
||||
height: '10px',
|
||||
left: `${10 + i * 18}%`,
|
||||
top: `${30 + (i % 2) * 20}%`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div> : <ResponsiveContainer width="100%" height={420}>
|
||||
<LineChart
|
||||
data={data}
|
||||
margin={{ top: 20, right: 20, left: 20, bottom: 80 }}
|
||||
>
|
||||
<XAxis
|
||||
dataKey="name"
|
||||
interval={0}
|
||||
padding={{ right: 10 }}
|
||||
axisLine={false}
|
||||
tick={{ fill: "white" }}
|
||||
/>
|
||||
|
||||
<Line type="monotone" dataKey="value" stroke="#ff4d6d" strokeWidth={2} dot={false} />
|
||||
|
||||
<ReferenceLine x="بلوغ" stroke="#00bc7c" strokeWidth={2} />
|
||||
|
||||
<Customized
|
||||
component={(props: any) => {
|
||||
const { xAxisMap, width, height } = props;
|
||||
const xAxes = Object.values(xAxisMap || {});
|
||||
if (!xAxes.length) return null;
|
||||
|
||||
const xAxis: any = xAxes[0];
|
||||
const ticks = xAxis?.ticks || [];
|
||||
const tick = ticks.find((t: any) => {
|
||||
return t && (t.value === "بلوغ" || (t.payload && t.payload.value === "بلوغ"));
|
||||
});
|
||||
|
||||
const x = (tick && tick.coordinate) ?? width / 2 + 80
|
||||
|
||||
const rectWidth = 140;
|
||||
const rectHeight = 28;
|
||||
const rectX = x - rectWidth / 2;
|
||||
|
||||
const axisHeight = xAxis?.height ?? 40;
|
||||
const rectY = (height - axisHeight) - 30;
|
||||
|
||||
return (
|
||||
<g>
|
||||
<rect
|
||||
x={rectX}
|
||||
y={rectY}
|
||||
width={rectWidth}
|
||||
height={rectHeight}
|
||||
fill="none"
|
||||
stroke="#00bc7c"
|
||||
strokeWidth={2}
|
||||
rx={6}
|
||||
/>
|
||||
<text
|
||||
x={x}
|
||||
y={rectY + rectHeight / 2}
|
||||
fill="white"
|
||||
fontSize={12}
|
||||
textAnchor="middle"
|
||||
alignmentBaseline="middle"
|
||||
>
|
||||
سطح بلوغ تکنولوژی
|
||||
</text>
|
||||
</g>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<h4 className="font-medium text-gray-300 font-persian mb-2 flex items-center gap-1">
|
||||
<UsersIcon className="h-4 text-green-500" />
|
||||
هزینه برآورد شده:
|
||||
</h4>
|
||||
<span className="text-white font-bold font-persian">
|
||||
{formatNumber(
|
||||
Number(
|
||||
selectedProjectDetails?.approved_budget.replaceAll(
|
||||
",",
|
||||
""
|
||||
)
|
||||
)
|
||||
) || "-"}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<h4 className="font-medium text-gray-300 font-persian mb-2 flex items-center gap-1">
|
||||
<UserIcon className="h-4 text-green-500" />
|
||||
نفر مرتبط:
|
||||
</h4>
|
||||
<span className="text-white font-bold font-persian">
|
||||
{selectedProjectDetails?.observer || "-"}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* <div className="flex items-center justify-between">
|
||||
<h4 className="font-medium text-gray-300 font-persian mb-2 flex items-center gap-1">
|
||||
<Radar className="h-4 text-green-500" />
|
||||
حوزه کاری :
|
||||
</h4>
|
||||
<span className="text-white font-bold font-persian">
|
||||
{selectedProjectDetails?.observer || "-"}
|
||||
</span>
|
||||
</div> */}
|
||||
|
||||
{/* <div className="flex items-center justify-between">
|
||||
<h4 className="font-medium text-gray-300 font-persian mb-2 flex items-center gap-1">
|
||||
<Cog className="h-4 text-green-500" />
|
||||
صنعت :
|
||||
</h4>
|
||||
<span className="text-white font-bold font-persian">
|
||||
{selectedProjectDetails?.observer || "-"}
|
||||
</span>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</DashboardLayout>
|
||||
</DashboardLayout >
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user