Restore multilingual support: / for sr, /en for en with browser detection

This commit is contained in:
Unchained
2026-03-06 18:51:38 +02:00
parent 2c8cf68e89
commit 0fab8b6d42
7 changed files with 381 additions and 5 deletions

66
src/app/en/about/page.tsx Normal file
View File

@@ -0,0 +1,66 @@
import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer";
export const metadata = {
title: "About - ManoonOils",
description: "Learn about ManoonOils - our story, mission, and commitment to natural beauty.",
};
export default function AboutPage() {
return (
<main className="min-h-screen pt-16 md:pt-20">
<Header />
<section className="py-20 px-4">
<div className="max-w-4xl mx-auto">
<h1 className="text-4xl md:text-5xl font-serif text-center mb-8">
Our Story
</h1>
<div className="prose prose-lg max-w-none text-foreground-muted space-y-6">
<p>
ManoonOils was born from a passion for natural beauty and the belief
that the best skincare comes from nature itself. Our journey began with
a simple question: how can we create products that truly nurture both
hair and skin?
</p>
<p>
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.
</p>
<h2 className="font-serif text-2xl text-foreground mt-8 mb-4">
Our Mission
</h2>
<p>
Our mission is to provide premium quality, natural products that
enhance your daily beauty routine. We are committed to:
</p>
<ul className="list-disc pl-6 space-y-2">
<li>Using only the finest natural ingredients</li>
<li>Cruelty-free and ethical production</li>
<li>Sustainable packaging practices</li>
<li>Transparency in our formulations</li>
</ul>
<h2 className="font-serif text-2xl text-foreground mt-8 mb-4">
Handmade with Love
</h2>
<p>
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.
</p>
</div>
</div>
</section>
<Footer />
</main>
);
}

114
src/app/en/contact/page.tsx Normal file
View File

@@ -0,0 +1,114 @@
"use client";
import { useState } from "react";
import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer";
export default function ContactPage() {
const [formData, setFormData] = useState({
name: "",
email: "",
message: "",
});
const [submitted, setSubmitted] = useState(false);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
setSubmitted(true);
};
return (
<main className="min-h-screen pt-16 md:pt-20">
<Header />
<section className="py-20 px-4">
<div className="max-w-2xl mx-auto">
<h1 className="text-4xl md:text-5xl font-serif text-center mb-8">
Contact Us
</h1>
<p className="text-foreground-muted text-center mb-12">
Have questions? We'd love to hear from you.
</p>
{submitted ? (
<div className="bg-green-50 text-green-700 p-6 text-center">
<p className="text-lg">Thank you for your message!</p>
<p className="mt-2">We'll get back to you soon.</p>
</div>
) : (
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label htmlFor="name" className="block text-sm font-medium mb-2">
Name
</label>
<input
type="text"
id="name"
required
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
className="w-full px-4 py-3 border border-border focus:outline-none focus:border-foreground"
/>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium mb-2">
Email
</label>
<input
type="email"
id="email"
required
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
className="w-full px-4 py-3 border border-border focus:outline-none focus:border-foreground"
/>
</div>
<div>
<label htmlFor="message" className="block text-sm font-medium mb-2">
Message
</label>
<textarea
id="message"
required
rows={5}
value={formData.message}
onChange={(e) => setFormData({ ...formData, message: e.target.value })}
className="w-full px-4 py-3 border border-border focus:outline-none focus:border-foreground resize-none"
/>
</div>
<button
type="submit"
className="w-full py-3 bg-foreground text-white hover:bg-accent-dark transition-colors"
>
Send Message
</button>
</form>
)}
<div className="mt-16 pt-8 border-t border-border/30">
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 text-center">
<div>
<h3 className="font-serif mb-2">Email</h3>
<p className="text-foreground-muted">hello@manoonoils.com</p>
</div>
<div>
<h3 className="font-serif mb-2">Shipping</h3>
<p className="text-foreground-muted">Free over 3000 RSD</p>
</div>
<div>
<h3 className="font-serif mb-2">Location</h3>
<p className="text-foreground-muted">Serbia</p>
</div>
</div>
</div>
</div>
</section>
<Footer />
</main>
);
}

77
src/app/en/page.tsx Normal file
View File

