This commit is contained in:
sankalp committed 2026-09-25 01:21:20 +05:45
1 parent 24cf7e12c4
commit ab7aadbbc8
11 files changed
+272 -574

No files matched your search

-74
View File
@@ -1,74 +0,0 @@
import re
with open("src/pages/Home.tsx", "r") as f:
content = f.read()
# I will write a simple string splitting mechanism based on `{block_name.length > 0 && (`
blocks = [
("hero", "{hero && ("),
("marquee", "{marquee.length > 0 && ("),
("whatWeDo", "{whatWeDo.length > 0 && ("),
("partners", "{partners.length > 0 && ("),
("services", "{services.length > 0 && ("),
("testimonials", "{testimonials.length > 0 && ("),
("sisterCompanies", "{sisterCompanies.length > 0 && ("),
("cta", "<section className=\"relative z-10 border-y border-border bg-mist/60\">")
]
# We need to split the content accurately
def get_block_end(start_idx, is_cta=False):
if is_cta:
# CTA goes till the end of the div
return content.find(" </div>\n );\n}", start_idx)
open_braces = 0
in_block = False
for i in range(start_idx, len(content)):
if content[i] == '{':
open_braces += 1
in_block = True
elif content[i] == '}':
open_braces -= 1
if in_block and open_braces == 0:
return i + 1
return -1
extracted = {}
for name, token in blocks:
idx = content.find(token)
if idx != -1:
end_idx = get_block_end(idx, is_cta=(name == "cta"))
extracted[name] = content[idx:end_idx].strip()
# Now reconstruct the body
new_order = [
"hero",
"marquee",
"partners",
"whatWeDo",
"services",
"sisterCompanies",
"testimonials",
"cta"
]
body_content = ""
for name in new_order:
if name in extracted:
body_content += "\n " + extracted[name] + "\n"
# Replace the old body with the new body
# The body starts after `<div className="relative">\n <LightField />`
start_body = content.find("<LightField />") + len("<LightField />")
end_body = content.find(" </div>\n );\n}")
new_content = content[:start_body] + "\n" + body_content + "\n" + content[end_body:]
with open("src/pages/Home.tsx", "w") as f:
f.write(new_content)
print("Reorganized Home.tsx")
+61 -50
View File
@@ -1,7 +1,5 @@
import { useEffect, useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
const COLUMNS = 4;
import { useEffect, useRef } from "react";
import { animate, motion, type AnimationPlaybackControls, useMotionValue } from "framer-motion";
interface Partner {
id: number;
@@ -9,65 +7,78 @@ interface Partner {
logo: string | null;
}
const LOGO_WIDTH = 220; // fixed width per logo block
const GAP = 24; // gap between logos
export function ClientsMarquee({
partners,
}: {
partners: Partner[];
}) {
const [step, setStep] = useState(0);
const x = useMotionValue(0);
const controls = useRef<AnimationPlaybackControls | null>(null);
useEffect(() => {
if (partners.length <= COLUMNS) return;
const id = setInterval(() => {
setStep((s) => (s + 1) % partners.length);
}, 2500);
return () => clearInterval(id);
}, [partners.length]);
if (partners.length === 0) return;
// We duplicate the array to ensure smooth infinite scroll
const setWidth = partners.length * (LOGO_WIDTH + GAP);
controls.current = animate(x, [-setWidth, 0], {
duration: 30, // adjust speed
ease: "linear",
repeat: Infinity,
});
return () => {
controls.current?.stop();
};
}, [partners.length, x]);
if (partners.length === 0) return null;
const visible: (Partner | null)[] = [];
for (let i = 0; i < COLUMNS; i++) {
visible.push(partners[(step + i) % partners.length]);
}
// Duplicate items enough times to fill the screen seamlessly
const items = [...partners, ...partners, ...partners, ...partners, ...partners, ...partners];
return (
<div className="grid grid-cols-2 gap-x-6 gap-y-5 sm:grid-cols-4">
{visible.map((client, i) => (
<div key={`slot-${i}`} className="relative flex h-40 items-center justify-center overflow-hidden">
<AnimatePresence initial={false} mode="popLayout">
{client && (
<motion.div
key={client.id}
layoutId={`client-slot-${i}`}
className="flex flex-col items-center justify-center text-center gap-4 w-full"
initial={{ opacity: 0, filter: "blur(8px)", scale: 0.92 }}
animate={{ opacity: 1, filter: "blur(0px)", scale: 1 }}
exit={{ opacity: 0, filter: "blur(8px)", scale: 1.08 }}
transition={{
duration: 0.4,
ease: "easeInOut",
}}
>
<div className="grid h-24 w-24 shrink-0 place-items-center overflow-hidden rounded-full border border-border bg-mist shadow-sm">
{client.logo ? (
<img
src={client.logo}
alt={client.name}
className="h-full w-full object-contain p-2"
/>
) : (
<span className="text-2xl font-bold text-accent">{client.name.charAt(0)}</span>
)}
</div>
<span className="truncate w-full text-xs font-bold uppercase leading-snug tracking-wide text-foreground">
{client.name}
</span>
</motion.div>
<div
className="relative flex w-full overflow-hidden mask-edges-clients"
onMouseEnter={() => controls.current?.pause()}
onMouseLeave={() => controls.current?.play()}
>
<motion.div
style={{ x, gap: GAP }}
className="flex items-center w-max"
>
{items.map((client, i) => (
<div
key={`${client.id}-${i}`}
className="group relative flex h-32 w-[220px] shrink-0 items-center justify-center transition-all"
>
{client.logo ? (
<img
src={client.logo}
alt={client.name}
className="h-16 w-32 object-contain filter grayscale transition-all duration-300 group-hover:grayscale-0 group-hover:scale-110 opacity-70 group-hover:opacity-100"
/>
) : (
<span className="text-xl font-bold tracking-widest text-muted-foreground transition-colors group-hover:text-brand">
{client.name}
</span>
)}
</AnimatePresence>
</div>
))}
</div>
))}
</motion.div>
<style
dangerouslySetInnerHTML={{
__html: `
.mask-edges-clients {
mask-image: linear-gradient(to right, transparent, black 15%, black 85%, transparent);
-webkit-mask-image: linear-gradient(to right, transparent, black 15%, black 85%, transparent);
}
`,
}}
/>
</div>
);
}
@@ -0,0 +1,61 @@
import { useState, useEffect } from "react";
import { ArrowUp, MessageSquare } from "lucide-react";
import { useApi } from "@/hooks/useApi";
interface Organization {
whatsapp_no: string;
}
export function FloatingActionButtons() {
const [isVisible, setIsVisible] = useState(false);
const { data: org } = useApi<Organization>("org/organization");
// Show button when page is scrolled down
useEffect(() => {
const toggleVisibility = () => {
if (window.scrollY > 300) {
setIsVisible(true);
} else {
setIsVisible(false);
}
};
window.addEventListener("scroll", toggleVisibility);
return () => window.removeEventListener("scroll", toggleVisibility);
}, []);
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};
return (
<div className="fixed bottom-6 right-6 z-50 flex flex-col gap-3">
{/* WhatsApp Button */}
{org?.whatsapp_no && (
<a
href={`https://wa.me/${org.whatsapp_no}`}
target="_blank"
rel="noreferrer"
className="group flex h-12 w-12 items-center justify-center rounded-full bg-[#25D366] text-white shadow-lg transition-all hover:scale-110 hover:shadow-xl hover:shadow-[#25D366]/20"
aria-label="Chat on WhatsApp"
>
<MessageSquare className="h-6 w-6" />
</a>
)}
{/* Scroll to Top Button */}
<button
onClick={scrollToTop}
className={`group flex h-12 w-12 items-center justify-center rounded-full border border-border bg-card shadow-lg transition-all hover:scale-110 hover:border-brand/50 hover:text-brand ${
isVisible ? "translate-y-0 opacity-100" : "pointer-events-none translate-y-10 opacity-0"
}`}
aria-label="Scroll to top"
>
<ArrowUp className="h-5 w-5" />
</button>
</div>
);
}
+2 -2
View File
@@ -26,7 +26,7 @@ export function Header() {
const [open, setOpen] = useState(false);
return (
<header className="sticky top-0 z-40 border-b border-border bg-background/95 backdrop-blur-md">
<header className="fixed top-0 inset-x-0 w-full z-50 border-b border-border bg-background/95 backdrop-blur-md transition-all duration-300">
<div className="mx-auto max-w-7xl px-4 sm:px-6">
<nav className="flex h-20 items-center justify-between gap-4">
<Link to="/" className="flex items-center gap-3">
@@ -61,7 +61,7 @@ export function Header() {
<div className="flex items-center gap-2">
<Link
to="/contact"
className="hidden bg-ink px-5 py-2.5 text-sm font-semibold text-primary-foreground transition-colors hover:bg-brand sm:inline-block"
className="hidden rounded-full bg-brand px-6 py-2.5 text-sm font-bold text-primary-foreground shadow-sm transition-all hover:scale-105 hover:bg-brand/90 sm:inline-block"
>
Get a Quote
</Link>
@@ -3,7 +3,7 @@ import { animate, motion, type AnimationPlaybackControls, useMotionValue } from
import { Star } from "lucide-react";
const CARD_WIDTH = 480;
const GAP = 0;
const GAP = 24;
interface Testimonial {
id: number;
@@ -54,7 +54,7 @@ export function TestimonialsMarquee({
const items = [...testimonials, ...testimonials, ...testimonials, ...testimonials, ...testimonials];
return (
<section className="relative z-10 overflow-hidden bg-[#0A0A0A] py-24 text-primary-foreground border-y border-white/10">
<section className="relative z-10 overflow-hidden bg-mist/30 py-24 text-foreground border-y border-border/50">
<div className="mx-auto mb-16 max-w-7xl px-6">
<div className="flex flex-col justify-between gap-5 md:flex-row md:items-end">
<div>
@@ -114,7 +114,7 @@ export function TestimonialsMarquee({
function TestimonialCard({ t }: { t: Testimonial }) {
return (
<article
className="flex min-h-[260px] w-[480px] shrink-0 flex-col justify-between border border-white/10 bg-[#0F0F0F] p-8 transition-colors hover:bg-[#141414] -ml-px -mt-px"
className="flex min-h-[260px] w-[480px] shrink-0 flex-col justify-between border border-border/50 bg-card p-8 shadow-sm transition-colors hover:bg-muted/30 m-3 rounded-3xl ml-4"
>
<div>
<div className="flex items-center gap-2 mb-6 text-accent">
@@ -122,21 +122,21 @@ function TestimonialCard({ t }: { t: Testimonial }) {
{[0, 1, 2, 3, 4].map((star) => <Star key={star} className="h-4 w-4 fill-accent" aria-hidden="true" />)}
</div>
</div>
<blockquote className="text-[17px] font-medium leading-[1.6] tracking-tight text-white/90">
<blockquote className="text-[17px] font-medium leading-[1.6] tracking-tight text-foreground">
{t.testimonial}
</blockquote>
</div>
<footer className="mt-8 flex items-center gap-4">
{t.image ? (
<img src={t.image} alt={t.name} className="h-11 w-11 rounded-lg object-cover ring-1 ring-white/10" />
<img src={t.image} alt={t.name} className="h-11 w-11 rounded-lg object-cover ring-1 ring-border/50" />
) : (
<div className="grid h-11 w-11 place-items-center rounded-lg bg-white/5 ring-1 ring-white/10 text-lg font-bold text-white/80">
<div className="grid h-11 w-11 place-items-center rounded-lg bg-muted ring-1 ring-border/50 text-lg font-bold text-muted-foreground">
{t.name.charAt(0)}
</div>
)}
<div>
<p className="text-[15px] font-semibold text-white">{t.name}</p>
<p className="text-[13px] text-white/50">{t.organization}</p>
<p className="text-[15px] font-semibold text-foreground">{t.name}</p>
<p className="text-[13px] text-muted-foreground">{t.organization}</p>
</div>
</footer>
</article>
+9 -9
View File
@@ -70,21 +70,21 @@ function About() {
<div className="mx-auto grid max-w-7xl items-center gap-12 px-6 pb-24 lg:grid-cols-12">
<div className="lg:col-span-5">
<Parallax speed={0.1}>
<div className="border border-border bg-mist p-3 shadow-glass">
<div className="group overflow-hidden rounded-3xl border border-border/50 bg-card p-2 shadow-2xl transition-all hover:shadow-brand/10">
<img
src={about.cover_image }
loading="lazy"
width={1024}
height={1152}
alt={about.title}
className="aspect-[4/5] w-full object-cover"
className="aspect-[4/5] w-full rounded-2xl object-cover transition duration-700 group-hover:scale-105"
/>
</div>
</Parallax>
</div>
<div className="lg:col-span-7">
<Reveal>
<h2 className="text-3xl font-bold md:text-4xl">{about.title}</h2>
<h2 className="text-4xl font-black tracking-tight md:text-5xl">{about.title}</h2>
<div className="mt-5 text-muted-foreground prose prose-invert" dangerouslySetInnerHTML={{ __html: about.about_us }} />
</Reveal>
</div>
@@ -96,8 +96,8 @@ function About() {
<section className="relative z-10">
<div className="mx-auto max-w-7xl px-6 pb-24">
<Reveal>
<p className="text-sm font-semibold uppercase tracking-[0.2em] text-brand">Vision</p>
<h2 className="mt-3 text-3xl font-bold md:text-4xl">{vision.title}</h2>
<p className="inline-flex items-center gap-2 rounded-full bg-brand/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-brand">Vision</p>
<h2 className="mt-3 text-4xl font-black tracking-tight md:text-5xl">{vision.title}</h2>
</Reveal>
<div className="mt-10 grid items-center gap-10 lg:grid-cols-12">
<div className="lg:col-span-7">
@@ -130,8 +130,8 @@ function About() {
<section className="relative z-10">
<div className="mx-auto max-w-7xl px-6 pb-24">
<Reveal>
<p className="text-sm font-semibold uppercase tracking-[0.2em] text-brand">Mission</p>
<h2 className="mt-3 text-3xl font-bold md:text-4xl">{mision.title}</h2>
<p className="inline-flex items-center gap-2 rounded-full bg-brand/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-brand">Mission</p>
<h2 className="mt-3 text-4xl font-black tracking-tight md:text-5xl">{mision.title}</h2>
</Reveal>
<div className="mt-10 grid items-center gap-10 lg:grid-cols-12">
{mision.subtitle && (
@@ -164,8 +164,8 @@ function About() {
<section className="relative z-10">
<div className="mx-auto max-w-7xl px-6 pb-24">
<Reveal>
<p className="text-sm font-semibold uppercase tracking-[0.2em] text-brand">Values</p>
<h2 className="mt-3 text-3xl font-bold md:text-4xl">What we stand for</h2>
<p className="inline-flex items-center gap-2 rounded-full bg-brand/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-brand">Values</p>
<h2 className="mt-3 text-4xl font-black tracking-tight md:text-5xl">What we stand for</h2>
<p className="mt-4 max-w-2xl text-muted-foreground">
The principles behind every machine we export, manufacture and supply.
</p>
+104 -94
View File
@@ -1,17 +1,5 @@
import { Link } from "react-router-dom";
import {
ArrowRight,
Building2,
Factory,
Headphones,
Leaf,
Quote,
Settings2,
ShieldCheck,
Star,
Wrench,
Zap,
} from "lucide-react";
import { Star, ArrowRight } from "lucide-react";
import { LightField, Parallax, Reveal } from "@/components/site/Parallax";
import { OrbitalVisualization } from "@/components/site/OrbitalVisualization";
import { Button } from "@/components/ui/button";
@@ -19,7 +7,6 @@ import { ClientsMarquee } from "@/components/site/ClientsMarquee";
import { TestimonialsMarquee } from "@/components/site/TestimonialsMarquee";
import { useApi } from "@/hooks/useApi";
export default Index;
function Index() {
@@ -42,36 +29,40 @@ function Index() {
const testimonials = testimonialsList || [];
return (
<div className="relative">
<div className="relative bg-background">
<LightField />
{hero && (
<section className="relative z-10 overflow-hidden">
<div className="mx-auto grid min-h-[720px] max-w-7xl items-center gap-12 px-6 py-16 lg:grid-cols-12 lg:py-24">
<div className="lg:col-span-6">
<div className="rise flex items-center gap-4 text-xs font-bold uppercase text-brand">
<span className="h-px w-12 bg-brand" /> {hero.eyebrow || "Est. 2020 · Kohalpur, Banke"}
<div className="rise inline-flex items-center gap-3 rounded-full bg-brand/10 px-4 py-1.5 text-xs font-bold uppercase tracking-wider text-brand">
<span className="relative flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-brand opacity-75"></span>
<span className="relative inline-flex h-2 w-2 rounded-full bg-brand"></span>
</span>
{hero.eyebrow || "Est. 2020 · Kohalpur, Banke"}
</div>
<h1 className="rise-2 mt-8 text-5xl leading-[1.02] md:text-7xl">
<h1 className="rise-2 mt-8 text-5xl font-black leading-[1.05] tracking-tight md:text-7xl">
{hero.title || "Machinery built for"} <span className="text-gradient">{hero.highlight || "Nepal."}</span>
</h1>
<p className="rise-3 mt-7 max-w-xl text-xl leading-relaxed text-muted-foreground">
<p className="rise-3 mt-7 max-w-xl text-lg md:text-xl leading-relaxed text-muted-foreground">
{hero.description || "Reliable, innovative machinery solutions — exporting, manufacturing, distributing and supplying small, medium and commercial scale equipment across the nation."}
</p>
<div className="rise-3 mt-8 flex flex-wrap gap-4">
<Button asChild size="lg" className="rounded-none bg-brand px-7 shadow-none">
<div className="rise-3 mt-10 flex flex-wrap gap-4">
<Button asChild size="lg" className="h-14 rounded-full bg-brand px-8 text-base shadow-lg shadow-brand/20 transition-all hover:scale-105 hover:bg-brand/90">
<Link to="/products">Explore Products</Link>
</Button>
<Button asChild size="lg" variant="outline" className="rounded-none bg-background px-7">
<Button asChild size="lg" variant="outline" className="h-14 rounded-full bg-background px-8 text-base border-border/50 hover:bg-muted transition-all hover:scale-105">
<Link to="/projects-events">View Projects</Link>
</Button>
</div>
{stats.length > 0 && (
<div className="rise-3 mt-14 grid max-w-xl grid-cols-3 gap-5 border-t border-border pt-7">
<div className="rise-3 mt-16 grid max-w-xl grid-cols-3 gap-6 border-t border-border/40 pt-8">
{stats.map((st) => (
<div key={st.id}>
<p className="font-display text-3xl font-bold">{st.stats}{st.title.includes('delivery') ? '%' : '+'}</p>
<p className="mt-1 text-xs text-muted-foreground">{st.title}</p>
<div key={st.id} className="group">
<p className="font-display text-3xl font-black tracking-tight text-foreground transition-colors group-hover:text-brand">{st.stats}{st.title.includes('delivery') ? '%' : '+'}</p>
<p className="mt-1 text-sm font-medium text-muted-foreground">{st.title}</p>
</div>
))}
</div>
@@ -79,23 +70,22 @@ function Index() {
</div>
<div className="relative min-h-[480px] lg:col-span-6">
<div className="absolute -right-6 top-0 h-20 w-32 border-r border-t border-brand/40" aria-hidden="true" />
<div className="absolute inset-4 right-0 md:left-10">
<div className="absolute inset-0 right-0 md:left-10">
<Parallax speed={0.06}>
<div className="relative overflow-hidden border border-border bg-mist p-3 shadow-glass">
<div className="group relative overflow-hidden rounded-3xl border border-border/40 bg-card p-2 shadow-2xl transition-all hover:shadow-brand/10">
<img
src={hero.image }
src={hero.image}
width={1024}
height={1280}
alt="Featured equipment"
className="h-[440px] w-full object-cover md:h-[540px]"
className="h-[440px] w-full rounded-2xl object-cover transition duration-700 group-hover:scale-105 md:h-[580px]"
/>
<div className="absolute inset-x-3 bottom-3 flex items-end justify-between bg-ink/90 p-5 text-primary-foreground">
<div className="absolute inset-x-4 bottom-4 flex items-end justify-between rounded-xl bg-ink/90 p-6 text-primary-foreground backdrop-blur-md">
<div>
<p className="text-xs font-bold uppercase text-primary-foreground/60">Featured equipment</p>
<p className="mt-1 font-display text-lg">{hero.featured_text || "Commercial systems"}</p>
<p className="text-xs font-bold uppercase tracking-widest text-primary-foreground/60">Featured equipment</p>
<p className="mt-2 font-display text-xl font-bold">{hero.featured_text || "Commercial systems"}</p>
</div>
<span className="font-display text-3xl text-accent">01</span>
<span className="font-display text-4xl font-black text-accent opacity-50">01</span>
</div>
</div>
</Parallax>
@@ -106,17 +96,17 @@ function Index() {
)}
{marquee.length > 0 && (
<div className="relative z-10 flex overflow-hidden border-y border-border bg-ink py-6">
<div className="relative z-10 flex overflow-hidden border-y border-border bg-card py-6">
<div className="animate-marquee flex whitespace-nowrap">
{[0, 1, 2, 3].map((i) => (
<div
key={i}
className="flex items-center gap-12 pr-12 text-xl md:text-2xl font-black uppercase tracking-[0.1em] text-white"
className="flex items-center gap-12 pr-12 text-xl font-black uppercase tracking-[0.1em] text-foreground md:text-2xl"
>
{marquee.map((m) => (
<span key={m.id} className="flex items-center gap-12">
<span>{m.title}</span>
<Star className="h-6 w-6 text-brand fill-brand" />
<Star className="h-6 w-6 fill-brand text-brand" />
</span>
))}
</div>
@@ -126,13 +116,15 @@ function Index() {
)}
{partners.length > 0 && (
<section className="relative z-10 overflow-hidden border-y border-border bg-mist/60">
<section className="relative z-10 overflow-hidden border-b border-border bg-mist/30">
<div className="mx-auto grid max-w-7xl items-center gap-14 px-6 py-24 lg:grid-cols-12">
<div className="lg:col-span-5">
<Reveal>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-accent">Our clients</p>
<h2 className="mt-3 text-4xl font-bold">Built around the people who produce.</h2>
<p className="mt-5 max-w-lg leading-relaxed text-muted-foreground">
<div className="inline-flex items-center gap-2 rounded-full bg-accent/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-accent">
Our clients
</div>
<h2 className="mt-6 text-4xl font-black tracking-tight md:text-5xl">Built around the people who produce.</h2>
<p className="mt-6 max-w-lg text-lg leading-relaxed text-muted-foreground">
We work with ambitious enterprises across agriculture, food production, construction,
utilities and commercial manufacturing.
</p>
@@ -140,8 +132,10 @@ function Index() {
</div>
<div className="lg:col-span-7">
<Parallax speed={0.06}>
<ClientsMarquee partners={partners} />
<Parallax speed={0.04}>
<div>
<ClientsMarquee partners={partners} />
</div>
</Parallax>
</div>
</div>
@@ -150,38 +144,39 @@ function Index() {
{whatWeDo.length > 0 && (
<section className="relative z-10">
<div className="mx-auto max-w-7xl px-6 py-24">
<div className="mb-12 flex items-end justify-between">
<div className="mx-auto max-w-7xl px-6 py-32">
<div className="mb-16 flex flex-col items-start justify-between gap-6 md:flex-row md:items-end">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-accent">
<div className="inline-flex items-center gap-2 rounded-full bg-accent/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-accent">
What we do
</p>
<h2 className="mt-3 text-4xl font-bold">Machinery, end to end</h2>
</div>
<h2 className="mt-6 text-4xl font-black tracking-tight md:text-5xl">Machinery, end to end</h2>
</div>
<Link
to="/products"
className="hidden text-sm font-semibold text-brand hover:underline sm:inline"
>
See all products →
</Link>
<Button asChild variant="ghost" className="rounded-full font-bold text-brand hover:bg-brand/10 hover:text-brand">
<Link to="/products" className="flex items-center gap-2">
See all products <ArrowRight className="h-4 w-4" />
</Link>
</Button>
</div>
<div className="grid gap-6 md:grid-cols-3">
<div className="grid gap-8 md:grid-cols-3">
{whatWeDo.map((c, i) => (
<Reveal key={c.id} delay={i * 90}>
<div className="group h-full overflow-hidden border border-border bg-background transition hover:border-brand">
<div className="group flex h-full flex-col overflow-hidden rounded-3xl border border-border/50 bg-card shadow-lg transition-all hover:-translate-y-1 hover:shadow-xl hover:shadow-brand/5">
{c.cover_image && (
<img
src={c.cover_image}
loading="lazy"
width={1024}
height={768}
alt={c.title}
className="aspect-[4/3] w-full object-cover transition duration-500 group-hover:scale-[1.02]"
/>
<div className="overflow-hidden">
<img
src={c.cover_image}
loading="lazy"
width={1024}
height={768}
alt={c.title}
className="aspect-[4/3] w-full object-cover transition-transform duration-700 group-hover:scale-105"
/>
</div>
)}
<div className="p-7">
<h3 className="text-xl font-bold">{c.title}</h3>
<div className="mt-2 text-sm text-muted-foreground prose prose-invert" dangerouslySetInnerHTML={{ __html: c.what_we_do }} />
<div className="flex flex-1 flex-col p-8">
<h3 className="text-2xl font-bold tracking-tight text-foreground">{c.title}</h3>
<div className="mt-4 text-muted-foreground prose prose-invert line-clamp-4" dangerouslySetInnerHTML={{ __html: c.what_we_do }} />
</div>
</div>
</Reveal>
@@ -192,26 +187,28 @@ function Index() {
)}
{services.length > 0 && (
<section className="relative z-10">
<div className="mx-auto max-w-7xl px-6 py-24">
<section className="relative z-10 border-y border-border bg-mist/30">
<div className="mx-auto max-w-7xl px-6 py-32">
<Reveal>
<div className="grid gap-6 md:grid-cols-[1.1fr_2fr] md:items-end">
<div className="grid gap-8 md:grid-cols-[1fr_1.5fr] md:items-end">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-accent">Why Udhamsil</p>
<h2 className="mt-3 text-4xl font-bold">From requirement to reliable output.</h2>
<div className="inline-flex items-center gap-2 rounded-full bg-accent/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-accent">
Why Udhamsil
</div>
<h2 className="mt-6 text-4xl font-black tracking-tight md:text-5xl">From requirement to reliable output.</h2>
</div>
<p className="max-w-2xl text-muted-foreground md:justify-self-end">
<p className="max-w-xl text-lg leading-relaxed text-muted-foreground md:justify-self-end">
One accountable team helps you choose, receive and keep the right machinery running.
</p>
</div>
</Reveal>
<div className="mt-12 grid gap-px overflow-hidden border border-border bg-border sm:grid-cols-2 lg:grid-cols-4">
<div className="mt-16 grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
{services.map((step, index) => (
<Reveal key={step.id} delay={index * 70}>
<div className="h-full bg-background p-7">
<span className="font-display text-sm font-bold text-accent">{(index + 1).toString().padStart(2, "0")}</span>
<h3 className="mt-8 text-xl font-bold">{step.name}</h3>
<div className="mt-3 text-sm leading-relaxed text-muted-foreground prose prose-invert" dangerouslySetInnerHTML={{ __html: step.description }} />
<div className="group relative flex h-full flex-col rounded-3xl border border-border/50 bg-card p-8 shadow-lg transition-all hover:border-brand/30 hover:bg-muted/50">
<span className="font-display text-5xl font-black text-brand/10 transition-colors group-hover:text-brand/20">{(index + 1).toString().padStart(2, "0")}</span>
<h3 className="mt-6 text-xl font-bold tracking-tight">{step.name}</h3>
<div className="mt-4 text-sm leading-relaxed text-muted-foreground prose prose-invert" dangerouslySetInnerHTML={{ __html: step.description }} />
</div>
</Reveal>
))}
@@ -221,13 +218,15 @@ function Index() {
)}
{sisterCompanies.length > 0 && (
<section className="relative z-10 overflow-hidden bg-mist/30">
<div className="mx-auto max-w-7xl px-6 py-24">
<section className="relative z-10 overflow-hidden bg-background">
<div className="mx-auto max-w-7xl px-6 py-32">
<Reveal>
<div className="mx-auto max-w-2xl text-center">
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-accent">Our sister companies</p>
<h2 className="mt-3 text-4xl font-bold">One group, connected capability.</h2>
<p className="mt-4 text-muted-foreground">A growing ecosystem designed to support enterprise from machinery to long-term operations.</p>
<div className="inline-flex items-center gap-2 rounded-full bg-accent/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-accent">
Ecosystem
</div>
<h2 className="mt-6 text-4xl font-black tracking-tight md:text-5xl">One group, connected capability.</h2>
<p className="mt-6 text-lg text-muted-foreground">A growing network designed to support enterprise from machinery to long-term operations.</p>
</div>
</Reveal>
<div className="mt-16">
@@ -241,25 +240,36 @@ function Index() {
<TestimonialsMarquee testimonials={testimonials} />
)}
<section className="relative z-10 border-y border-border bg-mist/60">
<div className="mx-auto max-w-7xl px-6 py-20 lg:items-center text-center">
<section className="relative z-10 border-t border-border/50 bg-gradient-to-b from-transparent to-mist/50">
<div className="mx-auto max-w-7xl px-6 py-32 text-center lg:py-40">
<Reveal>
<div className="border border-border bg-background px-8 py-16">
<h2 className="text-3xl font-bold md:text-4xl">
<div className="mx-auto max-w-4xl">
<div className="inline-flex items-center gap-2 rounded-full bg-brand/10 px-4 py-1.5 text-xs font-bold uppercase tracking-widest text-brand">
<span className="relative flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-brand opacity-75"></span>
<span className="relative inline-flex h-2 w-2 rounded-full bg-brand"></span>
</span>
Ready to scale
</div>
<h2 className="mt-8 text-4xl font-black tracking-tight text-foreground md:text-6xl md:leading-[1.1]">
Need a machine spec'd for your output?
</h2>
<p className="mx-auto mt-4 max-w-xl text-muted-foreground">
<p className="mx-auto mt-6 max-w-2xl text-xl leading-relaxed text-muted-foreground">
Tell us your scale and target production — our Banke team responds with a tailored
recommendation.
recommendation and pricing.
</p>
<Button asChild size="lg" className="mt-8 rounded-none bg-brand">
<Link to="/contact">Get a Quote</Link>
</Button>
<div className="mt-10 flex flex-col items-center justify-center gap-4 sm:flex-row">
<Button asChild size="lg" className="h-14 w-full sm:w-auto rounded-full bg-brand px-10 text-base font-bold shadow-xl shadow-brand/20 transition-all hover:scale-105 hover:bg-brand/90">
<Link to="/contact">Get a Quote</Link>
</Button>
<Button asChild size="lg" variant="ghost" className="h-14 w-full sm:w-auto rounded-full px-8 text-base font-bold transition-all hover:bg-muted">
<Link to="/products">Browse Catalogue</Link>
</Button>
</div>
</div>
</Reveal>
</div>
</section>
</div>
);
}
+3 -1
View File
@@ -2,15 +2,17 @@
import { Outlet } from "react-router-dom";
import { Header } from "../components/site/Header";
import { Footer } from "../components/site/Footer";
import { FloatingActionButtons } from "../components/site/FloatingActionButtons";
export default function Layout() {
return (
<div className="relative flex min-h-screen flex-col overflow-x-hidden bg-background">
<Header />
<main className="flex-1">
<main className="flex-1 pt-20">
<Outlet />
</main>
<Footer />
<FloatingActionButtons />
</div>
);
}
+21 -15
View File
@@ -35,28 +35,34 @@ function Products() {
/>
<section className="relative z-10">
<div className="mx-auto max-w-7xl space-y-8 px-6 pb-24">
<div className="mx-auto max-w-7xl space-y-12 px-6 pb-24">
{products?.map((product, i) => (
<Reveal key={product.id} delay={i * 80}>
<div className="grid items-center gap-8 border-y border-border bg-background py-8 md:grid-cols-2">
<div className="group grid items-center gap-8 overflow-hidden rounded-3xl border border-border/50 bg-card p-6 shadow-lg transition-all hover:shadow-xl hover:shadow-brand/5 md:grid-cols-2 md:gap-12 md:p-10">
{product.image && (
<img
src={product.image}
loading="lazy"
width={1024}
height={768}
alt={`${product.name} machinery`}
className="aspect-[4/3] w-full object-cover"
/>
<div className="overflow-hidden rounded-2xl shadow-md">
<img
src={product.image}
loading="lazy"
width={1024}
height={768}
alt={`${product.name} machinery`}
className="aspect-[4/3] w-full object-cover transition-transform duration-700 group-hover:scale-105"
/>
</div>
)}
<div>
<h2 className="text-2xl font-bold md:text-3xl">{product.name}</h2>
<h2 className="text-3xl font-black tracking-tight text-foreground md:text-4xl">{product.name}</h2>
{product.features && product.features.length > 0 && (
<ul className="mt-5 grid gap-2 text-sm text-muted-foreground sm:grid-cols-2">
<ul className="mt-8 grid gap-4 text-base text-muted-foreground sm:grid-cols-2">
{product.features.map((feature) => (
<li key={feature.id} className="flex items-center gap-2">
<span className="h-1.5 w-1.5 rounded-full bg-accent" />
{feature.name}
<li key={feature.id} className="flex items-center gap-3">
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-brand/10 text-brand">
<svg className="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={3}>
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
</svg>
</span>
<span className="font-medium">{feature.name}</span>
</li>
))}
</ul>
+3 -3
View File
@@ -84,7 +84,7 @@ function ProjectsEvents() {
<div className="mx-auto grid max-w-7xl gap-6 px-6 pb-24 md:grid-cols-3">
{entries.map((e, i) => (
<Reveal key={e.id} delay={i * 80}>
<article className="group h-full overflow-hidden border border-border bg-background transition hover:border-brand">
<article className="group flex h-full flex-col overflow-hidden rounded-3xl border border-border/50 bg-card shadow-lg transition-all hover:-translate-y-1 hover:shadow-xl hover:shadow-brand/5">
{e.image && (
<img
src={e.image}
@@ -92,11 +92,11 @@ function ProjectsEvents() {
width={1024}
height={768}
alt={e.title}
className="aspect-[4/3] w-full object-cover transition duration-500 group-hover:scale-[1.02]"
className="aspect-[4/3] w-full object-cover transition-transform duration-700 group-hover:scale-105"
/>
)}
<div className="p-6">
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-accent">
<p className="inline-flex items-center gap-2 rounded-full bg-accent/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-accent">
{e.year} · {e.tag}
</p>
<h2 className="mt-2 text-xl font-bold">{e.title}</h2>
-318
View File
@@ -1,318 +0,0 @@
const fs = require('fs');
const homeContent = `import { Link } from "react-router-dom";
import {
ArrowRight,
Building2,
Factory,
Headphones,
Leaf,
Quote,
Settings2,
ShieldCheck,
Star,
Wrench,
Zap,
} from "lucide-react";
import { LightField, Parallax, Reveal } from "@/components/site/Parallax";
import { Button } from "@/components/ui/button";
import { useApi } from "@/hooks/useApi";
import heroMachinery from "@/assets/hero-machinery.jpg";
export default Index;
function Index() {
const { data: heroList } = useApi("homepage/hero");
const { data: statsList } = useApi("homepage/stats");
const { data: marqueeList } = useApi("homepage/marquee");
const { data: whatWeDoList } = useApi("org/what-we-do");
const { data: partnersList } = useApi("org/partners");
const { data: sisterCompaniesList } = useApi("org/sister-companies");
const { data: servicesList } = useApi("org/services");
const { data: testimonialsList } = useApi("testimonials");
const hero = heroList?.[0] || null;
const stats = statsList || [];
const marquee = marqueeList || [];
const whatWeDo = whatWeDoList || [];
const partners = partnersList || [];
const sisterCompanies = sisterCompaniesList || [];
const services = servicesList || [];
const testimonials = testimonialsList || [];
return (
<div className="relative">
<LightField />
{hero && (
<section className="relative z-10 overflow-hidden">
<div className="mx-auto grid min-h-[720px] max-w-7xl items-center gap-12 px-6 py-16 lg:grid-cols-12 lg:py-24">
<div className="lg:col-span-6">
<div className="rise flex items-center gap-4 text-xs font-bold uppercase text-brand">
<span className="h-px w-12 bg-brand" /> {hero.eyebrow || "Est. 2020 · Kohalpur, Banke"}
</div>
<h1 className="rise-2 mt-8 text-5xl leading-[1.02] md:text-7xl">
{hero.title || "Machinery built for"} <span className="text-gradient">{hero.highlight || "Nepal."}</span>
</h1>
<p className="rise-3 mt-7 max-w-xl text-xl leading-relaxed text-muted-foreground">
{hero.description || "Reliable, innovative machinery solutions — exporting, manufacturing, distributing and supplying small, medium and commercial scale equipment across the nation."}
</p>
<div className="rise-3 mt-8 flex flex-wrap gap-4">
<Button asChild size="lg" className="rounded-none bg-brand px-7 shadow-none">
<Link to="/products">Explore Products</Link>
</Button>
<Button asChild size="lg" variant="outline" className="rounded-none bg-background px-7">
<Link to="/projects-events">View Projects</Link>
</Button>
</div>
{stats.length > 0 && (
<div className="rise-3 mt-14 grid max-w-xl grid-cols-3 gap-5 border-t border-border pt-7">
{stats.map((st) => (
<div key={st.id}>
<p className="font-display text-3xl font-bold">{st.value}</p>
<p className="mt-1 text-xs text-muted-foreground">{st.label}</p>
</div>
))}
</div>
)}
</div>
<div className="relative min-h-[480px] lg:col-span-6">
<div className="absolute -right-6 top-0 h-20 w-32 border-r border-t border-brand/40" aria-hidden="true" />
<div className="absolute inset-4 right-0 md:left-10">
<Parallax speed={0.06}>
<div className="relative overflow-hidden border border-border bg-mist p-3 shadow-glass">
<img
src={hero.image || heroMachinery}
width={1024}
height={1280}
alt="Featured equipment"
className="h-[440px] w-full object-cover md:h-[540px]"
/>
<div className="absolute inset-x-3 bottom-3 flex items-end justify-between bg-ink/90 p-5 text-primary-foreground">
<div>
<p className="text-xs font-bold uppercase text-primary-foreground/60">Featured equipment</p>
<p className="mt-1 font-display text-lg">{hero.featured_text || "Commercial systems"}</p>
</div>
<span className="font-display text-3xl text-accent">01</span>
</div>
</div>
</Parallax>
</div>
</div>
</div>
</section>
)}
{marquee.length > 0 && (
<div className="relative z-10 overflow-hidden border-y border-border bg-background/60 py-4">
<div className="animate-marquee flex whitespace-nowrap">
{[0, 1].map((i) => (
<div
key={i}
className="flex gap-12 pr-12 text-sm font-semibold uppercase tracking-[0.2em] text-muted-foreground"
>
{marquee.map((m) => (
<span key={m.id}>
<span>{m.text}</span><span className="text-accent ml-12">/</span>
</span>
))}
</div>
))}
</div>
</div>
)}
{whatWeDo.length > 0 && (
<section className="relative z-10">
<div className="mx-auto max-w-7xl px-6 py-24">
<div className="mb-12 flex items-end justify-between">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-accent">
What we do
</p>
<h2 className="mt-3 text-4xl font-bold">Machinery, end to end</h2>
</div>
<Link
to="/products"
className="hidden text-sm font-semibold text-brand hover:underline sm:inline"
>
See all products →
</Link>
</div>
<div className="grid gap-6 md:grid-cols-3">
{whatWeDo.map((c, i) => (
<Reveal key={c.id} delay={i * 90}>
<div className="group h-full overflow-hidden border border-border bg-background transition hover:border-brand">
{c.cover_image && (
<img
src={c.cover_image}
loading="lazy"
width={1024}
height={768}
alt={c.title}
className="aspect-[4/3] w-full object-cover transition duration-500 group-hover:scale-[1.02]"
/>
)}
<div className="p-7">
<h3 className="text-xl font-bold">{c.title}</h3>
<div className="mt-2 text-sm text-muted-foreground prose prose-invert" dangerouslySetInnerHTML={{ __html: c.what_we_do }} />
</div>
</div>
</Reveal>
))}
</div>
</div>
</section>
)}
{partners.length > 0 && (
<section className="relative z-10 overflow-hidden border-y border-border bg-mist/60">
<div className="mx-auto grid max-w-7xl items-center gap-14 px-6 py-24 lg:grid-cols-12">
<div className="lg:col-span-5">
<Reveal>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-accent">Our clients</p>
<h2 className="mt-3 text-4xl font-bold">Built around the people who produce.</h2>
<p className="mt-5 max-w-lg leading-relaxed text-muted-foreground">
We work with ambitious enterprises across agriculture, food production, construction,
utilities and commercial manufacturing.
</p>
</Reveal>
</div>
<div className="lg:col-span-7">
<Parallax speed={0.06}>
<div className="grid grid-cols-3 gap-6">
{partners.map((p) => (
<div key={p.id} className="flex flex-col items-center justify-center p-4 border border-border bg-background shadow-glass">
{p.logo && <img src={p.logo} alt={p.name} className="h-12 object-contain" />}
<span className="mt-2 text-xs font-semibold text-center">{p.name}</span>
</div>
))}
</div>
</Parallax>
</div>
</div>
</section>
)}
{services.length > 0 && (
<section className="relative z-10">
<div className="mx-auto max-w-7xl px-6 py-24">
<Reveal>
<div className="grid gap-6 md:grid-cols-[1.1fr_2fr] md:items-end">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-accent">Why Udhamsil</p>
<h2 className="mt-3 text-4xl font-bold">From requirement to reliable output.</h2>
</div>
<p className="max-w-2xl text-muted-foreground md:justify-self-end">
One accountable team helps you choose, receive and keep the right machinery running.
</p>
</div>
</Reveal>
<div className="mt-12 grid gap-px overflow-hidden border border-border bg-border sm:grid-cols-2 lg:grid-cols-4">
{services.map((step, index) => (
<Reveal key={step.id} delay={index * 70}>
<div className="h-full bg-background p-7">
<span className="font-display text-sm font-bold text-accent">{(index + 1).toString().padStart(2, "0")}</span>
<h3 className="mt-8 text-xl font-bold">{step.name}</h3>
<div className="mt-3 text-sm leading-relaxed text-muted-foreground prose prose-invert" dangerouslySetInnerHTML={{ __html: step.description }} />
</div>
</Reveal>
))}
</div>
</div>
</section>
)}
{testimonials.length > 0 && (
<section className="relative z-10 bg-ink text-primary-foreground">
<div className="mx-auto max-w-7xl px-6 py-24">
<Reveal>
<div className="flex flex-col justify-between gap-5 md:flex-row md:items-end">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-accent">Client voices</p>
<h2 className="mt-3 text-4xl font-bold">Confidence earned on the ground.</h2>
</div>
</div>
</Reveal>
<div className="mt-12 grid gap-6 lg:grid-cols-3">
{testimonials.map((item, index) => (
<Reveal key={item.id} delay={index * 90}>
<article className="h-full border border-primary-foreground/15 bg-primary-foreground/5 p-7">
<div className="flex items-center justify-between">
<div className="flex gap-1">
{[0, 1, 2, 3, 4].map((star) => <Star key={star} className="h-4 w-4 fill-accent text-accent" aria-hidden="true" />)}
</div>
<Quote className="h-7 w-7 text-accent/60" aria-hidden="true" />
</div>
<blockquote className="mt-8 text-lg leading-relaxed">“{item.testimonial}”</blockquote>
<footer className="mt-8 border-t border-primary-foreground/15 pt-5 flex items-center gap-4">
{item.image && <img src={item.image} alt={item.name} className="w-10 h-10 rounded-full object-cover" />}
<div>
<p className="font-semibold">{item.name}</p>
<p className="mt-1 text-sm text-primary-foreground/60">{item.organization}</p>
</div>
</footer>
</article>
</Reveal>
))}
</div>
</div>
</section>
)}
{sisterCompanies.length > 0 && (
<section className="relative z-10 overflow-hidden">
<div className="mx-auto max-w-7xl px-6 py-24">
<Reveal>
<div className="mx-auto max-w-2xl text-center">
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-accent">Our sister companies</p>
<h2 className="mt-3 text-4xl font-bold">One group, connected capability.</h2>
<p className="mt-4 text-muted-foreground">A growing ecosystem designed to support enterprise from machinery to long-term operations.</p>
</div>
</Reveal>
<div className="mt-16 grid gap-6 md:grid-cols-3">
{sisterCompanies.map((sc, index) => (
<Reveal key={sc.id} delay={index * 90}>
<article className="h-full border border-border bg-background p-7 transition hover:border-brand">
<div className="flex items-center justify-between">
<span className="flex h-11 w-11 items-center justify-center rounded-xl bg-brand/10 text-brand">
{sc.logo ? <img src={sc.logo} alt={sc.name} className="h-6 w-6 object-contain" /> : <Settings2 className="h-5 w-5" />}
</span>
</div>
<h3 className="mt-7 text-xl font-bold">
{sc.website_link ? <a href={sc.website_link} target="_blank" rel="noreferrer" className="hover:underline">{sc.name}</a> : sc.name}
</h3>
</article>
</Reveal>
))}
</div>
</div>
</section>
)}
<section className="relative z-10 border-y border-border bg-mist/60">
<div className="mx-auto max-w-7xl px-6 py-20 lg:items-center text-center">
<Reveal>
<div className="border border-border bg-background px-8 py-16">
<h2 className="text-3xl font-bold md:text-4xl">
Need a machine spec'd for your output?
</h2>
<p className="mx-auto mt-4 max-w-xl text-muted-foreground">
Tell us your scale and target production — our Banke team responds with a tailored
recommendation.
</p>
<Button asChild size="lg" className="mt-8 rounded-none bg-brand">
<Link to="/contact">Get a Quote</Link>
</Button>
</div>
</Reveal>
</div>
</section>
</div>
);
}
`;
fs.writeFileSync('src/pages/Home.tsx', homeContent);