Files
edr-platform/apps/edr-freight-web/backoffice/src/pages/HomePage/OrganizationGoal.tsx
yaschalew 697799b00d fix
2026-07-10 14:24:58 +03:00

292 lines
11 KiB
TypeScript

import { useLocalizedName } from "@/shared/common/localizedName";
import { useGoal } from "@/user-management/web-Management/hooks/useGoal";
import { useTheme } from "@/user-management/web-Management/hooks/useTheme";
import { useVision } from "@/user-management/web-Management/hooks/useVision";
import React, { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
const OrganizationGoals = () => {
const [currentGoalIndex, setCurrentGoalIndex] = useState(0);
const [isMobile, setIsMobile] = useState(false);
const localizedName = useLocalizedName();
const { t } = useTranslation();
const baseParams = {
isActive: true,
};
const { items } = useGoal(baseParams);
const { items: theme, unit } = useTheme();
const { items: vision } = useVision(baseParams);
const goals: any[] = items ?? [];
// Auto-rotate goals
useEffect(() => {
if (items?.length) {
const interval = setInterval(() => {
setCurrentGoalIndex((prevIndex) =>
prevIndex === goals?.length - 1 ? 0 : prevIndex + 1
);
}, 3000);
return () => clearInterval(interval);
}
}, [goals?.length, items]);
// Responsive
useEffect(() => {
const checkScreenSize = () => {
setIsMobile(window.innerWidth < 768);
};
checkScreenSize();
window.addEventListener("resize", checkScreenSize);
return () => window.removeEventListener("resize", checkScreenSize);
}, []);
const goToGoal = (index: any) => {
setCurrentGoalIndex(index);
};
const currentGoal = goals[currentGoalIndex];
function lightenColor(color: string, percent: number) {
const R = parseInt(color.substring(1, 3), 16);
const G = parseInt(color.substring(3, 5), 16);
const B = parseInt(color.substring(5, 7), 16);
const newR = Math.min(255, R + Math.round((255 - R) * (percent / 100)));
const newG = Math.min(255, G + Math.round((255 - G) * (percent / 100)));
const newB = Math.min(255, B + Math.round((255 - B) * (percent / 100)));
return `#${newR.toString(16).padStart(2, "0")}${newG
.toString(16)
.padStart(2, "0")}${newB.toString(16).padStart(2, "0")}`;
}
return (
<div
className="min-h-screen flex items-center justify-center p-4 md:p-8"
style={{
background: `linear-gradient(
to bottom,
${
theme?.find((i) => i.type === "PRIMARY_COLOR")?.value
? lightenColor(
theme.find((i) => i.type === "PRIMARY_COLOR")!.value,
30
)
: "var(--primary-300)"
},
${
theme?.find((i) => i.type === "SECONDARY_COLOR")?.value
? lightenColor(
theme.find((i) => i.type === "SECONDARY_COLOR")!.value,
55
)
: "var(--primary-300)"
}
)`,
}}>
<div className="max-w-6xl w-full">
{/* Header */}
<div className="text-center mb-12">
<div className="flex flex-col md:flex-row items-center justify-center mb-6">
{/* Logo */}
<div
className="overflow-hidden flex items-center justify-center shadow-lg mb-4 md:mb-0 md:mr-6"
style={{
width: "150px",
height: "150px",
borderRadius: "16px", // change to "50%" for full circle
flexShrink: 0,
}}>
<img
src={
theme?.find((i) => i.type === "LOGO")?.presigned ||
"https://www.w3.org/Icons/w3c_home"
}
alt={localizedName(unit?.name)}
className="w-full h-full object-cover"
/>
</div>
{/* Text */}
<div className="max-w-xs md:max-w-md break-words text-center md:text-left">
<h2 className="text-3xl md:text-4xl font-bold text-gray-800 mb-2 leading-tight">
{localizedName(unit?.name)}
</h2>
</div>
</div>
{/* Decorative line */}
<div
className="w-32 h-1 mx-auto rounded-full"
style={{
background: `linear-gradient(to right, ${
theme?.find((i) => i.type === "PRIMARY_COLOR")?.value ||
"#3b82f6"
}, ${
theme?.find((i) => i.type === "SECONDARY_COLOR")?.value ||
"#9333ea"
})`,
}}></div>
</div>
{/* Goals */}
<div className="bg-white rounded-2xl shadow-xl overflow-hidden transition-all duration-300 min-h-[470px] hover:shadow-2xl mb-12">
<div className="flex flex-col md:flex-row">
<div className="md:w-2/3 p-6 md:p-8 flex flex-col justify-center">
<div className="mb-6">
<div className="flex items-center mb-6">
<div
className="w-12 h-12 rounded-lg flex items-center justify-center mr-4 overflow-hidden"
style={{
background: `linear-gradient(to right, ${
theme?.find((i) => i.type === "SECONDARY_COLOR")
?.value || "#32CD32"
}, ${
theme?.find((i) => i.type === "SECONDARY_COLOR")
?.value || "#FFFFFF"
})`,
}}>
<img
src={
currentGoal?.presigned ||
"https://www.w3.org/Icons/w3c_home"
}
alt="Goal Icon"
className="w-full h-full object-cover"
/>
</div>
<div>
<h3 className="text-lg font-semibold text-gray-600 uppercase tracking-wide">
{t("Strategic Goal")} {currentGoalIndex + 1} {t("of")}{" "}
{goals?.length}
</h3>
<h2 className="text-2xl md:text-3xl font-bold text-gray-800 mt-1">
{localizedName(currentGoal?.goalTitle)}
</h2>
</div>
</div>
<div className="min-h-[120px] flex items-center">
<p className="text-gray-700 text-lg leading-relaxed transition-opacity duration-500">
{localizedName(currentGoal?.goalDescription) ||
t("msg.waitingMsg")}
</p>
</div>
</div>
<div className="mt-6">
<div className="flex justify-between items-center mb-4">
<span className="text-gray-600 text-sm">
{t("Our Strategic Goals")}
</span>
</div>
<div className="flex space-x-2 mb-4">
{goals?.map((_, index) => (
<button
key={index}
onClick={() => goToGoal(index)}
className={`flex-1 h-2 rounded-full transition-all duration-300 ${
index !== currentGoalIndex
? "bg-gray-200 hover:bg-gray-300"
: ""
}`}
style={
index === currentGoalIndex
? {
background: `linear-gradient(to right, ${
theme?.find((i) => i.type === "PRIMARY_COLOR")
?.value || "#00FF00"
})`,
}
: {}
}
aria-label={t("Go to goal", {
index: index + 1,
title: localizedName(goals[index].goalTitle),
})}
/>
))}
</div>
<div className="flex justify-between">
<button
onClick={() =>
goToGoal(
currentGoalIndex === 0
? goals?.length - 1
: currentGoalIndex - 1
)
}
className="flex items-center text-gray-600 hover:text-gray-800 transition-colors">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5 mr-1"
viewBox="0 0 20 20"
fill="currentColor">
<path
fillRule="evenodd"
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
clipRule="evenodd"
/>
</svg>
{t("Previous Goal")}
</button>
<button
onClick={() =>
goToGoal(
currentGoalIndex === goals?.length - 1
? 0
: currentGoalIndex + 1
)
}
className="flex items-center text-gray-600 hover:text-gray-800 transition-colors">
{t("Next Goal")}
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5 ml-1"
viewBox="0 0 20 20"
fill="currentColor">
<path
fillRule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
clipRule="evenodd"
/>
</svg>
</button>
</div>
</div>
</div>
{/* Vision Section */}
<div className="md:w-1/3 bg-gradient-to-br from-blue-50 to-indigo-100 p-6 md:p-8 flex flex-col justify-center items-center">
<div className="text-center">
<div className="w-32 h-32 mx-auto mb-6 bg-white rounded-2xl shadow-lg overflow-hidden">
<img
src={
currentGoal?.presigned ||
"https://www.w3.org/Icons/w3c_home"
}
alt="Vision Image"
className="w-full h-full object-cover"
/>
</div>
<h3 className="text-xl font-bold text-gray-800 mb-2">
{localizedName(vision?.[0]?.visionTitle)}
</h3>
<p className="text-gray-600">
{localizedName(vision?.[0]?.visionDescription)}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default OrganizationGoals;