New changes UI

This commit is contained in:
2026-01-05 18:53:25 +05:30
parent ad13634121
commit 676a40f0d9
3 changed files with 94 additions and 150 deletions

View File

@@ -8,15 +8,16 @@ import { toast } from "react-toastify";
const API_BASE = process.env.REACT_APP_API_BASE_URL;
const SECTORS = [
{ label: "Water Supply", value: "water supply" },
{ label: "Storm Water", value: "storm water" },
{ label: "Electromechanical", value: "electromechanical" },
{ label: "Real Estate / Buildings", value: "real estate / buildings" },
{ label: "Tunnel", value: "tunnel" },
{ label: "Roads", value: "roads" },
{ label: "Wastewater / Sewerage", value: "wastewater / sewerage" },
{ label: "Irrigation", value: "irrigation" },
{ label: "Renewable Energy", value: "renewable energy" },
{ label: "All", value: "All" },
{ label: "Water Supply", value: "Water Supply" },
{ label: "Storm Water", value: "Storm Water" },
{ label: "Electromechanical", value: "Electromechanical & Instrumentation" },
{ label: "Real Estate / Buildings", value: "Real estate / Buildings" },
{ label: "Tunnel", value: "Tunnel" },
{ label: "Roads", value: "Roads" },
{ label: "Wastewater / Sewerage", value: "Wastewater / Sewerage" },
{ label: "Irrigation", value: "Irrigation" },
{ label: "Renewable Energy", value: "Renewable Energy" },
];
const AddProjects = () => {

View File

@@ -1,45 +1,7 @@
import React, { useState, useEffect, useRef } from "react";
import axios from "axios";
import Slider from "react-slick";
import heroBg from "../assets/projects-hero.jpg";
import "../styles/Projects.css";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
/* =====================
Custom Arrows
===================== */
const NextArrow = ({ className, style, onClick }) => (
<div
className={className}
style={{
...style,
display: "block",
background: "rgba(0,0,0,0.5)",
borderRadius: "50%",
padding: "10px",
right: "10px",
zIndex: 2,
}}
onClick={onClick}
/>
);
const PrevArrow = ({ className, style, onClick }) => (
<div
className={className}
style={{
...style,
display: "block",
background: "rgba(0,0,0,0.5)",
borderRadius: "50%",
padding: "10px",
left: "10px",
zIndex: 2,
}}
onClick={onClick}
/>
);
const Projects = () => {
const [selectedSector, setSelectedSector] = useState("all");
@@ -54,7 +16,7 @@ const Projects = () => {
{ label: "All", value: "all" },
{ label: "Water Supply", value: "water supply" },
{ label: "Storm Water", value: "storm water" },
{ label: "Electromechanical", value: "electromechanical" },
{ label: "Electromechanical", value: "electromechanical & instrumentation" },
{ label: "Real Estate / Buildings", value: "real estate / buildings" },
{ label: "Tunnel", value: "tunnel" },
{ label: "Roads", value: "roads" },
@@ -63,9 +25,6 @@ const Projects = () => {
{ label: "Renewable Energy", value: "renewable energy" },
];
/* =====================
Fetch Projects
===================== */
useEffect(() => {
const fetchProjects = async () => {
try {
@@ -82,9 +41,6 @@ const Projects = () => {
fetchProjects();
}, []);
/* =====================
Scroll to sectors
===================== */
useEffect(() => {
if (window.location.hash === "#sectors" && sectorRef.current) {
setTimeout(() => {
@@ -108,32 +64,9 @@ const Projects = () => {
}));
};
/* =====================
Slider Settings
===================== */
const sliderSettings = {
dots: false,
infinite: true,
speed: 600,
slidesToShow: 3,
slidesToScroll: 1,
autoplay: true,
autoplaySpeed: 1500,
arrows: true,
nextArrow: <NextArrow />,
prevArrow: <PrevArrow />,
responsive: [
{ breakpoint: 1024, settings: { slidesToShow: 3 } },
{ breakpoint: 768, settings: { slidesToShow: 2 } },
{ breakpoint: 480, settings: { slidesToShow: 1 } },
],
};
return (
<div className="min-h-screen bg-gray-50">
{/* =====================
Hero Section
====================== */}
{/* Hero Section */}
<div
className="relative bg-cover bg-center h-[60vh] flex items-center justify-center"
style={{ backgroundImage: `url(${heroBg})` }}
@@ -149,9 +82,7 @@ const Projects = () => {
</div>
</div>
{/* =====================
Sector Buttons
====================== */}
{/* Sector Buttons */}
<div
ref={sectorRef}
className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4 px-4 mt-8 mb-10"
@@ -165,9 +96,7 @@ const Projects = () => {
"bg-gradient-to-r from-purple-400 to-purple-600",
"bg-gradient-to-r from-red-400 to-red-600",
];
const isSelected = selectedSector === sector.value;
return (
<button
key={sector.value}
@@ -182,81 +111,73 @@ const Projects = () => {
})}
</div>
{/* =====================
Projects Slider
====================== */}
<div className="px-6 mb-16">
{/* Projects Grid */}
<div className="px-6 mb-16 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 gap-6">
{loading ? (
<p className="text-center text-xl text-gray-500">Loading projects...</p>
) : filteredProjects.length === 0 ? (
<p className="text-center text-xl text-gray-600">
No projects available.
</p>
<p className="text-center text-xl text-gray-600">No projects available.</p>
) : (
<Slider key={selectedSector} {...sliderSettings}>
{filteredProjects.map((project) => (
<div key={project.id} className="px-2">
<div className="bg-white rounded-xl shadow-lg overflow-hidden hover:shadow-2xl transition">
filteredProjects.map((project) => (
<div key={project.id} className="radar-card bg-white rounded-xl shadow-lg overflow-hidden hover:shadow-2xl transition flex flex-col h-full">
{/* ✅ FIXED IMAGE SIZE (NO BIG / SMALL ISSUE) */}
{project.image && (
<div className="relative w-full aspect-[16/9] bg-gray-200 overflow-hidden">
<img
src={`${process.env.REACT_APP_API_BASE_URL}${project.image}`}
alt={project.name}
className="absolute inset-0 w-full h-full object-cover cursor-pointer"
onClick={(e) => {
e.stopPropagation();
setLightboxImage(
`${process.env.REACT_APP_API_BASE_URL}${project.image}`
);
}}
/>
</div>
)}
{project.image && (
<div className="radar-image-container relative w-full aspect-[16/9] bg-gray-200 overflow-hidden flex-shrink-0">
<img
src={`${process.env.REACT_APP_API_BASE_URL}${project.image}`}
alt={project.name}
className="radar-image absolute inset-0 w-full h-full object-cover cursor-pointer"
onClick={(e) => {
e.stopPropagation();
setLightboxImage(`${process.env.REACT_APP_API_BASE_URL}${project.image}`);
}}
/>
</div>
)}
<div className="p-4">
<h3 className="text-lg font-bold text-blue-800">
{project.name}
</h3>
<p className="text-sm text-gray-600">
Sector: {project.sector}
<div className="p-4 flex flex-col flex-grow">
<h3 className="radar-title text-lg font-bold text-blue-800 leading-tight">
{project.name}
</h3>
<p className="text-sm text-gray-600 mt-1 font-semibold">
Sector: {project.sector
.split(" ")
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
.join(" ")}
</p>
{project.location && (
<p className="text-sm text-gray-600">
Location: {project.location}
</p>
)}
{project.description && (
<div className="text-sm text-gray-700 mt-auto pt-4">
<p>
{expandedDescriptions[project.id]
? project.description
: project.description.slice(0, 100) + "..."}
</p>
{project.location && (
<p className="text-sm text-gray-600">
Location: {project.location}
</p>
)}
{project.description && (
<p className="text-sm text-gray-700 mt-2">
{expandedDescriptions[project.id]
? project.description
: project.description.slice(0, 100) + "..."}
{project.description.length > 100 && (
<button
onClick={() => toggleDescription(project.id)}
className="ml-2 text-blue-600 underline text-sm"
>
{expandedDescriptions[project.id]
? "Read Less"
: "Read More"}
</button>
)}
</p>
{project.description.length > 100 && (
<button
onClick={() => toggleDescription(project.id)}
className="text-blue-600 underline text-sm mt-1"
>
{expandedDescriptions[project.id] ? "Read Less" : "Read More"}
</button>
)}
</div>
</div>
)}
</div>
))}
</Slider>
</div>
))
)}
</div>
{/* =====================
Image Lightbox
====================== */}
{/* Image Lightbox */}
{lightboxImage && (
<div
className="fixed inset-0 bg-black bg-opacity-80 z-50 flex items-center justify-center"
@@ -269,11 +190,7 @@ const Projects = () => {
>
×
</button>
<img
src={lightboxImage}
alt="Project"
className="max-w-[90vw] max-h-[90vh] object-contain"
/>
<img src={lightboxImage} alt="Project" className="max-w-[90vw] max-h-[90vh] object-contain" />
</div>
</div>
)}

View File

@@ -28,3 +28,29 @@
stroke-width: 0.7;
}
}
.map-wrapper {
width: 100%;
max-width: 100%;
overflow: hidden;
}
.map-wrapper svg {
width: 100%;
height: auto;
}
@media (max-width: 767px) {
/* Optional: reduce stroke width and marker size for mobile */
.map-wrapper svg .rsm-geography {
stroke-width: 0.5 !important;
}
.map-wrapper svg circle {
r: 6 !important; /* smaller circles on mobile */
stroke-width: 1 !important;
}
.map-wrapper svg text {
font-size: 12px !important; /* smaller text on mobile */
}
}