ideas #15
|
|
@ -29,7 +29,7 @@ import {
|
||||||
} from "~/components/ui/chart";
|
} from "~/components/ui/chart";
|
||||||
import { BarChart, Bar, XAxis, YAxis, ResponsiveContainer, CartesianGrid, LabelList, Cell, RadialBarChart, PolarGrid, RadialBar, PolarRadiusAxis } from "recharts";
|
import { BarChart, Bar, XAxis, YAxis, ResponsiveContainer, CartesianGrid, LabelList, Cell, RadialBarChart, PolarGrid, RadialBar, PolarRadiusAxis } from "recharts";
|
||||||
import { BaseCard } from "~/components/ui/base-card";
|
import { BaseCard } from "~/components/ui/base-card";
|
||||||
import { Label } from "~/components/ui/label";
|
import { Label } from "recharts"
|
||||||
import { MetricCard } from "~/components/ui/metric-card";
|
import { MetricCard } from "~/components/ui/metric-card";
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -605,9 +605,34 @@ export function ManageIdeasTechPage() {
|
||||||
const VerticalBarChart = () => {
|
const VerticalBarChart = () => {
|
||||||
if (loadingChart) {
|
if (loadingChart) {
|
||||||
return (
|
return (
|
||||||
<div className="p-6">
|
<div className="p-6 space-y-4">
|
||||||
<div className="bg-gray-600 rounded animate-pulse w-48 mx-auto"></div>
|
{/* Chart title skeleton */}
|
||||||
<div className="h-40 bg-gray-700 rounded animate-pulse"></div>
|
<div className="h-5 bg-gray-600 rounded animate-pulse w-32 mx-auto"></div>
|
||||||
|
|
||||||
|
{/* Chart area skeleton */}
|
||||||
|
<div className="relative h-48 bg-gradient-to-t from-gray-700/30 to-transparent rounded p-4">
|
||||||
|
{/* Y-axis labels */}
|
||||||
|
<div className="absolute left-2 top-4 space-y-6">
|
||||||
|
{Array.from({ length: 4 }).map((_, i) => (
|
||||||
|
<div key={i} className="h-3 bg-gray-600 rounded animate-pulse w-6"></div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bars skeleton */}
|
||||||
|
<div className="flex items-end justify-center gap-4 h-full pt-4 pb-8 ml-8">
|
||||||
|
{Array.from({ length: 4 }).map((_, i) => (
|
||||||
|
<div key={i} className="flex flex-col items-center gap-2">
|
||||||
|
{/* Bar */}
|
||||||
|
<div
|
||||||
|
className="bg-gray-600 rounded-t animate-pulse w-12"
|
||||||
|
style={{ height: `${Math.random() * 60 + 40}%` }}
|
||||||
|
></div>
|
||||||
|
{/* X-axis label */}
|
||||||
|
<div className="h-3 bg-gray-600 rounded animate-pulse w-16"></div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -921,6 +946,23 @@ style: { textAnchor: "middle" },
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
<div className="col-span-1 col-start-2 row-start-2 flex flex-col-reverse justify-end gap-2 row-span-1">
|
<div className="col-span-1 col-start-2 row-start-2 flex flex-col-reverse justify-end gap-2 row-span-1">
|
||||||
<BaseCard title="ایدههای فناوری و نوآوری">
|
<BaseCard title="ایدههای فناوری و نوآوری">
|
||||||
|
{loadingStats ? (
|
||||||
|
<div className="flex items-center gap-2 justify-center flex-row-reverse">
|
||||||
|
<div className="w-[6rem] h-[6rem] bg-gray-600 rounded-full animate-pulse"></div>
|
||||||
|
<div className="font-bold font-persian text-center">
|
||||||
|
<div className="flex flex-col justify-between items-center gap-2">
|
||||||
|
<div className="flex items-center gap-1 text-base">
|
||||||
|
<div className="h-4 bg-gray-600 rounded animate-pulse w-16"></div>
|
||||||
|
<div className="h-5 bg-gray-600 rounded animate-pulse w-8"></div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1 text-base">
|
||||||
|
<div className="h-4 bg-gray-600 rounded animate-pulse w-20"></div>
|
||||||
|
<div className="h-5 bg-gray-600 rounded animate-pulse w-8"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
<div className="flex items-center gap-2 justify-center flex-row-reverse">
|
<div className="flex items-center gap-2 justify-center flex-row-reverse">
|
||||||
<ChartContainer
|
<ChartContainer
|
||||||
config={chartConfig}
|
config={chartConfig}
|
||||||
|
|
@ -1057,14 +1099,31 @@ style: { textAnchor: "middle" },
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
|
|
||||||
<MetricCard
|
{loadingStats ? (
|
||||||
title="درآمد افزایش یافته"
|
<div className="bg-gradient-to-br from-[#444a64] to-[#252942] rounded-xl p-4 border border-[#3F415A]">
|
||||||
value={statsData?.increased_revenue_from_ideas?.replaceAll("," , "") || "0"}
|
<div className="space-y-3">
|
||||||
percentValue={statsData?.increased_revenue_from_ideas_percent}
|
<div className="h-4 bg-gray-600 rounded animate-pulse w-24"></div>
|
||||||
percentLabel="درصد به کل درآمد"
|
<div className="space-y-2">
|
||||||
/>
|
<div className="h-8 bg-gray-600 rounded animate-pulse w-16"></div>
|
||||||
|
<div className="h-3 bg-gray-600 rounded animate-pulse w-20"></div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="h-4 bg-gray-600 rounded animate-pulse w-6"></div>
|
||||||
|
<div className="h-3 bg-gray-600 rounded animate-pulse w-16"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<MetricCard
|
||||||
|
title="درآمد افزایش یافته"
|
||||||
|
value={statsData?.increased_revenue_from_ideas?.replaceAll("," , "") || "0"}
|
||||||
|
percentValue={statsData?.increased_revenue_from_ideas_percent}
|
||||||
|
percentLabel="درصد به کل درآمد"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,7 @@ export function InfoPanel({ selectedCompany }: InfoPanelProps) {
|
||||||
{Array.from({ length: 4 }).map((_, i) => (
|
{Array.from({ length: 4 }).map((_, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className="absolute w-2 h-2 bg-green-400 rounded-full animate-pulse"
|
className="absolute w-2 h-2 bg-pr-green rounded-full animate-pulse"
|
||||||
style={{
|
style={{
|
||||||
left: `${20 + i * 25}%`,
|
left: `${20 + i * 25}%`,
|
||||||
top: `${30 + Math.random() * 40}%`,
|
top: `${30 + Math.random() * 40}%`,
|
||||||
|
|
@ -287,7 +287,7 @@ export function InfoPanel({ selectedCompany }: InfoPanelProps) {
|
||||||
{/* Actor Count Skeleton */}
|
{/* Actor Count Skeleton */}
|
||||||
<CardHeader className="text-center pt-0 pb-4">
|
<CardHeader className="text-center pt-0 pb-4">
|
||||||
<div className="w-36 h-5 rounded animate-pulse mx-auto mb-2"></div>
|
<div className="w-36 h-5 rounded animate-pulse mx-auto mb-2"></div>
|
||||||
<div className="w-16 h-8 bg-green-400 bg-opacity-30 rounded animate-pulse mx-auto"></div>
|
<div className="w-16 h-8 bg-pr-green bg-opacity-30 rounded animate-pulse mx-auto"></div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
{/* Bar Chart Skeleton */}
|
{/* Bar Chart Skeleton */}
|
||||||
|
|
@ -362,7 +362,7 @@ export function InfoPanel({ selectedCompany }: InfoPanelProps) {
|
||||||
{Array.from({ length: 4 }).map((_, i) => (
|
{Array.from({ length: 4 }).map((_, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className="absolute w-2 h-2 bg-green-400 rounded-full animate-pulse"
|
className="absolute w-2 h-2 bg-pr-green rounded-full animate-pulse"
|
||||||
style={{
|
style={{
|
||||||
left: `${20 + i * 25}%`,
|
left: `${20 + i * 25}%`,
|
||||||
top: `${30 + Math.random() * 40}%`,
|
top: `${30 + Math.random() * 40}%`,
|
||||||
|
|
@ -378,7 +378,7 @@ export function InfoPanel({ selectedCompany }: InfoPanelProps) {
|
||||||
<CardContent className="pt-0 pb-6">
|
<CardContent className="pt-0 pb-6">
|
||||||
<div className="bg-[rgba(255,255,255,0.1)] rounded-lg p-4 text-center">
|
<div className="bg-[rgba(255,255,255,0.1)] rounded-lg p-4 text-center">
|
||||||
<div className="w-28 h-4 bg-gray-600 rounded animate-pulse mx-auto mb-1"></div>
|
<div className="w-28 h-4 bg-gray-600 rounded animate-pulse mx-auto mb-1"></div>
|
||||||
<div className="w-12 h-6 bg-green-400 bg-opacity-30 rounded animate-pulse mx-auto"></div>
|
<div className="w-12 h-6 bg-pr-green bg-opacity-30 rounded animate-pulse mx-auto"></div>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ export interface CompanyDetails {
|
||||||
|
|
||||||
export interface NetworkGraphProps {
|
export interface NetworkGraphProps {
|
||||||
onNodeClick?: (node: CompanyDetails) => void;
|
onNodeClick?: (node: CompanyDetails) => void;
|
||||||
|
onLoadingChange?: (loading: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseApiResponse(raw: any): any[] {
|
function parseApiResponse(raw: any): any[] {
|
||||||
|
|
@ -58,7 +59,7 @@ function isBrowser(): boolean {
|
||||||
return typeof window !== "undefined";
|
return typeof window !== "undefined";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NetworkGraph({ onNodeClick }: NetworkGraphProps) {
|
export function NetworkGraph({ onNodeClick, onLoadingChange }: NetworkGraphProps) {
|
||||||
const svgRef = useRef<SVGSVGElement | null>(null);
|
const svgRef = useRef<SVGSVGElement | null>(null);
|
||||||
const [nodes, setNodes] = useState<Node[]>([]);
|
const [nodes, setNodes] = useState<Node[]>([]);
|
||||||
const [links, setLinks] = useState<Link[]>([]);
|
const [links, setLinks] = useState<Link[]>([]);
|
||||||
|
|
@ -441,6 +442,19 @@ export function NetworkGraph({ onNodeClick }: NetworkGraphProps) {
|
||||||
if (d.isCenter) return;
|
if (d.isCenter) return;
|
||||||
|
|
||||||
if (onNodeClick && d.stageid) {
|
if (onNodeClick && d.stageid) {
|
||||||
|
// Open dialog immediately with basic info
|
||||||
|
const basicDetails: CompanyDetails = {
|
||||||
|
id: d.id,
|
||||||
|
label: d.label,
|
||||||
|
category: d.category,
|
||||||
|
stageid: d.stageid,
|
||||||
|
fields: [],
|
||||||
|
};
|
||||||
|
onNodeClick(basicDetails);
|
||||||
|
|
||||||
|
// Start loading
|
||||||
|
onLoadingChange?.(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await callAPI(d.stageid);
|
const res = await callAPI(d.stageid);
|
||||||
const responseData = JSON.parse(res.data);
|
const responseData = JSON.parse(res.data);
|
||||||
|
|
@ -473,14 +487,10 @@ export function NetworkGraph({ onNodeClick }: NetworkGraphProps) {
|
||||||
onNodeClick(companyDetails);
|
onNodeClick(companyDetails);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch company details:", error);
|
console.error("Failed to fetch company details:", error);
|
||||||
const basicDetails: CompanyDetails = {
|
// Keep the basic details already shown
|
||||||
id: d.id,
|
} finally {
|
||||||
label: d.label,
|
// Stop loading
|
||||||
category: d.category,
|
onLoadingChange?.(false);
|
||||||
stageid: d.stageid,
|
|
||||||
fields: [],
|
|
||||||
};
|
|
||||||
onNodeClick(basicDetails);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,20 @@ function handleValue(val: any): any {
|
||||||
export default function EcosystemPage() {
|
export default function EcosystemPage() {
|
||||||
const [selectedCompany, setSelectedCompany] =
|
const [selectedCompany, setSelectedCompany] =
|
||||||
React.useState<CompanyDetails | null>(null);
|
React.useState<CompanyDetails | null>(null);
|
||||||
|
const [isDialogLoading, setIsDialogLoading] = React.useState(false);
|
||||||
const { token } = useAuth();
|
const { token } = useAuth();
|
||||||
|
|
||||||
const closeDialog = () => {
|
const closeDialog = () => {
|
||||||
setSelectedCompany(null);
|
setSelectedCompany(null);
|
||||||
|
setIsDialogLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNodeClick = (company: CompanyDetails) => {
|
||||||
|
setSelectedCompany(company);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLoadingChange = (loading: boolean) => {
|
||||||
|
setIsDialogLoading(loading);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Construct image URL
|
// Construct image URL
|
||||||
|
|
@ -79,7 +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 onNodeClick={setSelectedCompany} />
|
<NetworkGraph onNodeClick={handleNodeClick} onLoadingChange={handleLoadingChange} />
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -91,7 +101,7 @@ export default function EcosystemPage() {
|
||||||
open={!!selectedCompany}
|
open={!!selectedCompany}
|
||||||
onOpenChange={(open) => !open && closeDialog()}
|
onOpenChange={(open) => !open && closeDialog()}
|
||||||
>
|
>
|
||||||
<DialogContent className="font-persian max-w-6xl max-h-[75vh] overflow-y-auto bg-[linear-gradient(to_bottom_left,#464861,20%,#111628)]">
|
<DialogContent className="font-persian max-w-6xl min-h-max bg-[linear-gradient(to_bottom_left,#464861,20%,#111628)]">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle className="text-right border-b-2 border-gray-600 pt-2 pb-4 mr-4 text-sm font-semibold">
|
<DialogTitle className="text-right border-b-2 border-gray-600 pt-2 pb-4 mr-4 text-sm font-semibold">
|
||||||
معرفی
|
معرفی
|
||||||
|
|
@ -99,98 +109,136 @@ export default function EcosystemPage() {
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
{isDialogLoading ? (
|
||||||
{/* Right Column - Description */}
|
<div className="grid grid-cols-1 md:grid-cols-2 p-4 gap-6">
|
||||||
<div className="space-y-4 p-6 border-l-2 border-gray-600">
|
{/* Right Column - Loading Skeleton */}
|
||||||
{/* Company Image */}
|
<div className="space-y-4 p-6 border-l-2 border-gray-600">
|
||||||
<div className="flex justify-between px-10 items-center text-3xl font-bold mb-4">
|
{/* Company Image & Title Skeleton */}
|
||||||
{selectedCompany?.label || ""}
|
<div className="flex justify-between px-10 items-center mb-4">
|
||||||
{selectedCompany?.stageid && token?.accessToken ? (
|
<div className="h-8 bg-gray-600 rounded animate-pulse w-48"></div>
|
||||||
<img
|
<div className="w-12 h-12 bg-gray-600 rounded-2xl animate-pulse"></div>
|
||||||
src={getImageUrl(selectedCompany.stageid)}
|
</div>
|
||||||
alt={selectedCompany?.label || ""}
|
{/* Description Skeleton */}
|
||||||
className="w-12 h-12 object-cover rounded-2xl"
|
<div className="p-4 rounded-lg space-y-2">
|
||||||
onError={(e) => {
|
<div className="h-4 bg-gray-600 rounded animate-pulse w-full"></div>
|
||||||
// Hide image and show fallback on error
|
<div className="h-4 bg-gray-600 rounded animate-pulse w-5/6"></div>
|
||||||
e.currentTarget.style.display = "none";
|
<div className="h-4 bg-gray-600 rounded animate-pulse w-4/6"></div>
|
||||||
if (e.currentTarget.nextSibling) {
|
<div className="h-4 bg-gray-600 rounded animate-pulse w-3/6"></div>
|
||||||
(
|
|
||||||
e.currentTarget.nextSibling as HTMLElement
|
|
||||||
).style.display = "flex";
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
<div
|
|
||||||
className="w-24 h-24 rounded-full bg-gray-600 border-4 border-green-400 flex items-center justify-center"
|
|
||||||
style={{
|
|
||||||
display:
|
|
||||||
selectedCompany?.stageid && token?.accessToken
|
|
||||||
? "none"
|
|
||||||
: "flex",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
className="w-10 h-10 text-gray-400"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth={2}
|
|
||||||
d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{selectedCompany?.description ? (
|
{/* Left Column - Loading Skeleton */}
|
||||||
<div className="p-4 rounded-lg">
|
<div className="space-y-2">
|
||||||
<p className="font-persian text-sm font-normal leading-relaxed">
|
<div className="h-6 bg-gray-600 rounded animate-pulse w-32"></div>
|
||||||
{selectedCompany.description}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="text-gray-500 font-persian text-sm">
|
|
||||||
توضیحات در دسترس نیست
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{/* Left Column - Company Fields */}
|
|
||||||
<div className="space-y-2">
|
|
||||||
<h3 className="font-persian gap-1 flex text-sm font-semibold">
|
|
||||||
اطلاعات
|
|
||||||
<span>{selectedCompany?.category}</span>
|
|
||||||
</h3>
|
|
||||||
{selectedCompany?.fields &&
|
|
||||||
selectedCompany.fields.length > 0 ? (
|
|
||||||
<div className="space-y-3 px-2">
|
<div className="space-y-3 px-2">
|
||||||
{selectedCompany.fields.map((field, index) => (
|
{Array.from({ length: 6 }).map((_, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className="flex justify-between items-center rounded-lg"
|
className="flex justify-between items-center rounded-lg"
|
||||||
>
|
>
|
||||||
<span className="font-persian flex items-center gap-1 text-sm font-light">
|
<div className="flex items-center gap-1">
|
||||||
<Hexagon className="text-pr-green h-4 w-4" />
|
<div className="h-4 w-4 bg-gray-600 rounded animate-pulse"></div>
|
||||||
{field.N}:
|
<div className="h-4 bg-gray-600 rounded animate-pulse w-24"></div>
|
||||||
</span>
|
</div>
|
||||||
<span className="text-right min-w-1/3">
|
<div className="h-4 bg-gray-600 rounded animate-pulse w-20"></div>
|
||||||
<span className="font-persian text-sm font-normal text-right">
|
|
||||||
{handleValue(field.V)}
|
|
||||||
{field.U && <span className="mr-1">({field.U})</span>}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
</div>
|
||||||
<div className="text-gray-500 font-persian text-sm">
|
|
||||||
اطلاعات تکمیلی در دسترس نیست
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
) : (
|
||||||
|
<div className="grid p-4 pb-6 grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
{/* Right Column - Description */}
|
||||||
|
<div className="space-y-4 p-6 border-l-2 border-gray-600">
|
||||||
|
{/* Company Image */}
|
||||||
|
<div className="flex justify-between px-10 items-center text-3xl font-bold mb-4">
|
||||||
|
{selectedCompany?.label || ""}
|
||||||
|
{selectedCompany?.stageid && token?.accessToken ? (
|
||||||
|
<img
|
||||||
|
src={getImageUrl(selectedCompany.stageid)}
|
||||||
|
alt={selectedCompany?.label || ""}
|
||||||
|
className="w-12 h-12 object-cover rounded-2xl"
|
||||||
|
onError={(e) => {
|
||||||
|
// Hide image and show fallback on error
|
||||||
|
e.currentTarget.style.display = "none";
|
||||||
|
if (e.currentTarget.nextSibling) {
|
||||||
|
(
|
||||||
|
e.currentTarget.nextSibling as HTMLElement
|
||||||
|
).style.display = "flex";
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
<div
|
||||||
|
className="w-24 h-24 rounded-full bg-gray-600 border-4 border-pr-green flex items-center justify-center"
|
||||||
|
style={{
|
||||||
|
display:
|
||||||
|
selectedCompany?.stageid && token?.accessToken
|
||||||
|
? "none"
|
||||||
|
: "flex",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="w-10 h-10 text-gray-400"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{selectedCompany?.description ? (
|
||||||
|
<div className="p-4 rounded-lg">
|
||||||
|
<p className="font-persian text-sm font-normal leading-relaxed">
|
||||||
|
{selectedCompany.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="text-gray-500 font-persian text-sm">
|
||||||
|
توضیحات در دسترس نیست
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{/* Left Column - Company Fields */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h3 className="font-persian gap-1 flex text-sm font-semibold">
|
||||||
|
اطلاعات
|
||||||
|
<span>{selectedCompany?.category}</span>
|
||||||
|
</h3>
|
||||||
|
{selectedCompany?.fields &&
|
||||||
|
selectedCompany.fields.length > 0 ? (
|
||||||
|
<div className="space-y-3 px-2">
|
||||||
|
{selectedCompany.fields.map((field, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="flex justify-between items-center rounded-lg"
|
||||||
|
>
|
||||||
|
<span className="font-persian flex items-center gap-1 text-sm font-light">
|
||||||
|
<Hexagon className="text-pr-green h-4 w-4" />
|
||||||
|
{field.N}:
|
||||||
|
</span>
|
||||||
|
<span className="text-right min-w-1/3">
|
||||||
|
<span className="font-persian text-sm font-normal text-right">
|
||||||
|
{handleValue(field.V)}
|
||||||
|
{field.U && <span className="mr-1">({field.U})</span>}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="text-gray-500 font-persian text-sm">
|
||||||
|
اطلاعات تکمیلی در دسترس نیست
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</DashboardLayout>
|
</DashboardLayout>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user