@@ -0,0 +1,77 @@
import { getProducts } from "@/lib/woocommerce";
import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer";
import AnnouncementBar from "@/components/home/AnnouncementBar";
import NewHero from "@/components/home/NewHero";
import StatsSection from "@/components/home/StatsSection";
import FeaturesSection from "@/components/home/FeaturesSection";
import TestimonialsSection from "@/components/home/TestimonialsSection";
import NewsletterSection from "@/components/home/NewsletterSection";
export const metadata = {
title: "ManoonOils - Premium Natural Oils for Hair & Skin",
description:
"Discover our premium collection of natural oils for hair and skin care. Handmade with love using only the finest ingredients.",
};
export default async function Homepage() {
let products: any[] = [];
try {
products = await getProducts();
} catch (e) {
// Fallback for build time when API is unavailable
console.log('Failed to fetch products during build');
}
const featuredProduct = products.find((p) => p.status === "publish");
const publishedProducts = products
.filter((p) => p.status === "publish")
.slice(0, 4);
return (
<main className="min-h-screen bg-white">
<AnnouncementBar />
<div className="pt-10">
<Header />
</div>
{/* New Hero Section */}
<NewHero featuredProduct={featuredProduct} />
{/* Stats & Philosophy Section */}
<StatsSection />
{/* Features Section */}
<FeaturesSection />
{/* Testimonials Section */}
<TestimonialsSection />
{/* Newsletter Section */}
<NewsletterSection />
{/* Products Grid Section */}
{publishedProducts.length > 0 && (
<section className="py-20 px-6 bg-white">
<div className="max-w-[1400px] mx-auto">
<h2 className="font-serif italic text-4xl text-center mb-4">
Our Collection
</h2>
<p className="text-center text-[#4A4A4A] mb-12 max-w-2xl mx-auto">
Cold-pressed, pure, and natural oils for your daily beauty routine
</p>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8">
{publishedProducts.map((product, index) => (
<ProductCard key={product.id} product={product} index={index} />
))}
</div>
</div>
</section>
)}
<Footer />
</main>
);
}
// Import ProductCard here to avoid circular dependency
import ProductCard from "@/components/product/ProductCard";

View File

@@ -0,0 +1,71 @@
import { getProducts } from "@/lib/woocommerce";
import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer";
export const dynamic = 'force-dynamic';
// Disable static generation - this page will be server-rendered
export const generateStaticParams = undefined;
export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
let product = null;
try {
const products = await getProducts();
product = products.find((p) => (p.slug || p.id.toString()) === slug);
} catch (e) {
// Fallback
}
if (!product) {
return (
<main className="min-h-screen">
<Header />
<div className="pt-24 text-center">
<h1 className="text-2xl">Product not found</h1>
</div>
<Footer />
</main>
);
}
const image = product.images?.[0]?.src || '/placeholder.jpg';
const price = product.sale_price || product.price;
return (
<main className="min-h-screen">
<Header />
<section className="pt-24 pb-20 px-4">
<div className="max-w-7xl mx-auto">
<div className="grid grid-cols-1 md:grid-cols-2 gap-12">
<div className="relative aspect-[4/5] bg-background-ice overflow-hidden">
<img
src={image}
alt={product.name}
className="object-cover w-full h-full"
/>
</div>
<div className="flex flex-col">
<h1 className="text-4xl font-serif mb-4">{product.name}</h1>
<div className="text-2xl mb-6">{price} RSD</div>
<div className="prose max-w-none mb-8" dangerouslySetInnerHTML={{ __html: product.description || '' }} />
<button
className="inline-block bg-foreground text-white px-8 py-4 text-lg font-medium text-center hover:bg-opacity-90 transition-all"
>
Add to Cart
</button>
</div>
</div>
</div>
</section>
<Footer />
</main>
);
}

View File

@@ -0,0 +1,46 @@
import { getProducts } from "@/lib/woocommerce";
import Header from "@/components/layout/Header";
import Footer from "@/components/layout/Footer";
import ProductCard from "@/components/product/ProductCard";
export const metadata = {
title: "Products - ManoonOils",
description: "Browse our collection of premium natural oils for hair and skin care.",
};
export default async function ProductsPage() {
let products: any[] = [];
try {
products = await getProducts();
} catch (e) {
console.log('Failed to fetch products during build');
}
const publishedProducts = products.filter((p) => p.status === "publish");
return (
<main className="min-h-screen pt-16 md:pt-20">
<Header />
<section className="py-20 px-4">
<div className="max-w-7xl mx-auto">
<h1 className="text-4xl md:text-5xl font-serif text-center mb-16">
All Products
</h1>
{publishedProducts.length === 0 ? (
<p className="text-center text-foreground-muted">No products available</p>
) : (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8">
{publishedProducts.map((product, index) => (
<ProductCard key={product.id} product={product} index={index} />
))}
</div>
)}
</div>
</section>
<Footer />
</main>
);
}

View File

@@ -1,6 +1,7 @@
import { defineRouting } from 'next-intl/routing';
export const routing = defineRouting({
locales: ['sr'],
defaultLocale: 'sr'
locales: ['sr', 'en'],
defaultLocale: 'sr',
localePrefix: 'as-needed'
});

View File

@@ -2,12 +2,13 @@ import createMiddleware from "next-intl/middleware";
import { defineRouting } from 'next-intl/routing';
const routing = defineRouting({
locales: ['sr'],
defaultLocale: 'sr'
locales: ['sr', 'en'],
defaultLocale: 'sr',
localePrefix: 'as-needed'
});
export default createMiddleware(routing);
export const config = {
matcher: ['/((?!api|_next|_vercel|).*)']
matcher: ['/((?!api|_next|_vercel|.*\\..*).*)']
};