feat: implement proper i18n translations for Serbian and English

- Add comprehensive Serbian translation file (sr.json) with all UI strings
- Add comprehensive English translation file (en.json) with all UI strings
- Update Serbian root pages (/, /products, /products/[slug], /about, /contact) to use getTranslations()
- Update English pages (/en/*) to use getTranslations()
- Replace all hardcoded strings with translation keys
This commit is contained in:
Unchained
2026-03-23 18:28:00 +02:00
parent f72f32fe60
commit bcc51ce282
11 changed files with 700 additions and 577 deletions

View File

@@ -1,117 +1,113 @@
import { getTranslations } from "next-intl/server";
import Header from "@/components/layout/Header"; import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer"; import Footer from "@/components/layout/Footer";
export const metadata = { export async function generateMetadata() {
title: "About - ManoonOils", return {
description: "Learn about ManoonOils - our story, mission, and commitment to natural beauty.", title: "O nama - ManoonOils",
description: "Saznajte više o ManoonOils - naša priča, misija i posvećenost prirodnoj lepoti.",
}; };
}
export default async function AboutPage() {
const t = await getTranslations("About");
export default function AboutPage() {
return ( return (
<> <>
<Header /> <Header />
<main className="min-h-screen bg-white"> <main className="min-h-screen bg-white">
{/* Page Header */}
<div className="pt-[104px]"> <div className="pt-[104px]">
<div className="container py-12 md:py-16"> <div className="container py-12 md:py-16">
<div className="max-w-2xl mx-auto text-center"> <div className="max-w-2xl mx-auto text-center">
<span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block">Our Story</span> <span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block">
{t("subtitle")}
</span>
<h1 className="text-4xl md:text-5xl font-medium tracking-tight"> <h1 className="text-4xl md:text-5xl font-medium tracking-tight">
About ManoonOils {t("title")}
</h1> </h1>
</div> </div>
</div> </div>
</div> </div>
{/* Hero Image */}
<div className="relative h-[400px] md:h-[500px] overflow-hidden"> <div className="relative h-[400px] md:h-[500px] overflow-hidden">
<img <img
src="https://images.unsplash.com/photo-1608571423902-eed4a5ad8108?q=80&w=2000&auto=format&fit=crop" src="https://images.unsplash.com/photo-1608571423902-eed4a5ad8108?q=80&w=2000&auto=format&fit=crop"
alt="Natural oils production" alt="Proizvodnja prirodnih ulja"
className="w-full h-full object-cover" className="w-full h-full object-cover"
/> />
<div className="absolute inset-0 bg-black/20" /> <div className="absolute inset-0 bg-black/20" />
</div> </div>
{/* Content */}
<section className="py-16 md:py-24"> <section className="py-16 md:py-24">
<div className="container"> <div className="container">
<div className="max-w-3xl mx-auto"> <div className="max-w-3xl mx-auto">
{/* Introduction */}
<div className="mb-16"> <div className="mb-16">
<p className="text-xl md:text-2xl text-[#1a1a1a] leading-relaxed mb-8"> <p className="text-xl md:text-2xl text-[#1a1a1a] leading-relaxed mb-8">
ManoonOils was born from a passion for natural beauty and the belief {t("intro")}
that the best skincare comes from nature itself.
</p> </p>
<p className="text-[#666666] leading-relaxed"> <p className="text-[#666666] leading-relaxed">
We believe in the power of natural ingredients. Every oil in our {t("intro2")}
collection is carefully selected for its unique properties and
benefits. From nourishing oils that restore hair vitality to serums
that rejuvenate skin, we craft each product with love and attention
to detail.
</p> </p>
</div> </div>
{/* Values Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-12 mb-16"> <div className="grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-12 mb-16">
<div className="p-6 bg-[#f8f9fa]"> <div className="p-6 bg-[#f8f9fa]">
<h3 className="text-lg font-medium mb-3">Natural Ingredients</h3> <h3 className="text-lg font-medium mb-3">
{t("naturalIngredients")}
</h3>
<p className="text-[#666666] text-sm leading-relaxed"> <p className="text-[#666666] text-sm leading-relaxed">
We use only the finest natural ingredients, sourced ethically and sustainably {t("naturalIngredientsDesc")}
from trusted suppliers around the world.
</p> </p>
</div> </div>
<div className="p-6 bg-[#f8f9fa]"> <div className="p-6 bg-[#f8f9fa]">
<h3 className="text-lg font-medium mb-3">Cruelty-Free</h3> <h3 className="text-lg font-medium mb-3">
{t("crueltyFree")}
</h3>
<p className="text-[#666666] text-sm leading-relaxed"> <p className="text-[#666666] text-sm leading-relaxed">
Our products are never tested on animals. We believe in beauty {t("crueltyFreeDesc")}
without compromise.
</p> </p>
</div> </div>
<div className="p-6 bg-[#f8f9fa]"> <div className="p-6 bg-[#f8f9fa]">
<h3 className="text-lg font-medium mb-3">Sustainable Packaging</h3> <h3 className="text-lg font-medium mb-3">
{t("sustainablePackaging")}
</h3>
<p className="text-[#666666] text-sm leading-relaxed"> <p className="text-[#666666] text-sm leading-relaxed">
We use eco-friendly packaging materials and minimize waste {t("sustainablePackagingDesc")}
throughout our production process.
</p> </p>
</div> </div>
<div className="p-6 bg-[#f8f9fa]"> <div className="p-6 bg-[#f8f9fa]">
<h3 className="text-lg font-medium mb-3">Handcrafted Quality</h3> <h3 className="text-lg font-medium mb-3">
{t("handcraftedQuality")}
</h3>
<p className="text-[#666666] text-sm leading-relaxed"> <p className="text-[#666666] text-sm leading-relaxed">
Every bottle is handcrafted in small batches to ensure {t("handcraftedQualityDesc")}
the highest quality and freshness.
</p> </p>
</div> </div>
</div> </div>
{/* Mission */}
<div className="text-center py-12 border-t border-b border-[#e5e5e5]"> <div className="text-center py-12 border-t border-b border-[#e5e5e5]">
<span className="text-caption text-[#666666] mb-4 block">Our Mission</span> <span className="text-caption text-[#666666] mb-4 block">
{t("mission")}
</span>
<blockquote className="text-2xl md:text-3xl font-medium tracking-tight"> <blockquote className="text-2xl md:text-3xl font-medium tracking-tight">
&ldquo;To provide premium quality, natural products that enhance &ldquo;{t("missionQuote")}&rdquo;
your daily beauty routine.&rdquo;
</blockquote> </blockquote>
</div> </div>
{/* Story Section */}
<div className="mt-16"> <div className="mt-16">
<h2 className="text-2xl font-medium mb-6">Handmade with Love</h2> <h2 className="text-2xl font-medium mb-6">
{t("handmadeTitle")}
</h2>
<p className="text-[#666666] leading-relaxed mb-6"> <p className="text-[#666666] leading-relaxed mb-6">
Every bottle of ManoonOils is handcrafted with care. We small-batch {t("handmadeText1")}
produce our products to ensure the highest quality and freshness.
When you use ManoonOils, you can feel confident that you&apos;re using
something made with genuine care and expertise.
</p> </p>
<p className="text-[#666666] leading-relaxed"> <p className="text-[#666666] leading-relaxed">
Our journey began with a simple question: how can we create products {t("handmadeText2")}
that truly nurture both hair and skin? Today, we continue to innovate
while staying true to our commitment to natural, effective beauty solutions.
</p> </p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</main> </main>
<div className="pt-16"> <div className="pt-16">
<Footer /> <Footer />

View File

