Some checks failed
Build and Deploy / build (push) Has been cancelled
WARNING: This change breaks existing SEO URLs for Serbian locale. Changes: - Migrated from separate locale folders (src/app/en/, src/app/de/, etc.) to [locale] dynamic segments (src/app/[locale]/) - Serbian is now at /sr/ instead of / (root) - English at /en/, German at /de/, French at /fr/ - All components updated to generate locale-aware links - Root / now redirects to /sr (307 temporary redirect) SEO Impact: - Previously indexed Serbian URLs (/, /products, /about, /contact) will now return 404 or redirect to /sr/* URLs - This is a breaking change for SEO - Serbian pages should ideally remain at root (/) with only non-default locales getting prefix - Consider implementing 301 redirects from old URLs to maintain search engine rankings Technical Notes: - next-intl v4 with [locale] structure requires ALL locales to have the prefix (cannot have default locale at root) - Alternative approach would be separate folder structure per locale
109 lines
5.7 KiB
TypeScript
109 lines
5.7 KiB
TypeScript
"use client";
|
|
|
|
import { motion } from "framer-motion";
|
|
import { useTranslations, useLocale } from "next-intl";
|
|
|
|
export default function HowItWorks() {
|
|
const t = useTranslations("HowItWorks");
|
|
const locale = useLocale();
|
|
const steps = t.raw("steps") as Array<{ title: string; description: string }>;
|
|
|
|
return (
|
|
<section className="py-24 bg-gradient-to-b from-white to-[#faf9f7]">
|
|
<div className="container mx-auto px-4">
|
|
<motion.div
|
|
className="text-center mb-20"
|
|
initial={{ opacity: 0, y: 20 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.6 }}
|
|
>
|
|
<span className="text-xs uppercase tracking-[0.3em] text-[#c9a962] mb-4 block font-medium">
|
|
{t("title")}
|
|
</span>
|
|
<h2 className="text-4xl md:text-5xl font-medium text-[#1a1a1a]">
|
|
{t("subtitle")}
|
|
</h2>
|
|
<div className="w-24 h-1 bg-gradient-to-r from-[#c9a962] to-[#FFD700] mx-auto mt-6 rounded-full" />
|
|
</motion.div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 lg:gap-16 max-w-6xl mx-auto">
|
|
{steps.map((step, index) => (
|
|
<motion.div
|
|
key={index}
|
|
className="relative text-center group"
|
|
initial={{ opacity: 0, y: 30 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.5, delay: index * 0.15 }}
|
|
>
|
|
{index < steps.length - 1 && (
|
|
<div className="hidden md:block absolute top-16 left-[55%] w-[90%] h-[2px]">
|
|
<div className="absolute inset-0 bg-gradient-to-r from-[#c9a962]/40 to-transparent rounded-full" />
|
|
<motion.div
|
|
className="absolute inset-y-0 left-0 w-2 bg-[#FFD700] rounded-full"
|
|
initial={{ scaleX: 0 }}
|
|
whileInView={{ scaleX: 1 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.8, delay: 0.5 + index * 0.2 }}
|
|
style={{ originX: 0 }}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
<div className="relative p-8 bg-white rounded-3xl shadow-lg border border-[#f0ede8] hover:shadow-2xl hover:border-[#c9a962]/30 transition-all duration-500">
|
|
<div className="absolute -top-5 left-1/2 -translate-x-1/2">
|
|
<div className="w-14 h-14 rounded-2xl bg-gradient-to-br from-[#c9a962] to-[#FFD700] flex items-center justify-center shadow-lg">
|
|
<span className="text-white text-lg font-bold">0{index + 1}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="w-20 h-20 mx-auto mt-4 mb-6 rounded-2xl bg-gradient-to-br from-[#faf9f7] to-[#f5f0e8] flex items-center justify-center border border-[#e8e4dc] group-hover:border-[#c9a962]/50 transition-colors duration-300">
|
|
{index === 0 && (
|
|
<svg className="w-8 h-8" viewBox="0 0 24 24" fill="none" stroke="#c9a962" strokeWidth="1.5">
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09z" />
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 10.5V6a3.75 3.75 0 10-7.5 0v4.5m11.356-1.993l1.263 12c.07.665-.45 1.243-1.119 1.243H4.25a1.125 1.125 0 01-1.12-1.243l1.264-12A1.125 1.125 0 015.513 7.5h12.974c.576 0 1.059.435 1.119 1.007z" />
|
|
</svg>
|
|
)}
|
|
{index === 1 && (
|
|
<svg className="w-8 h-8" viewBox="0 0 24 24" fill="none" stroke="#c9a962" strokeWidth="1.5">
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z" />
|
|
</svg>
|
|
)}
|
|
{index === 2 && (
|
|
<svg className="w-8 h-8" viewBox="0 0 24 24" fill="#FFD700">
|
|
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
|
|
</svg>
|
|
)}
|
|
</div>
|
|
|
|
<h3 className="text-xl font-semibold text-[#1a1a1a] mb-3">{step.title}</h3>
|
|
<p className="text-[#666666] text-sm leading-relaxed max-w-xs mx-auto">
|
|
{step.description}
|
|
</p>
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
|
|
<motion.div
|
|
className="text-center mt-20"
|
|
initial={{ opacity: 0 }}
|
|
whileInView={{ opacity: 1 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.6, delay: 0.3 }}
|
|
>
|
|
<a
|
|
href={`/${locale}/products`}
|
|
className="group relative inline-flex items-center gap-3 px-12 py-5 bg-gradient-to-r from-[#1a1a1a] to-[#333333] text-white text-[13px] uppercase tracking-[0.2em] font-semibold hover:from-[#c9a962] hover:to-[#FFD700] transition-all duration-500 rounded-full shadow-lg hover:shadow-xl"
|
|
>
|
|
<span>{t("startTransformation")}</span>
|
|
<svg className="w-4 h-4 group-hover:translate-x-1 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M17.25 8.25L21 12m0 0l-3.75 3.75M21 12H3" />
|
|
</svg>
|
|
</a>
|
|
</motion.div>
|
|
</div>
|
|
</section>
|
|
);
|
|
} |