آماده سازی برای دو پتروشیمی دیگر
This commit is contained in:
parent
69e702d368
commit
e297522e5c
|
|
@ -212,7 +212,9 @@ export function LoginForm({ onSuccess }: LoginFormProps) {
|
|||
{/* Right Side - Branding */}
|
||||
<LoginSidebar>
|
||||
<LoginBranding
|
||||
brandName="پتروشیمی بندر امام"
|
||||
brandName="پتروشیمی آپادانا"
|
||||
// brandName="پتروشیمی نوری"
|
||||
// brandName="پتروشیمی بندر امام"
|
||||
engSub="Inception by Fara"
|
||||
companyName="توسعهیافته توسط شرکت رهپویان دانش و فناوری فرا"
|
||||
logo={<img src="/brand2.svg"/>}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import { cn } from "~/lib/utils";
|
||||
|
||||
|
||||
interface LoginLayoutProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
|
|
@ -106,14 +107,25 @@ export function LoginBranding({
|
|||
}: LoginBrandingProps) {
|
||||
return (
|
||||
<>
|
||||
{/* Top Logo */}
|
||||
<div className="flex justify-end">
|
||||
<div className="flex justify-end">
|
||||
<div className="text-slate-800 font-persian">
|
||||
<div className="text-lg font-bold leading-tight">
|
||||
<img src="/brand.svg" />
|
||||
</div>
|
||||
<img
|
||||
src="/brand.svg?v=1"
|
||||
alt="Brand Logo"
|
||||
className="w-auto h-16" // اضافه کردن سایز مشخص
|
||||
onError={(e) => {
|
||||
e.target.style.display = 'none';
|
||||
console.log('Image failed to load');
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{/* Bottom Section */}
|
||||
<div className="flex flex-col gap-2 mb-4 items-end justify-end">
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
//این فایل مخصوص
|
||||
//شماتیک آپادانا
|
||||
|
||||
import React from "react";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
//این فایل مخصوص
|
||||
//شماتیک بندر امام
|
||||
import React from "react";
|
||||
import { formatNumber } from "~/lib/utils";
|
||||
|
|
|
|||
211
app/components/dashboard/d3-image-info3.tsx
Normal file
211
app/components/dashboard/d3-image-info3.tsx
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
//این فایل مخصوص
|
||||
//شماتیک نوری
|
||||
|
||||
import React from "react";
|
||||
import { formatNumber } from "~/lib/utils";
|
||||
|
||||
export type CompanyInfo = {
|
||||
id: string;
|
||||
imageUrl: string;
|
||||
name: string;
|
||||
costReduction: number;
|
||||
revenue?: number;
|
||||
capacity?: number;
|
||||
costI: number;
|
||||
capacityI: number;
|
||||
revenueI: number;
|
||||
cost: number | string;
|
||||
};
|
||||
|
||||
export type D3ImageInfoProps = {
|
||||
companies: CompanyInfo[];
|
||||
width?: number;
|
||||
height?: number;
|
||||
};
|
||||
|
||||
const InfoBox = ({ company, style }: { company: CompanyInfo; style: any }) => {
|
||||
// const hideCapacity = company.name === "واحد 300"; // اگر واحد 300 بود ظرفیت مخفی شود
|
||||
const hideCapacity = false;
|
||||
return (
|
||||
<div className={`info-box`} style={style}>
|
||||
<div className="info-box-content">
|
||||
<div className="info-row">
|
||||
<div className="info-label">درآمد:</div>
|
||||
<div className="info-value revenue text-[12px]">{formatNumber(company?.revenue || 0)}</div>
|
||||
<div className="info-unit">میلیون ریال</div>
|
||||
</div>
|
||||
<div className="info-row">
|
||||
<div className="info-label">هزینه:</div>
|
||||
{hideCapacity ? (
|
||||
<div className="info-value cost2 text-[12px]">{formatNumber(company?.cost || 0)}</div>
|
||||
) : (
|
||||
<div className="info-value cost text-[12px]">{formatNumber(company?.cost || 0)}</div>
|
||||
)}
|
||||
<div className="info-unit">میلیون ریال</div>
|
||||
</div>
|
||||
{!hideCapacity && (
|
||||
<div className="info-row">
|
||||
<div className="info-label">ظرفیت:</div>
|
||||
<div className="info-value capacity text-[12px]">{formatNumber(company?.capacity || 0)}</div>
|
||||
<div className="info-unit">تن در سال</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export function D3ImageInfo({ companies }: D3ImageInfoProps) {
|
||||
// واحدهای جدید - 4 واحد
|
||||
const sample = [
|
||||
{ id: "واحد 100", name: "واحد 100", imageUrl: "/abniro.png" },
|
||||
{ id: "واحد 200", name: "واحد 200", imageUrl: "/besparan.png" },
|
||||
{ id: "واحد 300", name: "واحد 300", imageUrl: "/khwarazmi.png" },
|
||||
{ id: "واحد 400", name: "واحد 400", imageUrl: "/faravash1.png" }
|
||||
];
|
||||
|
||||
|
||||
|
||||
const merged = sample.map(company => {
|
||||
const found = companies.find(item => item.id === company.id);
|
||||
return found
|
||||
? found
|
||||
: { ...company, cost: 0, capacity: 0, revenue: 0, costReduction: 0, costI: 0, capacityI: 0, revenueI: 0 };
|
||||
});
|
||||
|
||||
const displayCompanies = merged;
|
||||
console.log(displayCompanies);
|
||||
|
||||
// موقعیتهای جدید برای چیدمان لوزی شکل (3 ردیف - 1-2-1)
|
||||
// گرید 5x4 نگه داشته شده اما موقعیتها تغییر کرده
|
||||
const gridPositions = [
|
||||
{ col: 2, row: 1, colI: 1, rowI: 1, name: "واحد 100" }, // ردیف اول - ستون اول
|
||||
{ col: 4, row: 1, colI: 5, rowI: 1, name: "واحد 200" }, // ردیف اول - ستون دوم
|
||||
{ col: 2, row: 3, colI: 1, rowI: 3, name: "واحد 300" }, // ردیف دوم - ستون اول
|
||||
{ col: 4, row: 3, colI: 5, rowI: 3, name: "واحد 400" }, // ردیف دوم - ستون دوم
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="w-full h-[500px] rounded-xl">
|
||||
<div dir="ltr" className="company-grid-container">
|
||||
{displayCompanies.map((company, index) => {
|
||||
const gp = gridPositions.find(v => v.name === company.name);
|
||||
return (
|
||||
<React.Fragment key={company.id}>
|
||||
<div
|
||||
className={`company-item`}
|
||||
style={{ gridColumn: gp?.col, gridRow: gp?.row }}
|
||||
>
|
||||
<div className="company-image-container">
|
||||
<img
|
||||
src={company.imageUrl}
|
||||
alt={company.name}
|
||||
className="company-image"
|
||||
/>
|
||||
</div>
|
||||
{company.name}
|
||||
</div>
|
||||
<InfoBox company={company} style={{ gridColumn: gp?.colI, gridRow: gp?.rowI }} />
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<style jsx>{`
|
||||
.company-grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
grid-template-rows: repeat(4, 1fr);
|
||||
gap: 5px;
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.company-item {
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.company-image-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.company-image {
|
||||
object-fit: contain;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border: 1px solid #3F415A;
|
||||
border-radius: 10px;
|
||||
height: max-content;
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
padding: .2rem 1.2rem;
|
||||
min-width: 8rem;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.info-box-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
position: relative;
|
||||
margin: .1rem 0;
|
||||
display: flex;
|
||||
gap: .5rem;
|
||||
justify-content: space-between;
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.info-row:has(.info-value.revenue) {
|
||||
border-bottom: 1px solid #3AEA83;
|
||||
}
|
||||
|
||||
.info-row:has(.info-value.cost) {
|
||||
border-bottom: 1px solid #F76276;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
color: #FFFFFF;
|
||||
font-size: 11px;
|
||||
font-weight: 300;
|
||||
text-align: right;
|
||||
margin: auto 0;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: #34D399;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
text-align: right;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
.info-value.revenue { color: #fff; }
|
||||
.info-value.cost { color: #fff; }
|
||||
.info-value.cost2 { color: #fff; }
|
||||
.info-value.capacity { color: #fff; }
|
||||
|
||||
.info-unit {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 2px;
|
||||
color: #ACACAC;
|
||||
font-size: 6px;
|
||||
font-weight: 400;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -641,6 +641,7 @@ export function DashboardHome() {
|
|||
<TabsContent value="canvas" className="w-ful h-full">
|
||||
<div className="p-4 h-full w-full">
|
||||
<D3ImageInfo
|
||||
|
||||
//پتروشیمی بندر امام
|
||||
// companies={companyChartData.map((item) => {
|
||||
// const imageMap: Record<string, string> = {
|
||||
|
|
@ -662,7 +663,14 @@ export function DashboardHome() {
|
|||
"واحد 400": "/faravash1.png"
|
||||
};
|
||||
|
||||
|
||||
//پتروشیمی نوری
|
||||
// companies={companyChartData.map((item) => {
|
||||
// const imageMap: Record<string, string> = {
|
||||
// "واحد 100": "/abniro.png" ,
|
||||
// "واحد 200": "/besparan.png" ,
|
||||
// "واحد 300": "/khwarazmi.png" ,
|
||||
// "واحد 400": "/faravash1.png"
|
||||
// };
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -233,7 +233,14 @@ export function Header({
|
|||
const redirectHandler = async () => {
|
||||
try {
|
||||
const getData = await apiService.post("/GenerateSsoCode");
|
||||
const url = `https://inogen-bpms.pelekan.org/redirect/${getData.data}`;
|
||||
|
||||
//بندر امام
|
||||
// const url = `https://inogen-bpms.pelekan.org/redirect/${getData.data}`;
|
||||
//آپادانا
|
||||
const url = `https://APADANA-IATM-bpms.pelekan.org/redirect/${getData.data}`;
|
||||
//نوری
|
||||
// const url = `https://NOPC-IATM-bpms.pelekan.org/redirect/${getData.data}`;
|
||||
|
||||
window.open(url, "_blank");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,13 @@ import { useAuth } from "../../contexts/auth-context";
|
|||
import apiService from "../../lib/api";
|
||||
|
||||
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.meta.env.VITE_API_URL || "https://APADANA-IATM-back.pelekan.org/api";
|
||||
//نوری
|
||||
// import.meta.env.VITE_API_URL || "https://NOPC-IATM-back.pelekan.org/api";
|
||||
|
||||
|
||||
export interface Node {
|
||||
id: string;
|
||||
|
|
@ -143,7 +149,9 @@ export function NetworkGraph({
|
|||
// نود مرکزی
|
||||
const centerNode: Node = {
|
||||
id: "center",
|
||||
label: "پتروشیمی بندر امام",
|
||||
// label: "پتروشیمی بندر امام",
|
||||
// label: "پتروشیمی نوری",
|
||||
label: "پتروشیمی آپادانا",
|
||||
category: "center",
|
||||
stageid: 0,
|
||||
isCenter: true,
|
||||
|
|
@ -367,13 +375,62 @@ export function NetworkGraph({
|
|||
nodeGroup.each(function (d) {
|
||||
const group = d3.select(this);
|
||||
|
||||
if (d.isCenter) {
|
||||
// if (d.isCenter) {
|
||||
// const rect = group
|
||||
// .append("rect")
|
||||
// .attr("width", 200)
|
||||
// .attr("height", 80)
|
||||
// .attr("x", -100) // نصف عرض جدید منفی
|
||||
// .attr("y", -40) // نصف ارتفاع جدید منفی
|
||||
// .attr("rx", 8)
|
||||
// .attr("ry", 8)
|
||||
// .attr("fill", categoryToColor[d.category] || "#94A3B8")
|
||||
// .attr("stroke", "#FFFFFF")
|
||||
// .attr("stroke-width", 3)
|
||||
// .style("pointer-events", "none");
|
||||
|
||||
// if (d.imageUrl || d.isCenter) {
|
||||
// const pattern = defs
|
||||
// .append("pattern")
|
||||
// .attr("id", `image-${d.id}`)
|
||||
// .attr("x", 0)
|
||||
// .attr("y", 0)
|
||||
// .attr("width", 1)
|
||||
// .attr("height", 1);
|
||||
|
||||
// pattern
|
||||
// .append("image")
|
||||
// .attr("x", 0)
|
||||
// .attr("y", 0)
|
||||
// .attr("width", 200) // ← هماندازه با مستطیل
|
||||
// .attr("height", 80)
|
||||
// .attr("href", d.isCenter ? "/main-circle.png" : d.imageUrl)
|
||||
// .attr("preserveAspectRatio", "xMidYMid slice");
|
||||
|
||||
// rect.attr("fill", `url(#image-${d.id})`);
|
||||
// }
|
||||
// }
|
||||
// راه حل سادهتر - ابعاد ثابت با حفظ نسبت
|
||||
if (d.isCenter) {
|
||||
|
||||
//آپادانا
|
||||
const fixedWidth = 198;
|
||||
const fixedHeight = 200; // یا میتوانید براساس نسبت تصویر محاسبه کنید
|
||||
|
||||
//بندر امام
|
||||
// const fixedWidth = 100;
|
||||
// const fixedHeight = 80; // یا میتوانید براساس نسبت تصویر محاسبه کنید
|
||||
|
||||
//نوری
|
||||
// const fixedWidth = 100;
|
||||
// const fixedHeight = 80; // یا میتوانید براساس نسبت تصویر محاسبه کنید
|
||||
|
||||
const rect = group
|
||||
.append("rect")
|
||||
.attr("width", 200)
|
||||
.attr("height", 80)
|
||||
.attr("x", -100) // نصف عرض جدید منفی
|
||||
.attr("y", -40) // نصف ارتفاع جدید منفی
|
||||
.attr("width", fixedWidth)
|
||||
.attr("height", fixedHeight)
|
||||
.attr("x", -fixedWidth / 2)
|
||||
.attr("y", -fixedHeight / 2)
|
||||
.attr("rx", 8)
|
||||
.attr("ry", 8)
|
||||
.attr("fill", categoryToColor[d.category] || "#94A3B8")
|
||||
|
|
@ -381,7 +438,6 @@ export function NetworkGraph({
|
|||
.attr("stroke-width", 3)
|
||||
.style("pointer-events", "none");
|
||||
|
||||
if (d.imageUrl || d.isCenter) {
|
||||
const pattern = defs
|
||||
.append("pattern")
|
||||
.attr("id", `image-${d.id}`)
|
||||
|
|
@ -394,14 +450,15 @@ export function NetworkGraph({
|
|||
.append("image")
|
||||
.attr("x", 0)
|
||||
.attr("y", 0)
|
||||
.attr("width", 200) // ← هماندازه با مستطیل
|
||||
.attr("height", 80)
|
||||
.attr("width", fixedWidth)
|
||||
.attr("height", fixedHeight)
|
||||
.attr("href", d.isCenter ? "/main-circle.png" : d.imageUrl)
|
||||
.attr("preserveAspectRatio", "xMidYMid slice");
|
||||
.attr("preserveAspectRatio", "xMidYMid meet"); // حفظ نسبت تصویر
|
||||
|
||||
rect.attr("fill", `url(#image-${d.id})`);
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
else {
|
||||
const circle = group
|
||||
.append("circle")
|
||||
.attr("r", 25)
|
||||
|
|
@ -444,7 +501,22 @@ export function NetworkGraph({
|
|||
.append("text")
|
||||
.text((d) => d.label)
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("dy", (d) => (d.isCenter ? 50 : 45))
|
||||
.attr("dy", (d) => {
|
||||
if (d.isCenter) {
|
||||
|
||||
//آپادانا
|
||||
const centerNodeHeight = 200; // ارتفاع نود مرکزی
|
||||
|
||||
//بندر امام
|
||||
// const centerNodeHeight = 80; // ارتفاع نود مرکزی
|
||||
|
||||
//نوری
|
||||
// const centerNodeHeight = 80; // ارتفاع نود مرکزی
|
||||
|
||||
return centerNodeHeight / 2 + 20; // نصف ارتفاع + فاصله 20px
|
||||
}
|
||||
return 45; // برای نودهای دیگر
|
||||
})
|
||||
.attr("font-size", (d) => (d.isCenter ? "14px" : "12px"))
|
||||
.attr("font-weight", "bold")
|
||||
.attr("fill", "#F9FAFB")
|
||||
|
|
|
|||
|
|
@ -162,10 +162,24 @@ class ApiService {
|
|||
|
||||
// Innovation process function call wrapper
|
||||
public async call<T = any>(payload: any) {
|
||||
//بندر امام
|
||||
const url = "https://inogen-back.pelekan.org/api/call";
|
||||
//آپادانا
|
||||
const url = "https://APADANA-IATM-back.pelekan.org/api/call";
|
||||
//نوری
|
||||
const url = "https://NOPC-IATM-back.pelekan.org/api/call";
|
||||
return this.postAbsolute<T>(url, payload);
|
||||
}
|
||||
|
||||
|
||||
const API_BASE_URL =
|
||||
//بندر امام
|
||||
// import.meta.env.VITE_API_URL || "https://inogen-bpms-back.pelekan.org/api";
|
||||
//آپادانا
|
||||
import.meta.env.VITE_API_URL || "https://APADANA-IATM-back.pelekan.org/api";
|
||||
//نوری
|
||||
// import.meta.env.VITE_API_URL || "https://NOPC-IATM-back.pelekan.org/api";
|
||||
|
||||
// GET request
|
||||
public async get<T = any>(endpoint: string): Promise<ApiResponse<T>> {
|
||||
return this.request<T>(endpoint, {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,14 @@ import type { Route } from "./+types/ecosystem";
|
|||
|
||||
// Get API base URL at module level to avoid process.env access in browser
|
||||
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.meta.env.VITE_API_URL || "https://APADANA-IATM-back.pelekan.org/api";
|
||||
//نوری
|
||||
// import.meta.env.VITE_API_URL || "https://NOPC-IATM-back.pelekan.org/api";
|
||||
|
||||
|
||||
|
||||
// Import the CompanyDetails type
|
||||
import { Hexagon } from "lucide-react";
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user