@@ -1,11 +1,13 @@
"use client"; "use client";
import { useState } from "react"; import { useState } from "react";
import { useTranslations } from "next-intl";
import Header from "@/components/layout/Header"; import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer"; import Footer from "@/components/layout/Footer";
import { Mail, MapPin, Truck, Check } from "lucide-react"; import { Mail, MapPin, Truck, Check } from "lucide-react";
export default function ContactPage() { export default function ContactPage() {
const t = useTranslations("Contact");
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
name: "", name: "",
email: "", email: "",
@@ -22,31 +24,31 @@ export default function ContactPage() {
<> <>
<Header /> <Header />
<main className="min-h-screen bg-white"> <main className="min-h-screen bg-white">
{/* Page Header */}
<div className="pt-[104px]"> <div className="pt-[104px]">
<div className="container py-12 md:py-16"> <div className="container py-12 md:py-16">
<div className="max-w-2xl mx-auto text-center"> <div className="max-w-2xl mx-auto text-center">
<span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block">Get in Touch</span> <span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block">
{t("subtitle")}
</span>
<h1 className="text-4xl md:text-5xl font-medium tracking-tight mb-4"> <h1 className="text-4xl md:text-5xl font-medium tracking-tight mb-4">
Contact Us {t("title")}
</h1> </h1>
<p className="text-[#666666]"> <p className="text-[#666666]">
Have questions? We&apos;d love to hear from you. {t("getInTouchDesc")}
</p> </p>
</div> </div>
</div> </div>
</div> </div>
{/* Contact Section */}
<section className="py-12 md:py-16"> <section className="py-12 md:py-16">
<div className="container"> <div className="container">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20">
{/* Contact Info */}
<div> <div>
<h2 className="text-2xl font-medium mb-6">Get in Touch</h2> <h2 className="text-2xl font-medium mb-6">
{t("getInTouch")}
</h2>
<p className="text-[#666666] mb-8 leading-relaxed"> <p className="text-[#666666] mb-8 leading-relaxed">
We&apos;re here to help! Whether you have questions about our products, {t("getInTouchDesc")}
need assistance with an order, or just want to say hello, we&apos;d love to hear from you.
</p> </p>
<div className="space-y-6"> <div className="space-y-6">
@@ -55,9 +57,9 @@ export default function ContactPage() {
<Mail className="w-5 h-5 text-[#666666]" strokeWidth={1.5} /> <Mail className="w-5 h-5 text-[#666666]" strokeWidth={1.5} />
</div> </div>
<div> <div>
<h3 className="font-medium mb-1">Email</h3> <h3 className="font-medium mb-1">{t("email")}</h3>
<p className="text-[#666666] text-sm">hello@manoonoils.com</p> <p className="text-[#666666] text-sm">hello@manoonoils.com</p>
<p className="text-[#999999] text-xs mt-1">We reply within 24 hours</p> <p className="text-[#999999] text-xs mt-1">{t("emailReply")}</p>
</div> </div>
</div> </div>
@@ -66,9 +68,9 @@ export default function ContactPage() {
<Truck className="w-5 h-5 text-[#666666]" strokeWidth={1.5} /> <Truck className="w-5 h-5 text-[#666666]" strokeWidth={1.5} />
</div> </div>
<div> <div>
<h3 className="font-medium mb-1">Shipping</h3> <h3 className="font-medium mb-1">{t("shippingTitle")}</h3>
<p className="text-[#666666] text-sm">Free shipping over 3,000 RSD</p> <p className="text-[#666666] text-sm">{t("freeShipping")}</p>
<p className="text-[#999999] text-xs mt-1">Delivered within 2-5 business days</p> <p className="text-[#999999] text-xs mt-1">{t("deliveryTime")}</p>
</div> </div>
</div> </div>
@@ -77,31 +79,30 @@ export default function ContactPage() {
<MapPin className="w-5 h-5 text-[#666666]" strokeWidth={1.5} /> <MapPin className="w-5 h-5 text-[#666666]" strokeWidth={1.5} />
</div> </div>
<div> <div>
<h3 className="font-medium mb-1">Location</h3> <h3 className="font-medium mb-1">{t("location")}</h3>
<p className="text-[#666666] text-sm">Serbia</p> <p className="text-[#666666] text-sm">{t("locationDesc")}</p>
<p className="text-[#999999] text-xs mt-1">Shipping nationwide</p> <p className="text-[#999999] text-xs mt-1">{t("worldwideShipping")}</p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{/* Contact Form */}
<div className="bg-[#f8f9fa] p-8 md:p-10"> <div className="bg-[#f8f9fa] p-8 md:p-10">
{submitted ? ( {submitted ? (
<div className="text-center py-12"> <div className="text-center py-12">
<div className="w-16 h-16 rounded-full bg-green-100 flex items-center justify-center mx-auto mb-4"> <div className="w-16 h-16 rounded-full bg-green-100 flex items-center justify-center mx-auto mb-4">
<Check className="w-8 h-8 text-green-600" strokeWidth={1.5} /> <Check className="w-8 h-8 text-green-600" strokeWidth={1.5} />
</div> </div>
<h3 className="text-xl font-medium mb-2">Thank You!</h3> <h3 className="text-xl font-medium mb-2">{t("thankYou")}</h3>
<p className="text-[#666666]"> <p className="text-[#666666]">
Your message has been sent. We&apos;ll get back to you soon. {t("thankYouDesc")}
</p> </p>
</div> </div>
) : ( ) : (
<form onSubmit={handleSubmit} className="space-y-6"> <form onSubmit={handleSubmit} className="space-y-6">
<div> <div>
<label htmlFor="name" className="block text-sm font-medium mb-2"> <label htmlFor="name" className="block text-sm font-medium mb-2">
Name {t("name")}
</label> </label>
<input <input
type="text" type="text"
@@ -110,13 +111,13 @@ export default function ContactPage() {
value={formData.name} value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })} onChange={(e) => setFormData({ ...formData, name: e.target.value })}
className="w-full px-4 py-3 bg-white border border-[#e5e5e5] focus:outline-none focus:border-black transition-colors" className="w-full px-4 py-3 bg-white border border-[#e5e5e5] focus:outline-none focus:border-black transition-colors"
placeholder="Your name" placeholder={t("namePlaceholder")}
/> />
</div> </div>
<div> <div>
<label htmlFor="email" className="block text-sm font-medium mb-2"> <label htmlFor="email" className="block text-sm font-medium mb-2">
Email {t("emailField")}
</label> </label>
<input <input
type="email" type="email"
@@ -125,13 +126,13 @@ export default function ContactPage() {
value={formData.email} value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })} onChange={(e) => setFormData({ ...formData, email: e.target.value })}
className="w-full px-4 py-3 bg-white border border-[#e5e5e5] focus:outline-none focus:border-black transition-colors" className="w-full px-4 py-3 bg-white border border-[#e5e5e5] focus:outline-none focus:border-black transition-colors"
placeholder="your@email.com" placeholder={t("emailPlaceholder")}
/> />
</div> </div>
<div> <div>
<label htmlFor="message" className="block text-sm font-medium mb-2"> <label htmlFor="message" className="block text-sm font-medium mb-2">
Message {t("message")}
</label> </label>
<textarea <textarea
id="message" id="message"
@@ -140,7 +141,7 @@ export default function ContactPage() {
value={formData.message} value={formData.message}
onChange={(e) => setFormData({ ...formData, message: e.target.value })} onChange={(e) => setFormData({ ...formData, message: e.target.value })}
className="w-full px-4 py-3 bg-white border border-[#e5e5e5] focus:outline-none focus:border-black transition-colors resize-none" className="w-full px-4 py-3 bg-white border border-[#e5e5e5] focus:outline-none focus:border-black transition-colors resize-none"
placeholder="How can we help you?" placeholder={t("messagePlaceholder")}
/> />
</div> </div>
@@ -148,7 +149,7 @@ export default function ContactPage() {
type="submit" type="submit"
className="w-full py-4 bg-black text-white text-sm uppercase tracking-[0.1em] font-medium hover:bg-[#333333] transition-colors" className="w-full py-4 bg-black text-white text-sm uppercase tracking-[0.1em] font-medium hover:bg-[#333333] transition-colors"
> >
Send Message {t("sendMessage")}
</button> </button>
</form> </form>
)} )}
@@ -157,32 +158,19 @@ export default function ContactPage() {
</div> </div>
</section> </section>
{/* FAQ Section */}
<section className="py-16 md:py-24 border-t border-[#e5e5e5]"> <section className="py-16 md:py-24 border-t border-[#e5e5e5]">
<div className="container"> <div className="container">
<div className="max-w-3xl mx-auto"> <div className="max-w-3xl mx-auto">
<h2 className="text-2xl font-medium text-center mb-12"> <h2 className="text-2xl font-medium text-center mb-12">
Frequently Asked Questions {t("faqTitle")}
</h2> </h2>
<div className="space-y-6"> <div className="space-y-6">
{[ {[
{ { q: t("faq1q"), a: t("faq1a") },
q: "How long does shipping take?", { q: t("faq2q"), a: t("faq2a") },
a: "Orders are typically delivered within 2-5 business days for domestic shipping. You'll receive a tracking number once your order ships." { q: t("faq3q"), a: t("faq3a") },
}, { q: t("faq4q"), a: t("faq4a") },
{
q: "Are your products 100% natural?",
a: "Yes! All our oils are 100% natural, cold-pressed, and free from any additives, preservatives, or artificial fragrances."
},
{
q: "What is your return policy?",
a: "We accept returns within 14 days of delivery for unopened products. Please contact us if you have any issues with your order."
},
{
q: "Do you offer wholesale?",
a: "Yes, we offer wholesale pricing for bulk orders. Please contact us at hello@manoonoils.com for more information."
}
].map((faq, index) => ( ].map((faq, index) => (
<div key={index} className="border-b border-[#e5e5e5] pb-6"> <div key={index} className="border-b border-[#e5e5e5] pb-6">
<h3 className="font-medium mb-2">{faq.q}</h3> <h3 className="font-medium mb-2">{faq.q}</h3>

View File

@@ -1,12 +1,17 @@
import { getTranslations } from "next-intl/server";
import Header from "@/components/layout/Header"; import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer"; import Footer from "@/components/layout/Footer";
export const metadata = { export async function generateMetadata() {
return {
title: "About - ManoonOils", title: "About - ManoonOils",
description: "Learn about ManoonOils - our story, mission, and commitment to natural beauty.", description: "Learn about ManoonOils - our story, mission, and commitment to natural beauty.",
}; };
}
export default async function AboutPage() {
const t = await getTranslations("About");
export default function AboutPage() {
return ( return (
<> <>
<Header /> <Header />
@@ -14,9 +19,11 @@ export default function AboutPage() {
<div className="pt-[104px]"> <div className="pt-[104px]">
<div className="container py-12 md:py-16"> <div className="container py-12 md:py-16">
<div className="max-w-2xl mx-auto text-center"> <div className="max-w-2xl mx-auto text-center">
<span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block">Our Story</span> <span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block">
{t("subtitle")}
</span>
<h1 className="text-4xl md:text-5xl font-medium tracking-tight"> <h1 className="text-4xl md:text-5xl font-medium tracking-tight">
About ManoonOils {t("title")}
</h1> </h1>
</div> </div>
</div> </div>
@@ -36,69 +43,66 @@ export default function AboutPage() {
<div className="max-w-3xl mx-auto"> <div className="max-w-3xl mx-auto">
<div className="mb-16"> <div className="mb-16">
<p className="text-xl md:text-2xl text-[#1a1a1a] leading-relaxed mb-8"> <p className="text-xl md:text-2xl text-[#1a1a1a] leading-relaxed mb-8">
ManoonOils was born from a passion for natural beauty and the belief {t("intro")}
that the best skincare comes from nature itself.
</p> </p>
<p className="text-[#666666] leading-relaxed"> <p className="text-[#666666] leading-relaxed">
We believe in the power of natural ingredients. Every oil in our {t("intro2")}
collection is carefully selected for its unique properties and
benefits. From nourishing oils that restore hair vitality to serums
that rejuvenate skin, we craft each product with love and attention
to detail.
</p> </p>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-12 mb-16"> <div className="grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-12 mb-16">
<div className="p-6 bg-[#f8f9fa]"> <div className="p-6 bg-[#f8f9fa]">
<h3 className="text-lg font-medium mb-3">Natural Ingredients</h3> <h3 className="text-lg font-medium mb-3">
{t("naturalIngredients")}
</h3>
<p className="text-[#666666] text-sm leading-relaxed"> <p className="text-[#666666] text-sm leading-relaxed">
We use only the finest natural ingredients, sourced ethically and sustainably {t("naturalIngredientsDesc")}
from trusted suppliers around the world.
</p> </p>
</div> </div>
<div className="p-6 bg-[#f8f9fa]"> <div className="p-6 bg-[#f8f9fa]">
<h3 className="text-lg font-medium mb-3">Cruelty-Free</h3> <h3 className="text-lg font-medium mb-3">
{t("crueltyFree")}
</h3>
<p className="text-[#666666] text-sm leading-relaxed"> <p className="text-[#666666] text-sm leading-relaxed">
Our products are never tested on animals. We believe in beauty {t("crueltyFreeDesc")}
without compromise.
</p> </p>
</div> </div>
<div className="p-6 bg-[#f8f9fa]"> <div className="p-6 bg-[#f8f9fa]">
<h3 className="text-lg font-medium mb-3">Sustainable Packaging</h3> <h3 className="text-lg font-medium mb-3">
{t("sustainablePackaging")}
</h3>
<p className="text-[#666666] text-sm leading-relaxed"> <p className="text-[#666666] text-sm leading-relaxed">
We use eco-friendly packaging materials and minimize waste {t("sustainablePackagingDesc")}
throughout our production process.
</p> </p>
</div> </div>
<div className="p-6 bg-[#f8f9fa]"> <div className="p-6 bg-[#f8f9fa]">
<h3 className="text-lg font-medium mb-3">Handcrafted Quality</h3> <h3 className="text-lg font-medium mb-3">
{t("handcraftedQuality")}
</h3>
<p className="text-[#666666] text-sm leading-relaxed"> <p className="text-[#666666] text-sm leading-relaxed">
Every bottle is handcrafted in small batches to ensure {t("handcraftedQualityDesc")}
the highest quality and freshness.
</p> </p>
</div> </div>
</div> </div>
<div className="text-center py-12 border-t border-b border-[#e5e5e5]"> <div className="text-center py-12 border-t border-b border-[#e5e5e5]">
<span className="text-caption text-[#666666] mb-4 block">Our Mission</span> <span className="text-caption text-[#666666] mb-4 block">
{t("mission")}
</span>
<blockquote className="text-2xl md:text-3xl font-medium tracking-tight"> <blockquote className="text-2xl md:text-3xl font-medium tracking-tight">
&ldquo;To provide premium quality, natural products that enhance &ldquo;{t("missionQuote")}&rdquo;
your daily beauty routine.&rdquo;
</blockquote> </blockquote>
</div> </div>
<div className="mt-16"> <div className="mt-16">
<h2 className="text-2xl font-medium mb-6">Handmade with Love</h2> <h2 className="text-2xl font-medium mb-6">
{t("handmadeTitle")}
</h2>
<p className="text-[#666666] leading-relaxed mb-6"> <p className="text-[#666666] leading-relaxed mb-6">
Every bottle of ManoonOils is handcrafted with care. We small-batch {t("handmadeText1")}
produce our products to ensure the highest quality and freshness.
When you use ManoonOils, you can feel confident that you&apos;re using
something made with genuine care and expertise.
</p> </p>
<p className="text-[#666666] leading-relaxed"> <p className="text-[#666666] leading-relaxed">
Our journey began with a simple question: how can we create products {t("handmadeText2")}
that truly nurture both hair and skin? Today, we continue to innovate
while staying true to our commitment to natural, effective beauty solutions.
</p> </p>
</div> </div>
</div> </div>

View File

@@ -1,11 +1,13 @@
"use client"; "use client";
import { useState } from "react"; import { useState } from "react";
import { useTranslations } from "next-intl";
import Header from "@/components/layout/Header"; import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer"; import Footer from "@/components/layout/Footer";
import { Mail, MapPin, Truck, Check } from "lucide-react"; import { Mail, MapPin, Truck, Check } from "lucide-react";
export default function ContactPage() { export default function ContactPage() {
const t = useTranslations("Contact");
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
name: "", name: "",
email: "", email: "",
@@ -25,12 +27,14 @@ export default function ContactPage() {
<div className="pt-[104px]"> <div className="pt-[104px]">
<div className="container py-12 md:py-16"> <div className="container py-12 md:py-16">
<div className="max-w-2xl mx-auto text-center"> <div className="max-w-2xl mx-auto text-center">
<span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block">Get in Touch</span> <span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block">
{t("subtitle")}
</span>
<h1 className="text-4xl md:text-5xl font-medium tracking-tight mb-4"> <h1 className="text-4xl md:text-5xl font-medium tracking-tight mb-4">
Contact Us {t("title")}
</h1> </h1>
<p className="text-[#666666]"> <p className="text-[#666666]">
Have questions? We&apos;d love to hear from you. {t("getInTouchDesc")}
</p> </p>
</div> </div>
</div> </div>
@@ -40,10 +44,11 @@ export default function ContactPage() {
<div className="container"> <div className="container">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20">
<div> <div>
<h2 className="text-2xl font-medium mb-6">Get in Touch</h2> <h2 className="text-2xl font-medium mb-6">
{t("getInTouch")}
</h2>
<p className="text-[#666666] mb-8 leading-relaxed"> <p className="text-[#666666] mb-8 leading-relaxed">
We&apos;re here to help! Whether you have questions about our products, {t("getInTouchDesc")}
need assistance with an order, or just want to say hello, we&apos;d love to hear from you.
</p> </p>
<div className="space-y-6"> <div className="space-y-6">
@@ -52,9 +57,9 @@ export default function ContactPage() {
<Mail className="w-5 h-5 text-[#666666]" strokeWidth={1.5} /> <Mail className="w-5 h-5 text-[#666666]" strokeWidth={1.5} />
</div> </div>
<div> <div>
<h3 className="font-medium mb-1">Email</h3> <h3 className="font-medium mb-1">{t("email")}</h3>
<p className="text-[#666666] text-sm">hello@manoonoils.com</p> <p className="text-[#666666] text-sm">hello@manoonoils.com</p>
<p className="text-[#999999] text-xs mt-1">We reply within 24 hours</p> <p className="text-[#999999] text-xs mt-1">{t("emailReply")}</p>
</div> </div>
</div> </div>
@@ -63,9 +68,9 @@ export default function ContactPage() {
<Truck className="w-5 h-5 text-[#666666]" strokeWidth={1.5} /> <Truck className="w-5 h-5 text-[#666666]" strokeWidth={1.5} />
</div> </div>
<div> <div>
<h3 className="font-medium mb-1">Shipping</h3> <h3 className="font-medium mb-1">{t("shippingTitle")}</h3>
<p className="text-[#666666] text-sm">Free shipping over £50</p> <p className="text-[#666666] text-sm">{t("freeShipping")}</p>
<p className="text-[#999999] text-xs mt-1">Delivered within 2-5 business days</p> <p className="text-[#999999] text-xs mt-1">{t("deliveryTime")}</p>
</div> </div>
</div> </div>
@@ -74,9 +79,9 @@ export default function ContactPage() {
<MapPin className="w-5 h-5 text-[#666666]" strokeWidth={1.5} /> <MapPin className="w-5 h-5 text-[#666666]" strokeWidth={1.5} />
</div> </div>
<div> <div>
<h3 className="font-medium mb-1">Location</h3> <h3 className="font-medium mb-1">{t("location")}</h3>
<p className="text-[#666666] text-sm">Serbia</p> <p className="text-[#666666] text-sm">{t("locationDesc")}</p>
<p className="text-[#999999] text-xs mt-1">Shipping worldwide</p> <p className="text-[#999999] text-xs mt-1">{t("worldwideShipping")}</p>
</div> </div>
</div> </div>
</div> </div>
@@ -88,16 +93,16 @@ export default function ContactPage() {
<div className="w-16 h-16 rounded-full bg-green-100 flex items-center justify-center mx-auto mb-4"> <div className="w-16 h-16 rounded-full bg-green-100 flex items-center justify-center mx-auto mb-4">
<Check className="w-8 h-8 text-green-600" strokeWidth={1.5} /> <Check className="w-8 h-8 text-green-600" strokeWidth={1.5} />
</div> </div>
<h3 className="text-xl font-medium mb-2">Thank You!</h3> <h3 className="text-xl font-medium mb-2">{t("thankYou")}</h3>
<p className="text-[#666666]"> <p className="text-[#666666]">
Your message has been sent. We&apos;ll get back to you soon. {t("thankYouDesc")}
</p> </p>
</div> </div>
) : ( ) : (
<form onSubmit={handleSubmit} className="space-y-6"> <form onSubmit={handleSubmit} className="space-y-6">
<div> <div>
<label htmlFor="name" className="block text-sm font-medium mb-2"> <label htmlFor="name" className="block text-sm font-medium mb-2">
Name {t("name")}
</label> </label>
<input <input
type="text" type="text"
@@ -106,13 +111,13 @@ export default function ContactPage() {
value={formData.name} value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })} onChange={(e) => setFormData({ ...formData, name: e.target.value })}
className="w-full px-4 py-3 bg-white border border-[#e5e5e5] focus:outline-none focus:border-black transition-colors" className="w-full px-4 py-3 bg-white border border-[#e5e5e5] focus:outline-none focus:border-black transition-colors"
placeholder="Your name" placeholder={t("namePlaceholder")}
/> />
</div> </div>
<div> <div>
<label htmlFor="email" className="block text-sm font-medium mb-2"> <label htmlFor="email" className="block text-sm font-medium mb-2">
Email {t("emailField")}
</label> </label>
<input <input
type="email" type="email"
@@ -121,13 +126,13 @@ export default function ContactPage() {
value={formData.email} value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })} onChange={(e) => setFormData({ ...formData, email: e.target.value })}
className="w-full px-4 py-3 bg-white border border-[#e5e5e5] focus:outline-none focus:border-black transition-colors" className="w-full px-4 py-3 bg-white border border-[#e5e5e5] focus:outline-none focus:border-black transition-colors"
placeholder="your@email.com" placeholder={t("emailPlaceholder")}
/> />
</div> </div>
<div> <div>
<label htmlFor="message" className="block text-sm font-medium mb-2"> <label htmlFor="message" className="block text-sm font-medium mb-2">
Message {t("message")}
</label> </label>
<textarea <textarea
id="message" id="message"
@@ -136,7 +141,7 @@ export default function ContactPage() {
value={formData.message} value={formData.message}
onChange={(e) => setFormData({ ...formData, message: e.target.value })} onChange={(e) => setFormData({ ...formData, message: e.target.value })}
className="w-full px-4 py-3 bg-white border border-[#e5e5e5] focus:outline-none focus:border-black transition-colors resize-none" className="w-full px-4 py-3 bg-white border border-[#e5e5e5] focus:outline-none focus:border-black transition-colors resize-none"
placeholder="How can we help you?" placeholder={t("messagePlaceholder")}
/> />
</div> </div>
@@ -144,7 +149,7 @@ export default function ContactPage() {
type="submit" type="submit"
className="w-full py-4 bg-black text-white text-sm uppercase tracking-[0.1em] font-medium hover:bg-[#333333] transition-colors" className="w-full py-4 bg-black text-white text-sm uppercase tracking-[0.1em] font-medium hover:bg-[#333333] transition-colors"
> >
Send Message {t("sendMessage")}
</button> </button>
</form> </form>
)} )}
@@ -157,27 +162,15 @@ export default function ContactPage() {
<div className="container"> <div className="container">
<div className="max-w-3xl mx-auto"> <div className="max-w-3xl mx-auto">
<h2 className="text-2xl font-medium text-center mb-12"> <h2 className="text-2xl font-medium text-center mb-12">
Frequently Asked Questions {t("faqTitle")}
</h2> </h2>
<div className="space-y-6"> <div className="space-y-6">
{[ {[
{ { q: t("faq1q"), a: t("faq1a") },
q: "How long does shipping take?", { q: t("faq2q"), a: t("faq2a") },
a: "Orders are typically delivered within 2-5 business days for domestic shipping. You'll receive a tracking number once your order ships." { q: t("faq3q"), a: t("faq3a") },
}, { q: t("faq4q"), a: t("faq4a") },
{
q: "Are your products 100% natural?",
a: "Yes! All our oils are 100% natural, cold-pressed, and free from any additives, preservatives, or artificial fragrances."
},
{
q: "What is your return policy?",
a: "We accept returns within 14 days of delivery for unopened products. Please contact us if you have any issues with your order."
},
{
q: "Do you offer wholesale?",
a: "Yes, we offer wholesale pricing for bulk orders. Please contact us at hello@manoonoils.com for more information."
}
].map((faq, index) => ( ].map((faq, index) => (
<div key={index} className="border-b border-[#e5e5e5] pb-6"> <div key={index} className="border-b border-[#e5e5e5] pb-6">
<h3 className="font-medium mb-2">{faq.q}</h3> <h3 className="font-medium mb-2">{faq.q}</h3>

View File

@@ -1,4 +1,5 @@
import { getProducts } from "@/lib/saleor"; import { getProducts } from "@/lib/saleor";
import { getTranslations } from "next-intl/server";
import Header from "@/components/layout/Header"; import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer"; import Footer from "@/components/layout/Footer";
import HeroVideo from "@/components/home/HeroVideo"; import HeroVideo from "@/components/home/HeroVideo";
@@ -10,13 +11,17 @@ import BeforeAfterGallery from "@/components/home/BeforeAfterGallery";
import ProblemSection from "@/components/home/ProblemSection"; import ProblemSection from "@/components/home/ProblemSection";
import HowItWorks from "@/components/home/HowItWorks"; import HowItWorks from "@/components/home/HowItWorks";
export const metadata = { export async function generateMetadata() {
return {
title: "ManoonOils - Premium Natural Oils for Hair & Skin", title: "ManoonOils - Premium Natural Oils for Hair & Skin",
description: description: "Discover our premium collection of natural oils for hair and skin care.",
"Discover our premium collection of natural oils for hair and skin care. Handmade with love using only the finest ingredients.",
}; };
}
export default async function EnglishHomepage() { export default async function EnglishHomepage() {
const t = await getTranslations("Home");
const tBenefits = await getTranslations("Benefits");
let products: any[] = []; let products: any[] = [];
try { try {
products = await getProducts("UK"); products = await getProducts("UK");
@@ -44,19 +49,19 @@ export default async function EnglishHomepage() {
<BeforeAfterGallery /> <BeforeAfterGallery />
<div id="main_content" className="scroll-mt-[72px] lg:scroll-mt-[72px]"> <div id="main-content" className="scroll-mt-[72px] lg:scroll-mt-[72px]">
{hasProducts && ( {hasProducts && (
<section className="py-24 px-4 sm:px-6 lg:px-8 bg-white"> <section className="py-24 px-4 sm:px-6 lg:px-8 bg-white">
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
<div className="text-center mb-16"> <div className="text-center mb-16">
<span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block"> <span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block">
Our Collection {t("collection")}
</span> </span>
<h2 className="text-3xl md:text-4xl font-medium mb-4"> <h2 className="text-3xl md:text-4xl font-medium mb-4">
Premium Natural Oils {t("premiumOils")}
</h2> </h2>
<p className="text-[#666666] max-w-xl mx-auto"> <p className="text-[#666666] max-w-xl mx-auto">
Cold-pressed, pure, and natural oils for your daily beauty routine {t("oilsDescription")}
</p> </p>
</div> </div>
@@ -71,7 +76,7 @@ export default async function EnglishHomepage() {
href="/en/products" href="/en/products"
className="inline-block text-sm uppercase tracking-[0.1em] border-b border-black pb-1 hover:text-[#666666] hover:border-[#666666] transition-colors" className="inline-block text-sm uppercase tracking-[0.1em] border-b border-black pb-1 hover:text-[#666666] hover:border-[#666666] transition-colors"
> >
View All Products {t("viewAll")}
</a> </a>
</div> </div>
</div> </div>
@@ -85,25 +90,22 @@ export default async function EnglishHomepage() {
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20 items-center"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20 items-center">
<div> <div>
<span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block"> <span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block">
Our Story {t("ourStory")}
</span> </span>
<h2 className="text-3xl md:text-4xl font-medium mb-6"> <h2 className="text-3xl md:text-4xl font-medium mb-6">
Handmade with Love {t("handmadeWithLove")}
</h2> </h2>
<p className="text-[#666666] mb-6 leading-relaxed"> <p className="text-[#666666] mb-6 leading-relaxed">
Every bottle of ManoonOils is crafted with care using traditional {t("storyText1")}
methods passed down through generations. We source only the finest
organic ingredients to bring you oils that nourish both hair and skin.
</p> </p>
<p className="text-[#666666] mb-8 leading-relaxed"> <p className="text-[#666666] mb-8 leading-relaxed">
Our commitment to purity means no additives, no preservatives - {t("storyText2")}
just nature&apos;s goodness in its most potent form.
</p> </p>
<a <a
href="/en/about" href="/en/about"
className="inline-block text-sm uppercase tracking-[0.1em] border-b border-black pb-1 hover:text-[#666666] hover:border-[#666666] transition-colors" className="inline-block text-sm uppercase tracking-[0.1em] border-b border-black pb-1 hover:text-[#666666] hover:border-[#666666] transition-colors"
> >
Learn More {t("learnMore")}
</a> </a>
</div> </div>
<div className="relative aspect-[4/3] bg-[#e8f0f5] rounded-lg overflow-hidden"> <div className="relative aspect-[4/3] bg-[#e8f0f5] rounded-lg overflow-hidden">
@@ -121,10 +123,10 @@ export default async function EnglishHomepage() {
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
<div className="text-center mb-16"> <div className="text-center mb-16">
<span className="text-xs uppercase tracking-[0.3em] text-[#c9a962] mb-4 block font-medium"> <span className="text-xs uppercase tracking-[0.3em] text-[#c9a962] mb-4 block font-medium">
Why Choose Us {t("whyChooseUs")}
</span> </span>
<h2 className="text-3xl md:text-4xl lg:text-5xl font-medium text-[#1a1a1a]"> <h2 className="text-3xl md:text-4xl lg:text-5xl font-medium text-[#1a1a1a]">
The Manoon Difference {t("manoonDifference")}
</h2> </h2>
<div className="w-24 h-1 bg-gradient-to-r from-[#c9a962] to-[#FFD700] mx-auto mt-6 rounded-full" /> <div className="w-24 h-1 bg-gradient-to-r from-[#c9a962] to-[#FFD700] mx-auto mt-6 rounded-full" />
</div> </div>
@@ -132,8 +134,8 @@ export default async function EnglishHomepage() {
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-8"> <div className="grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-8">
{[ {[
{ {
title: "100% Natural", title: tBenefits("natural"),
description: "Pure, cold-pressed oils with no additives or preservatives. Just nature's goodness.", description: tBenefits("naturalDesc"),
icon: ( icon: (
<svg className="w-10 h-10" viewBox="0 0 24 24" fill="none"> <svg className="w-10 h-10" viewBox="0 0 24 24" fill="none">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" fill="#7eb89e"/> <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" fill="#7eb89e"/>
@@ -142,8 +144,8 @@ export default async function EnglishHomepage() {
), ),
}, },
{ {
title: "Handcrafted", title: tBenefits("handcrafted"),
description: "Each batch is carefully prepared by hand to ensure the highest quality.", description: tBenefits("handcraftedDesc"),
icon: ( icon: (
<svg className="w-10 h-10" viewBox="0 0 24 24" fill="none"> <svg className="w-10 h-10" viewBox="0 0 24 24" fill="none">
<path stroke="#c9a962" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" d="M15.182 15.182a4.5 4.5 0 01-6.364 0M21 12a9 9 0 11-18 0 9 9 0 0118 0zM9.75 9.75c0 .414-.168.75-.375.75S9 10.164 9 9.75 9.168 9 9.375 9s.375.336.375.75zm-.375 0h.008v.015h-.008V9.75zm5.625 0c0 .414-.168.75-.375.75s-.375-.336-.375-.75.168-.75.375-.75.375.336.375.75zm-.375 0h.008v.015h-.008V9.75z"/> <path stroke="#c9a962" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" d="M15.182 15.182a4.5 4.5 0 01-6.364 0M21 12a9 9 0 11-18 0 9 9 0 0118 0zM9.75 9.75c0 .414-.168.75-.375.75S9 10.164 9 9.75 9.168 9 9.375 9s.375.336.375.75zm-.375 0h.008v.015h-.008V9.75zm5.625 0c0 .414-.168.75-.375.75s-.375-.336-.375-.75.168-.75.375-.75.375.336.375.75zm-.375 0h.008v.015h-.008V9.75z"/>
@@ -151,8 +153,8 @@ export default async function EnglishHomepage() {
), ),
}, },
{ {
title: "Sustainable", title: tBenefits("sustainable"),
description: "Ethically sourced ingredients and eco-friendly packaging for a better planet.", description: tBenefits("sustainableDesc"),
icon: ( icon: (
<svg className="w-10 h-10" viewBox="0 0 24 24" fill="none"> <svg className="w-10 h-10" viewBox="0 0 24 24" fill="none">
<path stroke="#e8967a" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" d="M12.75 3.03v.568c0 .334.148.65.405.864l1.068.89c.442.369.535 1.01.216 1.49l-.51.766a2.25 2.25 0 01-1.161.886l-.143.048a1.107 1.107 0 00-.57 1.664c.369.555.169 1.307-.427 1.605L9 13.125l.423 1.059a.956.956 0 11-1.652.928l-.714-.093a1.125 1.125 0 00-1.906.172L4.5 15.75l-.612.153M12.75 3.031l.002-.004m0 0a8.955 8.955 0 00-4.943.834 8.974 8.974 0 004.943.834m4.943-.834a8.955 8.955 0 00-4.943-.834c2.687 0 5.18.948 7.161 2.664a8.974 8.974 0 014.943-.834z"/> <path stroke="#e8967a" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" d="M12.75 3.03v.568c0 .334.148.65.405.864l1.068.89c.442.369.535 1.01.216 1.49l-.51.766a2.25 2.25 0 01-1.161.886l-.143.048a1.107 1.107 0 00-.57 1.664c.369.555.169 1.307-.427 1.605L9 13.125l.423 1.059a.956.956 0 11-1.652.928l-.714-.093a1.125 1.125 0 00-1.906.172L4.5 15.75l-.612.153M12.75 3.031l.002-.004m0 0a8.955 8.955 0 00-4.943.834 8.974 8.974 0 004.943.834m4.943-.834a8.955 8.955 0 00-4.943-.834c2.687 0 5.18.948 7.161 2.664a8.974 8.974 0 014.943-.834z"/>
@@ -179,25 +181,25 @@ export default async function EnglishHomepage() {
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
<div className="max-w-2xl mx-auto text-center"> <div className="max-w-2xl mx-auto text-center">
<span className="text-xs uppercase tracking-[0.2em] text-white/60 mb-3 block"> <span className="text-xs uppercase tracking-[0.2em] text-white/60 mb-3 block">
Stay Connected {t("stayConnected")}
</span> </span>
<h2 className="text-3xl md:text-4xl lg:text-5xl font-medium mb-6"> <h2 className="text-3xl md:text-4xl lg:text-5xl font-medium mb-6">
Join Our Community {t("joinCommunity")}
</h2> </h2>
<p className="text-white/70 mb-10 mx-auto text-lg"> <p className="text-white/70 mb-10 mx-auto text-lg">
Subscribe to receive exclusive offers, beauty tips, and be the first to know about new products. {t("newsletterText")}
</p> </p>
<form className="flex flex-col sm:flex-row items-stretch justify-center max-w-md mx-auto gap-0"> <form className="flex flex-col sm:flex-row items-stretch justify-center max-w-md mx-auto gap-0">
<input <input
type="email" type="email"
placeholder="Enter your email" placeholder={t("emailPlaceholder")}
className="flex-1 min-w-0 px-5 h-14 bg-white/10 border border-white/20 border-b-0 sm:border-b border-r-0 sm:border-r border-white/20 text-white placeholder:text-white/50 focus:border-white focus:outline-none transition-colors text-base text-center sm:text-left rounded-t sm:rounded-l sm:rounded-tr-none" className="flex-1 min-w-0 px-5 h-14 bg-white/10 border border-white/20 border-b-0 sm:border-b border-r-0 sm:border-r border-white/20 text-white placeholder:text-white/50 focus:border-white focus:outline-none transition-colors text-base text-center sm:text-left rounded-t sm:rounded-l sm:rounded-tr-none"
/> />
<button <button
type="submit" type="submit"
className="px-8 h-14 bg-white text-black text-sm uppercase tracking-[0.1em] font-medium hover:bg-white/90 transition-colors whitespace-nowrap flex-shrink-0 rounded-b sm:rounded-r sm:rounded-bl-none" className="px-8 h-14 bg-white text-black text-sm uppercase tracking-[0.1em] font-medium hover:bg-white/90 transition-colors whitespace-nowrap flex-shrink-0 rounded-b sm:rounded-r sm:rounded-bl-none"
> >
Subscribe {t("subscribe")}
</button> </button>
</form> </form>
</div> </div>

View File

@@ -1,15 +1,19 @@
import { getProducts } from "@/lib/saleor"; import { getProducts } from "@/lib/saleor";
import { getTranslations } from "next-intl/server";
import Header from "@/components/layout/Header"; import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer"; import Footer from "@/components/layout/Footer";
import ProductCard from "@/components/product/ProductCard"; import ProductCard from "@/components/product/ProductCard";
import { ChevronDown } from "lucide-react"; import { ChevronDown } from "lucide-react";
export const metadata = { export async function generateMetadata() {
return {
title: "Products - ManoonOils", title: "Products - ManoonOils",
description: "Browse our collection of premium natural oils for hair and skin care.", description: "Browse our collection of premium natural oils for hair and skin care.",
}; };
}
export default async function EnglishProductsPage() { export default async function EnglishProductsPage() {
const t = await getTranslations("Products");
const products = await getProducts("UK"); const products = await getProducts("UK");
return ( return (
@@ -23,26 +27,26 @@ export default async function EnglishProductsPage() {
<div className="flex flex-col md:flex-row md:items-end md:justify-between gap-4"> <div className="flex flex-col md:flex-row md:items-end md:justify-between gap-4">
<div> <div>
<span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-2 block"> <span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-2 block">
Our Collection {t("collection")}
</span> </span>
<h1 className="text-3xl md:text-4xl font-medium"> <h1 className="text-3xl md:text-4xl font-medium">
All Products {t("allProducts")}
</h1> </h1>
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<span className="text-sm text-[#666666]"> <span className="text-sm text-[#666666]">
{products.length} products {t("productsCount", { count: products.length })}
</span> </span>
<div className="relative"> <div className="relative">
<select <select
className="appearance-none bg-transparent border border-[#e5e5e5] pl-4 pr-10 py-2 text-sm focus:outline-none focus:border-black cursor-pointer" className="appearance-none bg-transparent border border-[#e5e5e5] pl-4 pr-10 py-2 text-sm focus:outline-none focus:border-black cursor-pointer"
defaultValue="featured" defaultValue="featured"
> >
<option value="featured">Featured</option> <option value="featured">{t("featured")}</option>
<option value="newest">Newest</option> <option value="newest">{t("newest")}</option>
<option value="price-low">Price: Low to High</option> <option value="price-low">{t("priceLow")}</option>
<option value="price-high">Price: High to Low</option> <option value="price-high">{t("priceHigh")}</option>
</select> </select>
<ChevronDown className="absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 pointer-events-none text-[#666666]" /> <ChevronDown className="absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 pointer-events-none text-[#666666]" />
</div> </div>
@@ -56,10 +60,10 @@ export default async function EnglishProductsPage() {
{products.length === 0 ? ( {products.length === 0 ? (
<div className="text-center py-20"> <div className="text-center py-20">
<p className="text-[#666666] mb-4"> <p className="text-[#666666] mb-4">
No products available {t("noProducts")}
</p> </p>
<p className="text-sm text-[#999999]"> <p className="text-sm text-[#999999]">
Please check back later for new arrivals. {t("checkBack")}
</p> </p>
</div> </div>
) : ( ) : (

View File

@@ -1,4 +1,5 @@
import { getProducts } from "@/lib/saleor"; import { getProducts } from "@/lib/saleor";
import { getTranslations } from "next-intl/server";
import Header from "@/components/layout/Header"; import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer"; import Footer from "@/components/layout/Footer";
import HeroVideo from "@/components/home/HeroVideo"; import HeroVideo from "@/components/home/HeroVideo";
@@ -10,19 +11,23 @@ import BeforeAfterGallery from "@/components/home/BeforeAfterGallery";
import ProblemSection from "@/components/home/ProblemSection"; import ProblemSection from "@/components/home/ProblemSection";
import HowItWorks from "@/components/home/HowItWorks"; import HowItWorks from "@/components/home/HowItWorks";
export const metadata = { export async function generateMetadata() {
title: "ManoonOils - Premium Natural Oils for Hair & Skin", const t = await getTranslations("Home");
description: return {
"Discover our premium collection of natural oils for hair and skin care. Handmade with love using only the finest ingredients.", title: "ManoonOils - Premium prirodna ulja za negu kose i kože",
description: "Otkrijte našu premium kolekciju prirodnih ulja za negu kose i kože.",
}; };
}
export default async function Homepage() { export default async function Homepage() {
const t = await getTranslations("Home");
const tBenefits = await getTranslations("Benefits");
let products: any[] = []; let products: any[] = [];
try { try {
products = await getProducts("SR"); products = await getProducts("SR");
} catch (e) { } catch (e) {
// Fallback for build time when API is unavailable console.log("Failed to fetch products during build");
console.log('Failed to fetch products during build');
} }
const featuredProducts = products?.slice(0, 4) || []; const featuredProducts = products?.slice(0, 4) || [];
@@ -33,97 +38,81 @@ export default async function Homepage() {
<Header /> <Header />
<main className="min-h-screen bg-white"> <main className="min-h-screen bg-white">
{/* Hero Section with Video Background */}
<HeroVideo /> <HeroVideo />
{/* As Seen In */}
<AsSeenIn /> <AsSeenIn />
{/* Testimonials Section */}
<ProductReviews /> <ProductReviews />
{/* Trust Badges */}
<TrustBadges /> <TrustBadges />
{/* Problem Section - Create empathy */}
<ProblemSection /> <ProblemSection />
{/* Before/After Gallery */}
<BeforeAfterGallery /> <BeforeAfterGallery />
{/* Main Content */}
<div id="main-content" className="scroll-mt-[72px] lg:scroll-mt-[72px]"> <div id="main-content" className="scroll-mt-[72px] lg:scroll-mt-[72px]">
{/* Products Grid Section */}
{hasProducts && ( {hasProducts && (
<section className="py-24 px-4 sm:px-6 lg:px-8 bg-white"> <section className="py-24 px-4 sm:px-6 lg:px-8 bg-white">
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
{/* Section Header */}
<div className="text-center mb-16"> <div className="text-center mb-16">
<span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block"> <span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block">
Our Collection {t("collection")}
</span> </span>
<h2 className="text-3xl md:text-4xl font-medium mb-4"> <h2 className="text-3xl md:text-4xl font-medium mb-4">
Premium Natural Oils {t("premiumOils")}
</h2> </h2>
<p className="text-[#666666] max-w-xl mx-auto"> <p className="text-[#666666] max-w-xl mx-auto">
Cold-pressed, pure, and natural oils for your daily beauty routine {t("oilsDescription")}
</p> </p>
</div> </div>
{/* Products Grid */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 lg:gap-8"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 lg:gap-8">
{featuredProducts.map((product, index) => ( {featuredProducts.map((product, index) => (
<ProductCard key={product.id} product={product} index={index} locale="SR" /> <ProductCard key={product.id} product={product} index={index} locale="SR" />
))} ))}
</div> </div>
{/* View All Link */}
<div className="text-center mt-12"> <div className="text-center mt-12">
<a <a
href="/products" href="/products"
className="inline-block text-sm uppercase tracking-[0.1em] border-b border-black pb-1 hover:text-[#666666] hover:border-[#666666] transition-colors" className="inline-block text-sm uppercase tracking-[0.1em] border-b border-black pb-1 hover:text-[#666666] hover:border-[#666666] transition-colors"
> >
View All Products {t("viewAll")}
</a> </a>
</div> </div>
</div> </div>
</section> </section>
)} )}
{/* How It Works */}
<HowItWorks /> <HowItWorks />
{/* Brand Story Section */}
<section className="py-24 px-4 sm:px-6 lg:px-8 bg-[#f8f9fa]"> <section className="py-24 px-4 sm:px-6 lg:px-8 bg-[#f8f9fa]">
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20 items-center"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20 items-center">
<div> <div>
<span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block"> <span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-3 block">
Our Story {t("ourStory")}
</span> </span>
<h2 className="text-3xl md:text-4xl font-medium mb-6"> <h2 className="text-3xl md:text-4xl font-medium mb-6">
Handmade with Love {t("handmadeWithLove")}
</h2> </h2>
<p className="text-[#666666] mb-6 leading-relaxed"> <p className="text-[#666666] mb-6 leading-relaxed">
Every bottle of ManoonOils is crafted with care using traditional {t("storyText1")}
methods passed down through generations. We source only the finest
organic ingredients to bring you oils that nourish both hair and skin.
</p> </p>
<p className="text-[#666666] mb-8 leading-relaxed"> <p className="text-[#666666] mb-8 leading-relaxed">
Our commitment to purity means no additives, no preservatives - {t("storyText2")}
just nature&apos;s goodness in its most potent form.
</p> </p>
<a <a
href="/about" href="/about"
className="inline-block text-sm uppercase tracking-[0.1em] border-b border-black pb-1 hover:text-[#666666] hover:border-[#666666] transition-colors" className="inline-block text-sm uppercase tracking-[0.1em] border-b border-black pb-1 hover:text-[#666666] hover:border-[#666666] transition-colors"
> >
Learn More {t("learnMore")}
</a> </a>
</div> </div>
<div className="relative aspect-[4/3] bg-[#e8f0f5] rounded-lg overflow-hidden"> <div className="relative aspect-[4/3] bg-[#e8f0f5] rounded-lg overflow-hidden">
<img <img
src="https://images.unsplash.com/photo-1608571423902-eed4a5ad8108?q=80&w=800&auto=format&fit=crop" src="https://images.unsplash.com/photo-1608571423902-eed4a5ad8108?q=80&w=800&auto=format&fit=crop"
alt="Natural oils production" alt="Proizvodnja prirodnih ulja"
className="w-full h-full object-cover" className="w-full h-full object-cover"
/> />
</div> </div>
@@ -131,15 +120,14 @@ export default async function Homepage() {
</div> </div>
</section> </section>
{/* Benefits Section */}
<section className="py-24 px-4 sm:px-6 lg:px-8 bg-gradient-to-b from-white to-[#faf9f7]"> <section className="py-24 px-4 sm:px-6 lg:px-8 bg-gradient-to-b from-white to-[#faf9f7]">
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
<div className="text-center mb-16"> <div className="text-center mb-16">
<span className="text-xs uppercase tracking-[0.3em] text-[#c9a962] mb-4 block font-medium"> <span className="text-xs uppercase tracking-[0.3em] text-[#c9a962] mb-4 block font-medium">
Why Choose Us {t("whyChooseUs")}
</span> </span>
<h2 className="text-3xl md:text-4xl lg:text-5xl font-medium text-[#1a1a1a]"> <h2 className="text-3xl md:text-4xl lg:text-5xl font-medium text-[#1a1a1a]">
The Manoon Difference {t("manoonDifference")}
</h2> </h2>
<div className="w-24 h-1 bg-gradient-to-r from-[#c9a962] to-[#FFD700] mx-auto mt-6 rounded-full" /> <div className="w-24 h-1 bg-gradient-to-r from-[#c9a962] to-[#FFD700] mx-auto mt-6 rounded-full" />
</div> </div>
@@ -147,8 +135,8 @@ export default async function Homepage() {
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-8"> <div className="grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-8">
{[ {[
{ {
title: "100% Natural", title: tBenefits("natural"),
description: "Pure, cold-pressed oils with no additives or preservatives. Just nature's goodness.", description: tBenefits("naturalDesc"),
icon: ( icon: (
<svg className="w-10 h-10" viewBox="0 0 24 24" fill="none"> <svg className="w-10 h-10" viewBox="0 0 24 24" fill="none">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" fill="#7eb89e"/> <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" fill="#7eb89e"/>
@@ -157,8 +145,8 @@ export default async function Homepage() {
), ),
}, },
{ {
title: "Handcrafted", title: tBenefits("handcrafted"),
description: "Each batch is carefully prepared by hand to ensure the highest quality.", description: tBenefits("handcraftedDesc"),
icon: ( icon: (
<svg className="w-10 h-10" viewBox="0 0 24 24" fill="none"> <svg className="w-10 h-10" viewBox="0 0 24 24" fill="none">
<path stroke="#c9a962" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" d="M15.182 15.182a4.5 4.5 0 01-6.364 0M21 12a9 9 0 11-18 0 9 9 0 0118 0zM9.75 9.75c0 .414-.168.75-.375.75S9 10.164 9 9.75 9.168 9 9.375 9s.375.336.375.75zm-.375 0h.008v.015h-.008V9.75zm5.625 0c0 .414-.168.75-.375.75s-.375-.336-.375-.75.168-.75.375-.75.375.336.375.75zm-.375 0h.008v.015h-.008V9.75z"/> <path stroke="#c9a962" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" d="M15.182 15.182a4.5 4.5 0 01-6.364 0M21 12a9 9 0 11-18 0 9 9 0 0118 0zM9.75 9.75c0 .414-.168.75-.375.75S9 10.164 9 9.75 9.168 9 9.375 9s.375.336.375.75zm-.375 0h.008v.015h-.008V9.75zm5.625 0c0 .414-.168.75-.375.75s-.375-.336-.375-.75.168-.75.375-.75.375.336.375.75zm-.375 0h.008v.015h-.008V9.75z"/>
@@ -166,8 +154,8 @@ export default async function Homepage() {
), ),
}, },
{ {
title: "Sustainable", title: tBenefits("sustainable"),
description: "Ethically sourced ingredients and eco-friendly packaging for a better planet.", description: tBenefits("sustainableDesc"),
icon: ( icon: (
<svg className="w-10 h-10" viewBox="0 0 24 24" fill="none"> <svg className="w-10 h-10" viewBox="0 0 24 24" fill="none">
<path stroke="#e8967a" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" d="M12.75 3.03v.568c0 .334.148.65.405.864l1.068.89c.442.369.535 1.01.216 1.49l-.51.766a2.25 2.25 0 01-1.161.886l-.143.048a1.107 1.107 0 00-.57 1.664c.369.555.169 1.307-.427 1.605L9 13.125l.423 1.059a.956.956 0 11-1.652.928l-.714-.093a1.125 1.125 0 00-1.906.172L4.5 15.75l-.612.153M12.75 3.031l.002-.004m0 0a8.955 8.955 0 00-4.943.834 8.974 8.974 0 004.943.834m4.943-.834a8.955 8.955 0 00-4.943-.834c2.687 0 5.18.948 7.161 2.664a8.974 8.974 0 014.943-.834z"/> <path stroke="#e8967a" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" d="M12.75 3.03v.568c0 .334.148.65.405.864l1.068.89c.442.369.535 1.01.216 1.49l-.51.766a2.25 2.25 0 01-1.161.886l-.143.048a1.107 1.107 0 00-.57 1.664c.369.555.169 1.307-.427 1.605L9 13.125l.423 1.059a.956.956 0 11-1.652.928l-.714-.093a1.125 1.125 0 00-1.906.172L4.5 15.75l-.612.153M12.75 3.031l.002-.004m0 0a8.955 8.955 0 00-4.943.834 8.974 8.974 0 004.943.834m4.943-.834a8.955 8.955 0 00-4.943-.834c2.687 0 5.18.948 7.161 2.664a8.974 8.974 0 014.943-.834z"/>
@@ -190,31 +178,29 @@ export default async function Homepage() {
</div> </div>
</section> </section>
{/* Newsletter Section */}
<section className="py-28 lg:py-32 px-4 sm:px-6 lg:px-8 bg-[#1a1a1a] text-white"> <section className="py-28 lg:py-32 px-4 sm:px-6 lg:px-8 bg-[#1a1a1a] text-white">
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
<div className="max-w-2xl mx-auto text-center"> <div className="max-w-2xl mx-auto text-center">
<span className="text-xs uppercase tracking-[0.2em] text-white/60 mb-3 block"> <span className="text-xs uppercase tracking-[0.2em] text-white/60 mb-3 block">
Stay Connected {t("stayConnected")}
</span> </span>
<h2 className="text-3xl md:text-4xl lg:text-5xl font-medium mb-6"> <h2 className="text-3xl md:text-4xl lg:text-5xl font-medium mb-6">
Join Our Community {t("joinCommunity")}
</h2> </h2>
<p className="text-white/70 mb-10 mx-auto text-lg"> <p className="text-white/70 mb-10 mx-auto text-lg">
Subscribe to receive exclusive offers, beauty tips, and be the first to know about new products. {t("newsletterText")}
</p> </p>
{/* Newsletter Form - Centered */}
<form className="flex flex-col sm:flex-row items-stretch justify-center max-w-md mx-auto gap-0"> <form className="flex flex-col sm:flex-row items-stretch justify-center max-w-md mx-auto gap-0">
<input <input
type="email" type="email"
placeholder="Enter your email" placeholder={t("emailPlaceholder")}
className="flex-1 min-w-0 px-5 h-14 bg-white/10 border border-white/20 border-b-0 sm:border-b border-r-0 sm:border-r border-white/20 text-white placeholder:text-white/50 focus:border-white focus:outline-none transition-colors text-base text-center sm:text-left rounded-t sm:rounded-l sm:rounded-tr-none" className="flex-1 min-w-0 px-5 h-14 bg-white/10 border border-white/20 border-b-0 sm:border-b border-r-0 sm:border-r border-white/20 text-white placeholder:text-white/50 focus:border-white focus:outline-none transition-colors text-base text-center sm:text-left rounded-t sm:rounded-l sm:rounded-tr-none"
/> />
<button <button
type="submit" type="submit"
className="px-8 h-14 bg-white text-black text-sm uppercase tracking-[0.1em] font-medium hover:bg-white/90 transition-colors whitespace-nowrap flex-shrink-0 rounded-b sm:rounded-r sm:rounded-bl-none" className="px-8 h-14 bg-white text-black text-sm uppercase tracking-[0.1em] font-medium hover:bg-white/90 transition-colors whitespace-nowrap flex-shrink-0 rounded-b sm:rounded-r sm:rounded-bl-none"
> >
Subscribe {t("subscribe")}
</button> </button>
</form> </form>
</div> </div>

View File

@@ -1,27 +1,21 @@
import { getProductBySlug, getProducts, getLocalizedProduct } from "@/lib/saleor"; import { getProductBySlug, getProducts, getLocalizedProduct } from "@/lib/saleor";
import { getTranslations } from "next-intl/server";
import Header from "@/components/layout/Header"; import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer"; import Footer from "@/components/layout/Footer";
import ProductDetail from "@/components/product/ProductDetail"; import ProductDetail from "@/components/product/ProductDetail";
import type { Product } from "@/types/saleor"; import type { Product } from "@/types/saleor";
interface ProductPageProps { interface ProductPageProps {
params: Promise<{ slug: string; locale?: string }>; params: Promise<{ slug: string }>;
} }
// Generate static params for all products
export async function generateStaticParams() { export async function generateStaticParams() {
try { try {
const products = await getProducts("SR", 100); const products = await getProducts("SR", 100);
const params: Array<{ slug: string; locale: string }> = []; const params: Array<{ slug: string }> = [];
products.forEach((product: Product) => { products.forEach((product: Product) => {
// Serbian slug params.push({ slug: product.slug });
params.push({ slug: product.slug, locale: "sr" });
// English slug (if translation exists)
if (product.translation?.slug) {
params.push({ slug: product.translation.slug, locale: "en" });
}
}); });
return params; return params;
@@ -31,39 +25,27 @@ export async function generateStaticParams() {
} }
export async function generateMetadata({ params }: ProductPageProps) { export async function generateMetadata({ params }: ProductPageProps) {
const { slug, locale = "sr" } = await params; const { slug } = await params;
const product = await getProductBySlug(slug, locale.toUpperCase()); const product = await getProductBySlug(slug, "SR");
if (!product) { if (!product) {
return { return {
title: locale === "en" ? "Product Not Found" : "Proizvod nije pronađen", title: "Proizvod nije pronađen",
}; };
} }
const localized = getLocalizedProduct(product, locale.toUpperCase()); const localized = getLocalizedProduct(product, "SR");
return { return {
title: localized.name, title: localized.name,
description: localized.seoDescription || localized.description?.slice(0, 160), description: localized.seoDescription || localized.description?.slice(0, 160),
alternates: {
canonical: `/products/${product.slug}`,
languages: {
"sr": `/products/${product.slug}`,
"en": product.translation?.slug ? `/products/${product.translation.slug}` : `/products/${product.slug}`,
},
},
openGraph: {
title: localized.name,
description: localized.seoDescription || localized.description?.slice(0, 160),
images: product.media?.[0]?.url ? [product.media[0].url] : [],
type: 'website',
},
}; };
} }
export default async function ProductPage({ params }: ProductPageProps) { export default async function ProductPage({ params }: ProductPageProps) {
const { slug, locale = "sr" } = await params; const t = await getTranslations("Product");
const product = await getProductBySlug(slug, locale.toUpperCase()); const { slug } = await params;
const product = await getProductBySlug(slug, "SR");
if (!product) { if (!product) {
return ( return (
@@ -72,18 +54,16 @@ export default async function ProductPage({ params }: ProductPageProps) {
<main className="min-h-screen bg-white"> <main className="min-h-screen bg-white">
<div className="pt-[180px] lg:pt-[200px] pb-20 text-center px-4"> <div className="pt-[180px] lg:pt-[200px] pb-20 text-center px-4">
<h1 className="text-2xl font-medium mb-4"> <h1 className="text-2xl font-medium mb-4">
{locale === "en" ? "Product not found" : "Proizvod nije pronađen"} {t("notFound")}
</h1> </h1>
<p className="text-[#666666] mb-8"> <p className="text-[#666666] mb-8">
{locale === "en" {t("notFoundDesc")}
? "The product you're looking for doesn't exist or has been removed."
: "Proizvod koji tražite ne postoji ili je uklonjen."}
</p> </p>
<a <a
href="/products" href="/products"
className="inline-block px-8 py-3 bg-black text-white text-sm uppercase tracking-[0.1em] hover:bg-[#333333] transition-colors" className="inline-block px-8 py-3 bg-black text-white text-sm uppercase tracking-[0.1em] hover:bg-[#333333] transition-colors"
> >
{locale === "en" ? "Browse Products" : "Pregledaj proizvode"} {t("browseProducts")}
</a> </a>
</div> </div>
</main> </main>
@@ -92,20 +72,13 @@ export default async function ProductPage({ params }: ProductPageProps) {
); );
} }
// Determine language based on which slug matched
const isEnglishSlug = slug === product.translation?.slug;
const currentLocale = isEnglishSlug ? "EN" : "SR";
// Get related products (same category or just other products)
let relatedProducts: Product[] = []; let relatedProducts: Product[] = [];
try { try {
const allProducts = await getProducts(currentLocale, 8); const allProducts = await getProducts("SR", 8);
relatedProducts = allProducts relatedProducts = allProducts
.filter((p: Product) => p.id !== product.id) .filter((p: Product) => p.id !== product.id)
.slice(0, 4); .slice(0, 4);
} catch (e) { } catch (e) {}
// Ignore error, just won't show related products
}
return ( return (
<> <>
@@ -114,7 +87,7 @@ export default async function ProductPage({ params }: ProductPageProps) {
<ProductDetail <ProductDetail
product={product} product={product}
relatedProducts={relatedProducts} relatedProducts={relatedProducts}
locale={currentLocale} locale="SR"
/> />
</main> </main>
<Footer /> <Footer />

View File

@@ -1,64 +1,52 @@
import { getProducts } from "@/lib/saleor"; import { getProducts } from "@/lib/saleor";
import { getTranslations } from "next-intl/server";
import Header from "@/components/layout/Header"; import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer"; import Footer from "@/components/layout/Footer";
import ProductCard from "@/components/product/ProductCard"; import ProductCard from "@/components/product/ProductCard";
import { ChevronDown } from "lucide-react"; import { ChevronDown } from "lucide-react";
export const metadata = { export async function generateMetadata() {
title: "Products - ManoonOils", return {
description: "Browse our collection of premium natural oils for hair and skin care.", title: "Proizvodi - ManoonOils",
description: "Pregledajte našu kolekciju premium prirodnih ulja za negu kose i kože.",
}; };
interface ProductsPageProps {
params: Promise<{ locale: string }>;
} }
export default async function ProductsPage({ params }: ProductsPageProps) { export default async function ProductsPage() {
const { locale = "sr" } = await params; const t = await getTranslations("Products");
const products = await getProducts(locale.toUpperCase()); const products = await getProducts("SR");
const localeUpper = locale.toUpperCase();
return ( return (
<> <>
<Header /> <Header />
<main className="min-h-screen bg-white"> <main className="min-h-screen bg-white">
{/* Page Header */}
<div className="pt-[72px] lg:pt-[72px]"> <div className="pt-[72px] lg:pt-[72px]">
<div className="border-b border-[#e5e5e5]"> <div className="border-b border-[#e5e5e5]">
<div className="container py-8 md:py-12"> <div className="container py-8 md:py-12">
<div className="flex flex-col md:flex-row md:items-end md:justify-between gap-4"> <div className="flex flex-col md:flex-row md:items-end md:justify-between gap-4">
<div> <div>
<span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-2 block"> <span className="text-xs uppercase tracking-[0.2em] text-[#666666] mb-2 block">
{localeUpper === "EN" ? "Our Collection" : "Naša kolekcija"} {t("collection")}
</span> </span>
<h1 className="text-3xl md:text-4xl font-medium"> <h1 className="text-3xl md:text-4xl font-medium">
{localeUpper === "EN" ? "All Products" : "Svi Proizvodi"} {t("allProducts")}
</h1> </h1>
</div> </div>
{/* Sort Dropdown */}
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<span className="text-sm text-[#666666]"> <span className="text-sm text-[#666666]">
{products.length} {localeUpper === "EN" ? "products" : "proizvoda"} {t("productsCount", { count: products.length })}
</span> </span>
<div className="relative"> <div className="relative">
<select <select
className="appearance-none bg-transparent border border-[#e5e5e5] pl-4 pr-10 py-2 text-sm focus:outline-none focus:border-black cursor-pointer" className="appearance-none bg-transparent border border-[#e5e5e5] pl-4 pr-10 py-2 text-sm focus:outline-none focus:border-black cursor-pointer"
defaultValue="featured" defaultValue="featured"
> >
<option value="featured"> <option value="featured">{t("featured")}</option>
{localeUpper === "EN" ? "Featured" : "Istaknuto"} <option value="newest">{t("newest")}</option>
</option> <option value="price-low">{t("priceLow")}</option>
<option value="newest"> <option value="price-high">{t("priceHigh")}</option>
{localeUpper === "EN" ? "Newest" : "Najnovije"}
</option>
<option value="price-low">
{localeUpper === "EN" ? "Price: Low to High" : "Cena: Rastuće"}
</option>
<option value="price-high">
{localeUpper === "EN" ? "Price: High to Low" : "Cena: Opadajuće"}
</option>
</select> </select>
<ChevronDown className="absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 pointer-events-none text-[#666666]" /> <ChevronDown className="absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 pointer-events-none text-[#666666]" />
</div> </div>
@@ -67,18 +55,15 @@ export default async function ProductsPage({ params }: ProductsPageProps) {
</div> </div>
</div> </div>
{/* Products Grid */}
<section className="py-12 md:py-16"> <section className="py-12 md:py-16">
<div className="container"> <div className="container">
{products.length === 0 ? ( {products.length === 0 ? (
<div className="text-center py-20"> <div className="text-center py-20">
<p className="text-[#666666] mb-4"> <p className="text-[#666666] mb-4">
{localeUpper === "EN" ? "No products available" : "Nema dostupnih proizvoda"} {t("noProducts")}
</p> </p>
<p className="text-sm text-[#999999]"> <p className="text-sm text-[#999999]">
{localeUpper === "EN" {t("checkBack")}
? "Please check back later for new arrivals."
: "Molimo proverite ponovo kasnije za nove proizvode."}
</p> </p>
</div> </div>
) : ( ) : (
@@ -88,7 +73,7 @@ export default async function ProductsPage({ params }: ProductsPageProps) {
key={product.id} key={product.id}
product={product} product={product}
index={index} index={index}
locale={localeUpper} locale="SR"
/> />
))} ))}
</div> </div>

View File

@@ -10,24 +10,40 @@
"title": "Premium Natural Oils", "title": "Premium Natural Oils",
"subtitle": "For hair and skin care" "subtitle": "For hair and skin care"
}, },
"ticker": { "collection": "Our Collection",
"text": "Free shipping on orders over 3000 RSD • Natural ingredients • Cruelty-free • Handmade with love" "premiumOils": "Premium Natural Oils",
"oilsDescription": "Cold-pressed, pure, and natural oils for your daily beauty routine",
"viewAll": "View All Products",
"ourStory": "Our Story",
"handmadeWithLove": "Handmade with Love",
"storyText1": "Every bottle of ManoonOils is crafted with care using traditional methods passed down through generations. We source only the finest organic ingredients to bring you oils that nourish both hair and skin.",
"storyText2": "Our commitment to purity means no additives, no preservatives - just nature's goodness in its most potent form.",
"learnMore": "Learn More",
"whyChooseUs": "Why Choose Us",
"manoonDifference": "The Manoon Difference",
"stayConnected": "Stay Connected",
"joinCommunity": "Join Our Community",
"newsletterText": "Subscribe to receive exclusive offers, beauty tips, and be the first to know about new products.",
"emailPlaceholder": "Enter your email",
"subscribe": "Subscribe"
}, },
"products": { "Benefits": {
"title": "Our Products" "natural": "100% Natural",
"naturalDesc": "Pure, cold-pressed oils with no additives or preservatives. Just nature's goodness.",
"handcrafted": "Handcrafted",
"handcraftedDesc": "Each batch is carefully prepared by hand to ensure the highest quality.",
"sustainable": "Sustainable",
"sustainableDesc": "Ethically sourced ingredients and eco-friendly packaging for a better planet."
}, },
"bestsellers": { "Products": {
"title": "Best Sellers" "allProducts": "All Products",
}, "productsCount": "{count} products",
"story": { "featured": "Featured",
"title": "Our Story", "newest": "Newest",
"description": "ManoonOils was born from a passion for natural beauty..." "priceLow": "Price: Low to High",
}, "priceHigh": "Price: High to Low",
"newsletter": { "noProducts": "No products available",
"title": "Stay Updated", "checkBack": "Please check back later for new arrivals."
"placeholder": "Enter your email",
"button": "Subscribe"
}
}, },
"Product": { "Product": {
"addToCart": "Add to Cart", "addToCart": "Add to Cart",
@@ -35,19 +51,99 @@
"details": "Details", "details": "Details",
"ingredients": "Ingredients", "ingredients": "Ingredients",
"usage": "How to Use", "usage": "How to Use",
"related": "You May Also Like" "related": "You May Also Like",
"notFound": "Product not found",
"notFoundDesc": "The product you're looking for doesn't exist or has been removed.",
"browseProducts": "Browse Products"
}, },
"Cart": { "Cart": {
"title": "Your Cart", "title": "Your Cart",
"empty": "Your cart is empty", "empty": "Your cart is empty",
"emptyDesc": "Looks like you haven't added anything to your cart yet.",
"continueShopping": "Continue Shopping", "continueShopping": "Continue Shopping",
"checkout": "Checkout", "checkout": "Checkout",
"subtotal": "Subtotal", "subtotal": "Subtotal",
"remove": "Remove" "shipping": "Shipping",
"shippingCalc": "Calculated at checkout",
"total": "Total",
"freeShipping": "Free shipping on orders over {amount}",
"remove": "Remove",
"processes": "Processing...",
"cartEmpty": "Your cart is empty"
},
"About": {
"title": "About Us",
"subtitle": "Our Story",
"intro": "ManoonOils was born from a passion for natural beauty and the belief that the best skincare comes from nature itself.",
"intro2": "We believe in the power of natural ingredients. Every oil in our collection is carefully selected for its unique properties and benefits. From nourishing oils that restore hair vitality to serums that rejuvenate skin, we craft each product with love and attention to detail.",
"naturalIngredients": "Natural Ingredients",
"naturalIngredientsDesc": "We use only the finest natural ingredients, sourced ethically and sustainably from trusted suppliers around the world.",
"crueltyFree": "Cruelty-Free",
"crueltyFreeDesc": "Our products are never tested on animals. We believe in beauty without compromise.",
"sustainablePackaging": "Sustainable Packaging",
"sustainablePackagingDesc": "We use eco-friendly packaging materials and minimize waste throughout our production process.",
"handcraftedQuality": "Handcrafted Quality",
"handcraftedQualityDesc": "Every bottle is handcrafted in small batches to ensure the highest quality and freshness.",
"mission": "Our Mission",
"missionQuote": "\"To provide premium quality, natural products that enhance your daily beauty routine.\"",
"handmadeTitle": "Handmade with Love",
"handmadeText1": "Every bottle of ManoonOils is handcrafted with care. We small-batch produce our products to ensure the highest quality and freshness. When you use ManoonOils, you can feel confident that you're using something made with genuine care and expertise.",
"handmadeText2": "Our journey began with a simple question: how can we create products that truly nurture both hair and skin? Today, we continue to innovate while staying true to our commitment to natural, effective beauty solutions."
},
"Contact": {
"title": "Contact",
"subtitle": "Get in Touch",
"getInTouch": "Get in Touch",
"getInTouchDesc": "We're here to help! Whether you have questions about our products, need assistance with an order, or just want to say hello, we'd love to hear from you.",
"email": "Email",
"emailReply": "We reply within 24 hours",
"shippingTitle": "Shipping",
"freeShipping": "Free shipping over £50",
"deliveryTime": "Delivered within 2-5 business days",
"location": "Location",
"locationDesc": "Serbia",
"worldwideShipping": "Shipping worldwide",
"name": "Name",
"namePlaceholder": "Your name",
"emailField": "Email",
"emailPlaceholder": "your@email.com",
"message": "Message",
"messagePlaceholder": "How can we help you?",
"sendMessage": "Send Message",
"thankYou": "Thank You!",
"thankYouDesc": "Your message has been sent. We'll get back to you soon.",
"faqTitle": "Frequently Asked Questions",
"faq1q": "How long does shipping take?",
"faq1a": "Orders are typically delivered within 2-5 business days for domestic shipping. You'll receive a tracking number once your order ships.",
"faq2q": "Are your products 100% natural?",
"faq2a": "Yes! All our oils are 100% natural, cold-pressed, and free from any additives, preservatives, or artificial fragrances.",
"faq3q": "What is your return policy?",
"faq3a": "We accept returns within 14 days of delivery for unopened products. Please contact us if you have any issues with your order.",
"faq4q": "Do you offer wholesale?",
"faq4a": "Yes, we offer wholesale pricing for bulk orders. Please contact us at hello@manoonoils.com for more information."
}, },
"Footer": { "Footer": {
"quickLinks": "Quick Links", "quickLinks": "Quick Links",
"customerService": "Customer Service", "customerService": "Customer Service",
"copyright": "All rights reserved." "contact": "Contact",
"shipping": "Shipping",
"returns": "Returns",
"faq": "FAQ",
"followUs": "Follow Us",
"newsletter": "Newsletter",
"newsletterDesc": "Subscribe to our newsletter for exclusive offers and updates.",
"copyright": "All rights reserved.",
"allRights": "© {year} ManoonOils."
},
"Common": {
"loading": "Loading...",
"error": "An error occurred",
"tryAgain": "Try again",
"close": "Close",
"back": "Back",
"next": "Next",
"previous": "Previous",
"search": "Search",
"noResults": "No results found"
} }
} }

View File

@@ -10,24 +10,40 @@
"title": "Premium prirodna ulja", "title": "Premium prirodna ulja",
"subtitle": "Za negu kose i kože" "subtitle": "Za negu kose i kože"
}, },
"ticker": { "collection": "Naša kolekcija",
"text": "Besplatna dostava za porudžbine preko 3000 RSD • Prirodni sastojci • Bez okrutnosti • Ručno sa ljubavlju" "premiumOils": "Premium prirodna ulja",
"oilsDescription": "Hladno ceđena, čista i prirodna ulja za vašu svakodnevnuBeauty rutinu",
"viewAll": "Pogledaj sve proizvode",
"ourStory": "Naša priča",
"handmadeWithLove": "Ručno sa ljubavlju",
"storyText1": "Svaka boca ManoonOils je izrađena sa pažnjom koristeći tradicionalne metode koje se prenose kroz generacije. Nabavljamo samo najkvalitetnije organske sastojke da bismo vam doneli ulja koja neguju kosu i kožu.",
"storyText2": "Naša posvećenost čistoći znači bez aditiva, bez konzervanasa - samo dobrobit prirode u njenom najpotentnijem obliku.",
"learnMore": "Saznajte više",
"whyChooseUs": "Zašto nas izabrati",
"manoonDifference": "Manoon razlika",
"stayConnected": "Ostanite povezani",
"joinCommunity": "Pridružite se našoj zajednici",
"newsletterText": "Pretplatite se da biste primali ekskluzivne ponude, Beauty savete i budite prvi koji ćete saznati za nove proizvode.",
"emailPlaceholder": "Unesite vaš email",
"subscribe": "Pretplatite se"
}, },
"products": { "Benefits": {
"title": "Naši proizvodi" "natural": "100% Prirodno",
"naturalDesc": "Čista, hladno ceđena ulja bez aditiva ili konzervanasa. Samo dobrobit prirode.",
"handcrafted": "Ručno pravljeno",
"handcraftedDesc": "Svaka serija je pažljivo pripremljena ručno kako bi se osigurao najviši kvalitet.",
"sustainable": "Održivo",
"sustainableDesc": "Etički nabavljeni sastojci i ekološka ambalaža za bolju planetu."
}, },
"bestsellers": { "Products": {
"title": "Najprodavaniji" "allProducts": "Svi proizvodi",
}, "productsCount": "{count} proizvoda",
"story": { "featured": "Istaknuto",
"title": "Naša priča", "newest": "Najnovije",
"description": "ManoonOils je rođen iz strasti za prirodnu lepotu..." "priceLow": "Cena: Rastuće",
}, "priceHigh": "Cena: Opadajuće",
"newsletter": { "noProducts": "Nema dostupnih proizvoda",
"title": "Ostanite u toku", "checkBack": "Molimo proverite ponovo kasnije za nove proizvode."
"placeholder": "Unesite vaš email",
"button": "Pretplati se"
}
}, },
"Product": { "Product": {
"addToCart": "Dodaj u korpu", "addToCart": "Dodaj u korpu",
@@ -35,19 +51,99 @@
"details": "Detalji", "details": "Detalji",
"ingredients": "Sastojci", "ingredients": "Sastojci",
"usage": "Način upotrebe", "usage": "Način upotrebe",
"related": "Takođe će vam se svideti" "related": "Takođe će vam se svideti",
"notFound": "Proizvod nije pronađen",
"notFoundDesc": "Proizvod koji tražite ne postoji ili je uklonjen.",
"browseProducts": "Pregledaj proizvode"
}, },
"Cart": { "Cart": {
"title": "Vaša korpa", "title": "Vaša korpa",
"empty": "Vaša korpa je prazna", "empty": "Vaša korpa je prazna",
"emptyDesc": "Izgleda da još uvek niste dodali ništa u korpu.",
"continueShopping": "Nastavite kupovinu", "continueShopping": "Nastavite kupovinu",
"checkout": "Kupovina", "checkout": "Kupovina",
"subtotal": "Ukupno", "subtotal": "Ukupno",
"remove": "Ukloni" "shipping": "Dostava",
"shippingCalc": "Racunato pri kupovini",
"total": "Ukupno",
"freeShipping": "Besplatna dostava za porudžbine preko {amount}",
"remove": "Ukloni",
"processes": "Obrađuje se...",
"cartEmpty": "Vaša korpa je prazna"
},
"About": {
"title": "O nama",
"subtitle": "Naša priča",
"intro": "ManoonOils je rođen iz strasti za prirodnu lepotu i verovanja da najbolja nega kože dolazi od same prirode.",
"intro2": "Verujemo u moć prirodnih sastojaka. Svako ulje u našoj kolekciji je pažljivo odabrano zbog svojih jedinstvenih svojstava i prednosti. Od hranljivih ulja koja obnavljaju vitalnost kose, do seruma koji podmlađuju kožu, svaki proizvod pravimo sa ljubavlju i pažnjom prema detaljima.",
"naturalIngredients": "Prirodni sastojci",
"naturalIngredientsDesc": "Koristimo samo najfinije prirodne sastojke, etički i održivo nabavljene od pouzdanih dobavljača širom sveta.",
"crueltyFree": "Bez okrutnosti",
"crueltyFreeDesc": "Naši proizvodi se nikada ne testiraju na životinjama. Verujemo u lepotu bez kompromisa.",
"sustainablePackaging": "Održiva ambalaža",
"sustainablePackagingDesc": "Koristimo ekološke materijale za pakovanje i minimizujemo otpad tokom celokupnog proizvodnog procesa.",
"handcraftedQuality": "Ručna izrada",
"handcraftedQualityDesc": "Svaka boca je ručno napravljena u malim serijama kako bi se osigurao najviši kvalitet i svežina.",
"mission": "Naša misija",
"missionQuote": "\"Da pružimo proizvode premium kvaliteta, prirodne proizvode koji unapređuju vašu svakodnevnuBeauty rutinu.\"",
"handmadeTitle": "Ručno sa ljubavlju",
"handmadeText1": "Svaka boca ManoonOils je ručno napravljena sa brigom. Proizvodimo proizvode u malim serijama kako bi osigurali najviši kvalitet i svežinu. Kada koristite ManoonOils, možete biti sigurni da koristite nešto napravljeno sa iskrenom brigom i stručnošću.",
"handmadeText2": "Naše putovanje je počelo jednostavnim pitanjem: kako možemo stvoriti proizvode koji zaista neguju kosu i kožu? Danas nastavljamo da inoviramo dok ostajemo verni našoj posvećenosti prirodnim, efikasnim Beauty rešenjima."
},
"Contact": {
"title": "Kontakt",
"subtitle": "Stupite u kontakt",
"getInTouch": "Stupite u kontakt",
"getInTouchDesc": "Tu smo da pomognemo! Bilo da imate pitanja o našim proizvodima, trebate pomoć sa narudžbinom, ili jednostavno želite reći zdravo, voleli bismo da čujemo od vas.",
"email": "Email",
"emailReply": "Odgovaramo u roku od 24 sata",
"shippingTitle": "Dostava",
"freeShipping": "Besplatna dostava preko 3.000 RSD",
"deliveryTime": "Isporučeno u roku od 2-5 radnih dana",
"location": "Lokacija",
"locationDesc": "Srbija",
"worldwideShipping": "Isporuka širom sveta",
"name": "Ime",
"namePlaceholder": "Vaše ime",
"emailField": "Email",
"emailPlaceholder": "vas@email.com",
"message": "Poruka",
"messagePlaceholder": "Kako možemo da vam pomognemo?",
"sendMessage": "Pošalji poruku",
"thankYou": "Hvala vam!",
"thankYouDesc": "Vaša poruka je poslata. Javićemo vam se uskoro.",
"faqTitle": "Često postavljana pitanja",
"faq1q": "Koliko dugo traje dostava?",
"faq1a": "Narudžbe se obično isporučuju u roku od 2-5 radnih dana za domaću dostavu. Dobićete broj za praćenje čim vaša narudžbina bude poslata.",
"faq2q": "Da li su vaši proizvodi 100% prirodni?",
"faq2a": "Da! Sva naša ulja su 100% prirodna, hladno ceđena i bez ikakvih aditiva, konzervanasa ili veštačkih mirisa.",
"faq3q": "Koja je vaša politika povrata?",
"faq3a": "Prihvatamo povrate u roku od 14 dana od isporuke za neotvorene proizvode. Molimo kontaktirajte nas ako imate bilo kakvih problema sa narudžbinom.",
"faq4q": "Da li nudite veleprodaju?",
"faq4a": "Da, nudimo veleprodajne cene za narudžbine u velikim količinama. Molimo kontaktirajte nas na hello@manoonoils.com za više informacija."
}, },
"Footer": { "Footer": {
"quickLinks": "Brze veze", "quickLinks": "Brze veze",
"customerService": "Korisnička podrška", "customerService": "Korisnička podrška",
"copyright": "Sva prava zadržana." "contact": "Kontakt",
"shipping": "Dostava",
"returns": "Povrat",
"faq": "Česta pitanja",
"followUs": "Pratite nas",
"newsletter": "Newsletter",
"newsletterDesc": "Pretplatite se na naš newsletter za ekskluzivne ponude i novosti.",
"copyright": "Sva prava zadržana.",
"allRights": "© {year} ManoonOils."
},
"Common": {
"loading": "Učitavanje...",
"error": "Došlo je do greške",
"tryAgain": "Pokušajte ponovo",
"close": "Zatvori",
"back": "Nazad",
"next": "Sledeće",
"previous": "Prethodno",
"search": "Pretraga",
"noResults": "Nema rezultata"
} }
} }