This commit is contained in:
2026-07-23 09:45:21 +00:00
parent e388dc2cf4
commit 08816695c9
405 changed files with 13784 additions and 686 deletions

View File

@@ -1,5 +1,8 @@
import { createFileRoute, Link } from "@tanstack/react-router";
import { ArrowUpRight, Droplets, Wind, Factory, Sparkles, Gauge, ShieldCheck } from "lucide-react";
import { useState, useCallback, useEffect } from "react";
import useEmblaCarousel from "embla-carousel-react";
import Autoplay from "embla-carousel-autoplay";
export const Route = createFileRoute("/")({
head: () => ({
@@ -14,116 +17,168 @@ export const Route = createFileRoute("/")({
});
const IMG = {
nozzle: "https://promistcool.com/wp-content/uploads/2020/04/banner-sanitz.jpg",
booth: "https://promistcool.com/wp-content/uploads/2020/04/image-002.png",
humid: "https://promistcool.com/wp-content/uploads/2016/03/humidification-misting.jpg",
commercial: "https://promistcool.com/wp-content/uploads/2016/03/commercial-misting.jpg",
industrial: "https://promistcool.com/wp-content/uploads/2016/03/industrial-misting.jpg",
project1: "https://promistcool.com/wp-content/uploads/2017/04/banner4.jpg",
project2: "https://promistcool.com/wp-content/uploads/2017/04/banner2.jpg",
project3: "https://promistcool.com/wp-content/uploads/2017/04/banner3.jpg",
banner: "https://promistcool.com/wp-content/uploads/2017/04/new-banner.jpg",
nozzle: "/wp-uploads/2020/04/banner-sanitz.jpg",
booth: "/wp-uploads/2020/04/image-002.png",
humid: "/wp-uploads/2016/03/humidification-misting.jpg",
commercial: "/wp-uploads/2016/03/commercial-misting.jpg",
industrial: "/wp-uploads/2016/03/industrial-misting.jpg",
project1: "/wp-uploads/2017/04/banner4.jpg",
project2: "/wp-uploads/2017/04/banner2.jpg",
project3: "/wp-uploads/2017/04/banner3.jpg",
banner: "/wp-uploads/2017/04/new-banner.jpg",
};
const SLIDES = [
{
img: "/slide-sanitization.jpg",
title: "Sanitization Booth",
subtitle: "A turnkey solution for your disinfectant needs — engineered for continuous public use.",
cta: "View details",
ctaTo: "/products/sanitization-booth",
},
{
img: "/slide-residential.jpg",
title: "Residential Outdoor Cooling",
subtitle: "Reclaim your outdoor spaces with high-pressure misting — even when temperatures push past 45°C.",
cta: "Explore applications",
ctaTo: "/applications",
},
{
img: "/slide-humidity.jpg",
title: "Humidity & Control",
subtitle: "The most efficient way to keep the right humidity levels for industrial and commercial environments.",
cta: "Request a quote",
ctaTo: "/enquiry",
},
];
const APP_CARDS = [
{ img: IMG.humid, title: "Humidification", desc: "Commercial and industrial environments where controlled humidity or temperature drive profitability.", icon: Droplets, href: "/applications/humidification" },
{ img: IMG.commercial, title: "Commercial Outdoor Cooling", desc: "Reclaim patio dining and outdoor bars once temperatures push past 45°C.", icon: Wind, href: "/applications/commercial-outdoor-cooling" },
{ img: IMG.industrial, title: "Industrial Cooling", desc: "A safer, more productive floor — cooling employees, equipment and processes.", icon: Factory, href: "/applications/industrial-outdoor-cooling" },
];
function HeroSlider() {
const [emblaRef, emblaApi] = useEmblaCarousel(
{ loop: true, duration: 40 },
[Autoplay({ delay: 5000, stopOnInteraction: true })],
);
const [selectedIndex, setSelectedIndex] = useState(0);
const scrollTo = useCallback(
(index: number) => emblaApi && emblaApi.scrollTo(index),
[emblaApi],
);
const onSelect = useCallback(() => {
if (!emblaApi) return;
setSelectedIndex(emblaApi.selectedScrollSnap());
}, [emblaApi]);
useEffect(() => {
if (!emblaApi) return;
onSelect();
emblaApi.on("select", onSelect);
return () => {
emblaApi.off("select", onSelect);
};
}, [emblaApi, onSelect]);
return (
<section className="relative overflow-hidden">
<div ref={emblaRef} className="overflow-hidden">
<div className="flex">
{SLIDES.map((slide, i) => (
<div
key={i}
className="relative min-w-0 shrink-0 grow-0 basis-full"
>
<div className="relative h-[75vh] min-h-[500px] max-h-[800px]">
<img
src={slide.img}
alt={slide.title}
className="absolute inset-0 w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-r from-black/70 via-black/40 to-black/30" />
<div className="absolute inset-0 flex items-center">
<div className="container-page">
<div className="max-w-2xl">
<div className="inline-flex items-center gap-2 text-xs uppercase tracking-[0.25em] text-white/80 font-semibold mb-4">
<span className="block w-8 h-0.5 bg-brand-red" /> Since 1979
</div>
<h1 className="font-display text-5xl md:text-7xl lg:text-8xl font-black leading-[0.95] text-white">
{slide.title}
</h1>
<p className="mt-6 text-lg md:text-xl text-white/80 max-w-xl">
{slide.subtitle}
</p>
<div className="mt-8 flex flex-wrap gap-3">
<Link
to={slide.ctaTo as any}
className="inline-flex items-center gap-2 bg-brand-red text-white px-7 py-3.5 rounded-md text-sm font-semibold hover:opacity-90 transition-opacity"
>
{slide.cta} <ArrowUpRight className="h-4 w-4" />
</Link>
<Link
to="/contact"
className="inline-flex items-center gap-2 bg-white/10 backdrop-blur-sm text-white border border-white/30 px-7 py-3.5 rounded-md text-sm font-semibold hover:bg-white/20 transition-colors"
>
Contact us
</Link>
</div>
</div>
</div>
</div>
</div>
</div>
))}
</div>
</div>
{/* Dots */}
<div className="absolute bottom-6 left-1/2 -translate-x-1/2 flex items-center gap-2.5">
{SLIDES.map((_, i) => (
<button
key={i}
onClick={() => scrollTo(i)}
className={`rounded-full transition-all duration-300 ${
i === selectedIndex
? "w-8 h-2.5 bg-brand-red"
: "w-2.5 h-2.5 bg-white/50 hover:bg-white/80"
}`}
aria-label={`Go to slide ${i + 1}`}
/>
))}
</div>
{/* Arrows */}
<button
onClick={() => emblaApi?.scrollPrev()}
className="absolute left-4 top-1/2 -translate-y-1/2 w-11 h-11 rounded-full bg-white/10 backdrop-blur-sm border border-white/20 flex items-center justify-center text-white hover:bg-white/20 transition-colors"
aria-label="Previous slide"
>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</button>
<button
onClick={() => emblaApi?.scrollNext()}
className="absolute right-4 top-1/2 -translate-y-1/2 w-11 h-11 rounded-full bg-white/10 backdrop-blur-sm border border-white/20 flex items-center justify-center text-white hover:bg-white/20 transition-colors"
aria-label="Next slide"
>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</button>
</section>
);
}
function Home() {
return (
<>
{/* HERO */}
<section className="relative overflow-hidden border-b">
<div className="container-page grid lg:grid-cols-12 gap-10 py-16 lg:py-24 items-center">
<div className="lg:col-span-6">
<div className="inline-flex items-center gap-2 text-xs uppercase tracking-[0.25em] text-brand-blue font-semibold">
<span className="rule-blue" /> Since 1979
</div>
<h1 className="mt-6 font-display text-5xl md:text-7xl font-black leading-[0.95]">
Humidity
<br />
<span className="text-brand-blue">and</span>{" "}
<span className="text-brand-red italic">Control.</span>
</h1>
<p className="mt-6 text-lg text-muted-foreground max-w-xl">
We engineer high-pressure misting systems that cool, humidify, suppress dust and sanitize
from residential patios to industrial factories across the region.
</p>
<div className="mt-8 flex flex-wrap gap-3">
<Link to="/enquiry" className="inline-flex items-center gap-2 bg-brand-red text-white px-6 py-3.5 rounded-md text-sm font-semibold hover:opacity-90">
Request a quote <ArrowUpRight className="h-4 w-4" />
</Link>
<Link to="/products" className="inline-flex items-center gap-2 border border-foreground/20 px-6 py-3.5 rounded-md text-sm font-semibold hover:border-brand-blue hover:text-brand-blue">
Explore products
</Link>
</div>
<dl className="mt-12 grid grid-cols-3 gap-6 max-w-lg">
{[
["45+", "Years of expertise"],
["1000+", "Projects delivered"],
["70 bar", "High-pressure precision"],
].map(([k, v]) => (
<div key={k}>
<dt className="font-display text-3xl font-black text-brand-red">{k}</dt>
<dd className="text-xs uppercase tracking-wider text-muted-foreground mt-1">{v}</dd>
</div>
))}
</dl>
</div>
<div className="lg:col-span-6">
<div className="relative">
<div className="absolute -inset-4 bg-gradient-to-br from-brand-blue/10 to-brand-red/10 blur-2xl" />
<img src={IMG.nozzle} alt="Promist misting nozzle" className="relative w-full h-[520px] object-cover" />
<div className="absolute bottom-0 left-0 right-0 bg-background/90 backdrop-blur border-t border-l border-r px-6 py-4 flex items-center justify-between">
<div>
<div className="text-xs uppercase tracking-widest text-muted-foreground">Featured</div>
<div className="font-display text-xl font-bold">Sanitization Booth</div>
</div>
<Link to="/products" className="text-sm font-semibold text-brand-red inline-flex items-center gap-1">
View <ArrowUpRight className="h-4 w-4" />
</Link>
</div>
</div>
</div>
</div>
</section>
{/* APPLICATIONS */}
<section className="py-24">
<div className="container-page">
<div className="flex flex-wrap items-end justify-between gap-6 mb-14">
<div>
<span className="rule-red" />
<h2 className="mt-4 font-display text-4xl md:text-5xl font-black">Applications</h2>
<p className="mt-4 max-w-2xl text-muted-foreground">
A cost-effective solution for outdoor cooling and humidification across industrial, commercial,
residential, warehouses, greenhouses, gardens, patios, parks and amusement areas.
</p>
</div>
<Link to="/applications" className="text-sm font-semibold text-brand-blue inline-flex items-center gap-1">
All applications <ArrowUpRight className="h-4 w-4" />
</Link>
</div>
<div className="grid md:grid-cols-3 divide-y md:divide-y-0 md:divide-x border-y">
{[
{ img: IMG.humid, title: "Humidification", desc: "Commercial and industrial environments where controlled humidity or temperature drive profitability.", icon: Droplets },
{ img: IMG.commercial, title: "Commercial Outdoor Cooling", desc: "Reclaim patio dining and outdoor bars once temperatures push past 45°C.", icon: Wind },
{ img: IMG.industrial, title: "Industrial Cooling", desc: "A safer, more productive floor — cooling employees, equipment and processes.", icon: Factory },
].map((a) => (
<article key={a.title} className="p-8 group">
<div className="aspect-[4/3] overflow-hidden">
<img src={a.img} alt={a.title} className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105" />
</div>
<div className="mt-6 flex items-center gap-3">
<a.icon className="h-5 w-5 text-brand-red" />
<h3 className="font-display text-xl font-bold">{a.title}</h3>
</div>
<p className="mt-3 text-sm text-muted-foreground">{a.desc}</p>
<Link to="/applications" className="mt-5 inline-flex items-center gap-1 text-sm font-semibold text-brand-red">
Details <ArrowUpRight className="h-4 w-4" />
</Link>
</article>
))}
</div>
</div>
</section>
{/* HERO SLIDER */}
<HeroSlider />
{/* SANITIZATION BOOTH FEATURE */}
<section className="bg-muted/40 py-24 border-y">
@@ -149,7 +204,7 @@ function Home() {
</li>
))}
</ul>
<Link to="/products" className="mt-8 inline-flex items-center gap-2 bg-brand-blue text-white px-6 py-3 rounded-md text-sm font-semibold hover:opacity-90">
<Link to="/products/sanitization-booth" className="mt-8 inline-flex items-center gap-2 bg-brand-blue text-white px-6 py-3 rounded-md text-sm font-semibold hover:opacity-90">
View details <ArrowUpRight className="h-4 w-4" />
</Link>
</div>
@@ -159,6 +214,43 @@ function Home() {
</div>
</section>
{/* APPLICATIONS */}
<section className="py-24">
<div className="container-page">
<div className="flex flex-wrap items-end justify-between gap-6 mb-14">
<div>
<span className="rule-red" />
<h2 className="mt-4 font-display text-4xl md:text-5xl font-black">Applications</h2>
<p className="mt-4 max-w-2xl text-muted-foreground">
A cost-effective solution for outdoor cooling and humidification across industrial, commercial,
residential, warehouses, greenhouses, gardens, patios, parks and amusement areas.
</p>
</div>
<Link to="/applications" className="text-sm font-semibold text-brand-blue inline-flex items-center gap-1">
All applications <ArrowUpRight className="h-4 w-4" />
</Link>
</div>
<div className="grid md:grid-cols-3 divide-y md:divide-y-0 md:divide-x border-y">
{APP_CARDS.map((a) => (
<article key={a.title} className="p-8 group">
<div className="aspect-[4/3] overflow-hidden">
<img src={a.img} alt={a.title} className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105" />
</div>
<div className="mt-6 flex items-center gap-3">
<a.icon className="h-5 w-5 text-brand-red" />
<h3 className="font-display text-xl font-bold">{a.title}</h3>
</div>
<p className="mt-3 text-sm text-muted-foreground">{a.desc}</p>
<Link to={a.href} className="mt-5 inline-flex items-center gap-1 text-sm font-semibold text-brand-red">
Details <ArrowUpRight className="h-4 w-4" />
</Link>
</article>
))}
</div>
</div>
</section>
{/* 5 REASONS */}
<section className="py-24">
<div className="container-page">