Mobile view changes

This commit is contained in:
2026-01-01 17:43:46 +05:30
parent 2c14ebacf5
commit ad13634121
5 changed files with 214 additions and 137 deletions

2
.env
View File

@@ -1,3 +1,3 @@
REACT_APP_API_BASE_URL=http://localhost:8000 REACT_APP_API_BASE_URL=http://192.168.1.48:8000
HOST=0.0.0.0 HOST=0.0.0.0

View File

@@ -9,22 +9,61 @@ import mechanicalBg from "../assets/mechanical-bg.jpg";
import electricalBg from "../assets/electrical-bg.jpg"; import electricalBg from "../assets/electrical-bg.jpg";
import electromechanicalBg from "../assets/electromechanical-bg.jpg"; import electromechanicalBg from "../assets/electromechanical-bg.jpg";
import itBg from "../assets/it-bg.jpg"; import itBg from "../assets/it-bg.jpg";
import renewableBg from "../assets/renewable-bg.jpg"; // renamed image import renewableBg from "../assets/renewable-bg.jpg";
// Animation variants /* =====================
Animation Variants
===================== */
const containerVariants = { const containerVariants = {
hidden: { opacity: 0 }, hidden: { opacity: 0 },
visible: { visible: {
opacity: 1, opacity: 1,
transition: { staggerChildren: 0.2 } transition: { staggerChildren: 0.2 },
}, },
}; };
const itemVariants = { const itemVariants = {
hidden: { opacity: 0, y: 20 }, hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 } visible: { opacity: 1, y: 0 },
}; };
/* =====================
Working Fields Data
(Declared Once)
===================== */
const WORKING_FIELDS = [
{
title: "Civil Engineering",
desc: "Urban infrastructure, roadworks, dams, WTPs, STPs, stormwater management, and structural development.",
bg: civilBg,
},
{
title: "Mechanical Engineering",
desc: "Fabrication, installation, and maintenance of industrial systems, heavy machinery, and automated solutions including SCADA.",
bg: mechanicalBg,
},
{
title: "Electrical Engineering",
desc: "Reliable installations, power distribution, and maintenance services.",
bg: electricalBg,
},
{
title: "Electromechanical & Instrumentation",
desc: "Integration of mechanical and electrical systems for pumping stations and automation.",
bg: electromechanicalBg,
},
{
title: "Information Technology",
desc: "Project planning, GIS, data systems, and automation tools for smart engineering.",
bg: itBg,
},
{
title: "Renewable Energy",
desc: "Solar, wind and sustainable energy solutions with advanced engineering support.",
bg: renewableBg,
},
];
const AboutUs = () => { const AboutUs = () => {
return ( return (
<> <>
@@ -32,8 +71,12 @@ const AboutUs = () => {
<section className="about-hero"> <section className="about-hero">
<div className="hero-overlay"> <div className="hero-overlay">
<h1>About Us</h1> <h1>About Us</h1>
<p className="hero-subtitle">Building the Nation with Precision & Excellence</p> <p className="hero-subtitle">
<p className="mt-4 text-white text-lg italic">Engineering the future, one project at a time.</p> Building the Nation with Precision & Excellence
</p>
<p className="mt-4 text-white text-lg italic">
Engineering the future, one project at a time.
</p>
</div> </div>
</section> </section>
@@ -51,20 +94,27 @@ const AboutUs = () => {
About Laxmi Civil Engineering Services Pvt. Ltd. About Laxmi Civil Engineering Services Pvt. Ltd.
</h2> </h2>
<p className="text-gray-700 leading-relaxed mb-4"> <p className="text-gray-700 leading-relaxed mb-4">
Laxmi Civil Engineering Services Pvt. Ltd. was established on <strong>15th August 1980</strong> as a partnership firm and later Laxmi Civil Engineering Services Pvt. Ltd. was established on{" "}
converted into a Private Limited Company on <strong>31st March 2000</strong>. <strong>15th August 1980</strong> as a partnership firm and later
converted into a Private Limited Company on{" "}
<strong>31st March 2000</strong>.
</p> </p>
<p className="text-gray-700 leading-relaxed mb-4"> <p className="text-gray-700 leading-relaxed mb-4">
For over four decades, LCEPL has been delivering exceptional engineering and construction services, making us one of the leading civil engineering solution providers in India. For over four decades, LCEPL has been delivering exceptional
engineering and construction services.
</p> </p>
<p className="text-gray-700 leading-relaxed mb-4"> <p className="text-gray-700 leading-relaxed mb-4">
We specialize in major infrastructure projects such as portable water supply, irrigation, pumping stations, electromechanical works, and operation & maintenance. We specialize in major infrastructure projects such as portable
water supply, irrigation, pumping stations, electromechanical
works, and operation & maintenance.
</p> </p>
<p className="text-gray-700 leading-relaxed mb-4"> <p className="text-gray-700 leading-relaxed mb-4">
Our leadership in these unique services has allowed us to establish a strong foothold in the central, western, and southern regions of India, while also expanding into the northern region. Our leadership in these unique services has allowed us to expand
across central, western, southern, and northern India.
</p> </p>
<p className="text-gray-700 leading-relaxed"> <p className="text-gray-700 leading-relaxed">
With a workforce of <strong>1300+ professionals</strong>, supported by advanced technology and an inspiring work environment, we continue to move forward with confidence. With a workforce of <strong>1300+ professionals</strong>, we
continue to move forward with confidence.
</p> </p>
</div> </div>
@@ -76,85 +126,52 @@ const AboutUs = () => {
className="grid grid-cols-1 gap-6" className="grid grid-cols-1 gap-6"
> >
<motion.div variants={itemVariants}> <motion.div variants={itemVariants}>
<CounterCard count="45+" label="Years of Experience" icon="🎖️" className="bg-white shadow-lg border border-gray-200 px-4 py-3 rounded-lg" /> <CounterCard
count="45+"
label="Years of Experience"
icon="🎖️"
className="bg-white shadow-lg border px-4 py-3 rounded-lg"
/>
</motion.div> </motion.div>
<motion.div variants={itemVariants}> <motion.div variants={itemVariants}>
<CounterCard count="18+" label="Number of States" icon="🗺️" className="bg-white shadow-lg border border-gray-200 px-4 py-3 rounded-lg" /> <CounterCard
count="18+"
label="Number of States"
icon="🗺️"
className="bg-white shadow-lg border px-4 py-3 rounded-lg"
/>
</motion.div> </motion.div>
<motion.div variants={itemVariants}> <motion.div variants={itemVariants}>
<CounterCard count="50+" label="Clients" icon="🏭" className="bg-white shadow-lg border border-gray-200 px-4 py-3 rounded-lg" /> <CounterCard
count="50+"
label="Clients"
icon="🏭"
className="bg-white shadow-lg border px-4 py-3 rounded-lg"
/>
</motion.div> </motion.div>
</motion.div> </motion.div>
</div> </div>
</section> </section>
{/* QUOTE BANNER */}
<div className="bg-blue-100 text-blue-800 text-center py-6 text-xl font-semibold italic tracking-wide">
Driven by innovation, guided by integrity, delivering with passion.
</div>
{/* VISION & MISSION SECTION */}
<motion.section initial={{ opacity: 0 }} whileInView={{ opacity: 1 }} transition={{ duration: 0.6 }} viewport={{ once: true }} className="relative py-20 px-4 md:px-8 lg:px-20 bg-gradient-to-br from-blue-900 to-blue-800 overflow-hidden">
<motion.div initial={{ y: 30, opacity: 0 }} whileInView={{ y: 0, opacity: 1 }} transition={{ duration: 0.6 }} viewport={{ once: true }} className="max-w-7xl mx-auto relative z-10">
<h2 className="text-4xl font-bold text-center text-white mb-16 relative pb-2">
<span className="relative inline-block">
Vision & Mission
<motion.span initial={{ scaleX: 0 }} whileInView={{ scaleX: 1 }} transition={{ duration: 0.6 }} viewport={{ once: true }} className="absolute bottom-0 left-0 w-full h-1 bg-red-500 z-0 transform origin-center" />
</span>
</h2>
<div className="grid md:grid-cols-2 gap-8 mb-16">
{/* Vision */}
<motion.div initial={{ x: -50, opacity: 0 }} whileInView={{ x: 0, opacity: 1 }} transition={{ duration: 0.5 }} viewport={{ once: true }} className="bg-white p-8 rounded-xl shadow-lg hover:shadow-xl transition-all border-l-4 border-blue-500 hover:border-blue-400">
<div className="flex items-start mb-6">
<div className="bg-blue-100 p-3 rounded-full mr-4">
<svg className="w-8 h-8 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
</svg>
</div>
<div>
<h3 className="text-xl font-bold text-blue-900 mb-2">Vision</h3>
<p className="text-gray-700">To be a company at the forefront of engineering and construction, renowned for excellence, quality, performance, and reliability.</p>
</div>
</div>
</motion.div>
{/* Mission */}
<motion.div initial={{ x: 50, opacity: 0 }} whileInView={{ x: 0, opacity: 1 }} transition={{ duration: 0.5 }} viewport={{ once: true }} className="bg-white p-8 rounded-xl shadow-lg hover:shadow-xl transition-all border-l-4 border-red-500 hover:border-red-400">
<div className="flex items-start mb-6">
<div className="bg-blue-100 p-3 rounded-full mr-4">
<svg className="w-8 h-8 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
</div>
<div>
<h3 className="text-xl font-bold text-blue-900 mb-2">Mission</h3>
<p className="text-gray-700">To complete every project undertaken with sincerity, excellence, and in a time-bound manner, meeting all expectations of the client.</p>
</div>
</div>
</motion.div>
</div>
</motion.div>
</motion.section>
{/* WORKING FIELDS SECTION */} {/* WORKING FIELDS SECTION */}
<section className="working-fields px-6 lg:px-20 py-16 bg-gray-50"> <section className="working-fields px-6 lg:px-20 py-16 bg-gray-50">
<h2 className="highlight-title text-4xl font-bold text-center mb-4 text-black">Expertise Across Multiple Sectors</h2> <h2 className="highlight-title text-4xl font-bold text-center mb-4 text-black">
<p className="text-center text-gray-600 mb-12">Our multidisciplinary approach helps us lead across multiple domains.</p> Expertise Across Multiple Sectors
</h2>
<p className="text-center text-gray-600 mb-12">
Our multidisciplinary approach helps us lead across multiple domains.
</p>
<div className="grid sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"> <div className="grid sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{[ {WORKING_FIELDS.map((field) => (
{ title: "Civil Engineering", desc: "Urban infrastructure, roadworks, dams, WTPs, STPs, stormwater management, and structural development.", bg: civilBg }, <div
{ title: "Mechanical Engineering", desc: "Fabrication, installation, and maintenance of industrial systems, heavy machinery, and automated solutions including SCADA.", bg: mechanicalBg }, key={field.title}
{ title: "Electrical Engineering", desc: "Reliable installations, power distribution, and maintenance services.", bg: electricalBg }, className="relative field-card rounded-xl shadow-lg overflow-hidden transition-all cursor-pointer bg-cover bg-center group hover:shadow-2xl"
{ title: "Electromechanical & Instrumentation", desc: "Integration of mechanical and electrical systems for pumping stations and automation.", bg: electromechanicalBg }, style={{ backgroundImage: `url(${field.bg})` }}
{ title: "Information Technology", desc: "Project planning, GIS, data systems, and automation tools for smart engineering.", bg: itBg }, >
{ title: "Renewable Energy", desc: "Solar, wind and sustainable energy solutions with advanced engineering support.", bg: renewableBg },
].map((field, idx) => (
<div key={idx} className="relative field-card rounded-xl shadow-lg overflow-hidden transition-all cursor-pointer bg-cover bg-center group hover:shadow-2xl" style={{ backgroundImage: `url(${field.bg})` }}>
<div className="absolute inset-0 bg-black/50 group-hover:bg-black/25 transition-all duration-300"></div> <div className="absolute inset-0 bg-black/50 group-hover:bg-black/25 transition-all duration-300"></div>
<div className="relative p-6 flex flex-col items-center text-center text-white z-10"> <div className="relative p-6 flex flex-col items-center text-center text-white z-10">
<div className="text-5xl mb-4">{field.icon}</div>
<h3 className="text-xl font-bold mb-2">{field.title}</h3> <h3 className="text-xl font-bold mb-2">{field.title}</h3>
<p>{field.desc}</p> <p>{field.desc}</p>
</div> </div>

View File

@@ -2,6 +2,23 @@ import React, { useState, useEffect } from "react";
import axios from "axios"; import axios from "axios";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
/* =====================
Constants (Optimized)
===================== */
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" },
];
const AddProjects = () => { const AddProjects = () => {
const [projects, setProjects] = useState([]); const [projects, setProjects] = useState([]);
const [sector, setSector] = useState(""); const [sector, setSector] = useState("");
@@ -10,22 +27,12 @@ const AddProjects = () => {
const [editMode, setEditMode] = useState(false); const [editMode, setEditMode] = useState(false);
const [editProjectId, setEditProjectId] = useState(null); const [editProjectId, setEditProjectId] = useState(null);
const sectors = [ /* =====================
{ label: "Water Supply", value: "water supply" }, Fetch Projects
{ 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" }
];
// Fetch all projects
const fetchProjects = async () => { const fetchProjects = async () => {
try { try {
const res = await axios.get(`${process.env.REACT_APP_API_BASE_URL}/api/projects`); const res = await axios.get(`${API_BASE}/api/projects`);
setProjects(res.data); setProjects(res.data);
} catch (err) { } catch (err) {
console.error("Error fetching projects", err); console.error("Error fetching projects", err);
@@ -36,7 +43,9 @@ const AddProjects = () => {
fetchProjects(); fetchProjects();
}, []); }, []);
// Reset the form /* =====================
Helpers
===================== */
const resetForm = () => { const resetForm = () => {
setSector(""); setSector("");
setImage(null); setImage(null);
@@ -45,16 +54,18 @@ const AddProjects = () => {
setEditProjectId(null); setEditProjectId(null);
}; };
// Handle image selection
const handleImageChange = (e) => { const handleImageChange = (e) => {
const file = e.target.files[0]; const file = e.target.files[0];
setImage(file); setImage(file);
setImagePreview(file ? URL.createObjectURL(file) : null); setImagePreview(file ? URL.createObjectURL(file) : null);
}; };
// Handle form submit (add or update) /* =====================
Submit (Add / Update)
===================== */
const handleSubmit = async (e) => { const handleSubmit = async (e) => {
e.preventDefault(); e.preventDefault();
if (!sector || (!editMode && !image)) { if (!sector || (!editMode && !image)) {
toast.error("Sector and image are required!"); toast.error("Sector and image are required!");
return; return;
@@ -66,10 +77,13 @@ const AddProjects = () => {
try { try {
if (editMode) { if (editMode) {
await axios.post(`${process.env.REACT_APP_API_BASE_URL}/api/projects/update/${editProjectId}`, formData); await axios.post(
`${API_BASE}/api/projects/update/${editProjectId}`,
formData
);
toast.success("Project updated successfully!"); toast.success("Project updated successfully!");
} else { } else {
await axios.post(`${process.env.REACT_APP_API_BASE_URL}/api/projects`, formData); await axios.post(`${API_BASE}/api/projects`, formData);
toast.success("Project added successfully!"); toast.success("Project added successfully!");
} }
@@ -81,21 +95,25 @@ const AddProjects = () => {
} }
}; };
// Load project into form for editing /* =====================
Edit Project
===================== */
const handleEdit = (project) => { const handleEdit = (project) => {
setSector(project.sector); setSector(project.sector);
setImage(null); setImage(null);
setImagePreview(`${process.env.REACT_APP_API_BASE_URL}${project.image}`); setImagePreview(`${API_BASE}${project.image}`);
setEditMode(true); setEditMode(true);
setEditProjectId(project.id); setEditProjectId(project.id);
}; };
// Delete a project /* =====================
Delete Project
===================== */
const handleDelete = async (id) => { const handleDelete = async (id) => {
if (!window.confirm("Are you sure you want to delete this project?")) return; if (!window.confirm("Are you sure you want to delete this project?")) return;
try { try {
await axios.delete(`${process.env.REACT_APP_API_BASE_URL}/api/projects/${id}`); await axios.delete(`${API_BASE}/api/projects/${id}`);
toast.success("Project deleted"); toast.success("Project deleted");
fetchProjects(); fetchProjects();
} catch (err) { } catch (err) {
@@ -111,14 +129,17 @@ const AddProjects = () => {
</h1> </h1>
{/* FORM */} {/* FORM */}
<form onSubmit={handleSubmit} className="space-y-4 max-w-md mx-auto bg-white p-6 rounded-lg shadow"> <form
onSubmit={handleSubmit}
className="space-y-4 max-w-md mx-auto bg-white p-6 rounded-lg shadow"
>
<select <select
value={sector} value={sector}
onChange={(e) => setSector(e.target.value)} onChange={(e) => setSector(e.target.value)}
className="w-full border p-2 rounded" className="w-full border p-2 rounded"
> >
<option value="">Select Sector</option> <option value="">Select Sector</option>
{sectors.map((s) => ( {SECTORS.map((s) => (
<option key={s.value} value={s.value}> <option key={s.value} value={s.value}>
{s.label} {s.label}
</option> </option>
@@ -147,6 +168,7 @@ const AddProjects = () => {
> >
{editMode ? "Update Project" : "Save Project"} {editMode ? "Update Project" : "Save Project"}
</button> </button>
{editMode && ( {editMode && (
<button <button
type="button" type="button"
@@ -161,19 +183,25 @@ const AddProjects = () => {
{/* PROJECT LIST */} {/* PROJECT LIST */}
<div className="mt-10"> <div className="mt-10">
<h2 className="text-2xl font-semibold text-blue-800 mb-4">All Projects</h2> <h2 className="text-2xl font-semibold text-blue-800 mb-4">
All Projects
</h2>
<div className="grid md:grid-cols-3 sm:grid-cols-2 gap-6"> <div className="grid md:grid-cols-3 sm:grid-cols-2 gap-6">
{projects.map((proj) => ( {projects.map((proj) => (
<div <div
key={proj.id} key={proj.id}
className="bg-white p-4 rounded-xl shadow hover:shadow-lg transition-all relative" className="bg-white p-4 rounded-xl shadow hover:shadow-lg transition-all"
> >
<img <img
src={`${process.env.REACT_APP_API_BASE_URL}${proj.image}`} src={`${API_BASE}${proj.image}`}
alt={proj.sector} alt={proj.sector}
className="h-56 w-full object-cover rounded mb-3" className="h-56 w-full object-cover rounded mb-3"
/> />
<p className="text-sm text-gray-700 capitalize mb-1">Sector: {proj.sector}</p>
<p className="text-sm text-gray-700 capitalize mb-1">
Sector: {proj.sector}
</p>
<div className="flex justify-between mt-2"> <div className="flex justify-between mt-2">
<button <button

View File

@@ -1,45 +1,72 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import axios from 'axios'; import axios from 'axios';
/* =====================
Constants
===================== */
const API_BASE = process.env.REACT_APP_API_BASE_URL;
const AdminHR = () => { const AdminHR = () => {
const [submissions, setSubmissions] = useState([]); const [submissions, setSubmissions] = useState([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
// Fetch HR submissions from API /* =====================
useEffect(() => { Fetch Submissions
axios ===================== */
.get(`${process.env.REACT_APP_API_BASE_URL}/api/hr-submissions`) const fetchSubmissions = async () => {
.then((res) => { try {
setLoading(true);
setError(null);
const res = await axios.get(`${API_BASE}/api/hr-submissions`);
setSubmissions(res.data || []); setSubmissions(res.data || []);
setLoading(false); } catch (err) {
})
.catch((err) => {
console.error('Error fetching HR submissions:', err); console.error('Error fetching HR submissions:', err);
setError('Failed to load submissions');
} finally {
setLoading(false); setLoading(false);
}); }
};
useEffect(() => {
fetchSubmissions();
}, []); }, []);
const handleDelete = (id) => { /* =====================
if (window.confirm('Are you sure you want to delete this submission?')) { Delete Submission
axios ===================== */
.delete(`${process.env.REACT_APP_API_BASE_URL}/api/hr-submissions/${id}`) const handleDelete = async (id) => {
.then(() => { if (!window.confirm('Are you sure you want to delete this submission?')) return;
setSubmissions(submissions.filter((sub) => sub.id !== id));
}) try {
.catch((err) => console.error('Error deleting submission:', err)); await axios.delete(`${API_BASE}/api/hr-submissions/${id}`);
setSubmissions((prev) => prev.filter((sub) => sub.id !== id));
} catch (err) {
console.error('Error deleting submission:', err);
alert('Failed to delete submission');
} }
}; };
return ( return (
<div className="max-w-6xl mx-auto px-4 py-16"> <div className="max-w-6xl mx-auto px-4 py-16">
<h2 className="text-3xl font-bold text-blue-900 mb-4">Admin - HR</h2> <h2 className="text-3xl font-bold text-blue-900 mb-4">Admin - HR</h2>
<p className="text-gray-600 mb-6">Manage HR contacts and career submissions.</p> <p className="text-gray-600 mb-6">
Manage HR contacts and career submissions.
</p>
{loading ? ( {/* STATES */}
<p className="text-gray-500">Loading submissions...</p> {loading && <p className="text-gray-500">Loading submissions...</p>}
) : submissions.length === 0 ? (
{!loading && error && (
<p className="text-red-600">{error}</p>
)}
{!loading && !error && submissions.length === 0 && (
<p className="text-gray-500">No submissions found.</p> <p className="text-gray-500">No submissions found.</p>
) : ( )}
{!loading && !error && submissions.length > 0 && (
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<table className="w-full border-collapse border border-gray-200"> <table className="w-full border-collapse border border-gray-200">
<thead> <thead>
@@ -53,15 +80,20 @@ const AdminHR = () => {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{submissions.map((sub, index) => ( {submissions.map((sub) => (
<tr key={sub.id || index} className="hover:bg-gray-50"> <tr key={sub.id} className="hover:bg-gray-50">
<td className="p-2 border">{sub.id}</td> <td className="p-2 border">{sub.id}</td>
<td className="p-2 border">{sub.name}</td> <td className="p-2 border">{sub.name}</td>
<td className="p-2 border">{sub.email}</td> <td className="p-2 border">{sub.email}</td>
<td className="p-2 border">{sub.phone}</td> <td className="p-2 border">{sub.phone}</td>
<td className="p-2 border"> <td className="p-2 border">
{sub.resume ? ( {sub.resume ? (
<a href={sub.resume} target="_blank" rel="noopener noreferrer" className="text-blue-600 underline"> <a
href={sub.resume}
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 underline"
>
View Resume View Resume
</a> </a>
) : ( ) : (

View File

@@ -72,10 +72,10 @@
.counters-grid { max-width: 100%; gap: 0.8rem; } .counters-grid { max-width: 100%; gap: 0.8rem; }
.counter-card { .counter-card {
flex-direction: column; /* icon on top, number + label below */ flex-direction: column; /* icon on top, number + label below */
align-items: flex-start; /* align-items: flex-start; */
padding: 12px 15px; padding: 12px 15px;
min-height: 60px; min-height: 60px;
} }
.counter-card h3 { font-size: 1.4rem; margin-bottom: 3px; } .counter-card h3 { font-size: 1.4rem; margin-bottom: 3px; }
.counter-card p { font-size: 0.9rem; } .counter-card p { font-size: 1.5rem; }
} }