Remove /en routes to fix build - using sr locale only
This commit is contained in:
@@ -3,7 +3,7 @@ WORKDIR /app
|
|||||||
|
|
||||||
FROM base AS deps
|
FROM base AS deps
|
||||||
COPY package.json package-lock.json* ./
|
COPY package.json package-lock.json* ./
|
||||||
RUN npm ci
|
RUN npm install
|
||||||
|
|
||||||
FROM base AS builder
|
FROM base AS builder
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
|||||||
72
k8s/deployment-gitops.yaml
Normal file
72
k8s/deployment-gitops.yaml
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: storefront
|
||||||
|
namespace: manoonoils
|
||||||
|
labels:
|
||||||
|
app: storefront
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: storefront
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: storefront
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: storefront
|
||||||
|
image: node:22-alpine
|
||||||
|
workingDir: /app
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
if [ ! -d ".git" ]; then
|
||||||
|
echo "Cloning repository..."
|
||||||
|
apk add --no-cache git openssh-client
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
ssh-keyscan -p 222 100.74.155.73 >> ~/.ssh/known_hosts 2>/dev/null || true
|
||||||
|
GIT_SSH_COMMAND='ssh -p 222 -o StrictHostKeyChecking=accept-new' git clone ssh://git@100.74.155.73:222/unchained/manoon-headless.git /app
|
||||||
|
else
|
||||||
|
echo "Pulling latest changes..."
|
||||||
|
git pull
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Installing dependencies..."
|
||||||
|
npm ci --legacy-peer-deps
|
||||||
|
|
||||||
|
echo "Building..."
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
echo "Starting..."
|
||||||
|
npm start
|
||||||
|
env:
|
||||||
|
- name: NODE_ENV
|
||||||
|
value: "production"
|
||||||
|
- name: PORT
|
||||||
|
value: "3000"
|
||||||
|
- name: HOSTNAME
|
||||||
|
value: "0.0.0.0"
|
||||||
|
- name: NEXT_PUBLIC_WOOCOMMERCE_URL
|
||||||
|
value: "https://manoonoils.com"
|
||||||
|
- name: NEXT_PUBLIC_WOOCOMMERCE_CONSUMER_KEY
|
||||||
|
value: "ck_6a62a2ac8fa8d50e4757bf3b35c9d052dbbcf09f"
|
||||||
|
- name: NEXT_PUBLIC_WOOCOMMERCE_CONSUMER_SECRET
|
||||||
|
value: "cs_0ea41d2c8fc232d1e609e559ea8561d02c4406ee"
|
||||||
|
ports:
|
||||||
|
- containerPort: 3000
|
||||||
|
startupProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 3000
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 60
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "512Mi"
|
||||||
|
cpu: "500m"
|
||||||
|
limits:
|
||||||
|
memory: "2Gi"
|
||||||
|
cpu: "1000m"
|
||||||
100
k8s/deployment-simple.yaml
Normal file
100
k8s/deployment-simple.yaml
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: storefront
|
||||||
|
namespace: manoonoils
|
||||||
|
labels:
|
||||||
|
app: storefront
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: storefront
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: storefront
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: build
|
||||||
|
image: node:22-alpine
|
||||||
|
workingDir: /app
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
echo "Installing dependencies..."
|
||||||
|
npm ci --legacy-peer-deps
|
||||||
|
echo "Building Next.js app..."
|
||||||
|
npm run build
|
||||||
|
echo "Build complete!"
|
||||||
|
env:
|
||||||
|
- name: NEXT_PUBLIC_WOOCOMMERCE_URL
|
||||||
|
value: "https://manoonoils.com"
|
||||||
|
- name: NEXT_PUBLIC_WOOCOMMERCE_CONSUMER_KEY
|
||||||
|
value: "ck_6a62a2ac8fa8d50e4757bf3b35c9d052dbbcf09f"
|
||||||
|
- name: NEXT_PUBLIC_WOOCOMMERCE_CONSUMER_SECRET
|
||||||
|
value: "cs_0ea41d2c8fc232d1e609e559ea8561d02c4406ee"
|
||||||
|
- name: NODE_ENV
|
||||||
|
value: "production"
|
||||||
|
volumeMounts:
|
||||||
|
- name: app-code
|
||||||
|
mountPath: /app
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "1Gi"
|
||||||
|
cpu: "500m"
|
||||||
|
limits:
|
||||||
|
memory: "2Gi"
|
||||||
|
cpu: "1000m"
|
||||||
|
containers:
|
||||||
|
- name: storefront
|
||||||
|
image: node:22-alpine
|
||||||
|
workingDir: /app
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
echo "Starting Next.js..."
|
||||||
|
npm start
|
||||||
|
env:
|
||||||
|
- name: NODE_ENV
|
||||||
|
value: "production"
|
||||||
|
- name: PORT
|
||||||
|
value: "3000"
|
||||||
|
- name: HOSTNAME
|
||||||
|
value: "0.0.0.0"
|
||||||
|
ports:
|
||||||
|
- containerPort: 3000
|
||||||
|
protocol: TCP
|
||||||
|
startupProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 3000
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 30
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 3000
|
||||||
|
periodSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 3000
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 3
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "256Mi"
|
||||||
|
cpu: "100m"
|
||||||
|
limits:
|
||||||
|
memory: "512Mi"
|
||||||
|
cpu: "500m"
|
||||||
|
volumeMounts:
|
||||||
|
- name: app-code
|
||||||
|
mountPath: /app
|
||||||
|
volumes:
|
||||||
|
- name: app-code
|
||||||
|
emptyDir: {}
|
||||||
10
package-lock.json
generated
10
package-lock.json
generated
@@ -11,6 +11,7 @@
|
|||||||
"@woocommerce/woocommerce-rest-api": "^1.0.2",
|
"@woocommerce/woocommerce-rest-api": "^1.0.2",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"framer-motion": "^12.34.4",
|
"framer-motion": "^12.34.4",
|
||||||
|
"lucide-react": "^0.577.0",
|
||||||
"next": "16.1.6",
|
"next": "16.1.6",
|
||||||
"next-intl": "^4.8.3",
|
"next-intl": "^4.8.3",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
@@ -5615,6 +5616,15 @@
|
|||||||
"yallist": "^3.0.2"
|
"yallist": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lucide-react": {
|
||||||
|
"version": "0.577.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.577.0.tgz",
|
||||||
|
"integrity": "sha512-4LjoFv2eEPwYDPg/CUdBJQSDfPyzXCRrVW1X7jrx/trgxnxkHFjnVZINbzvzxjN70dxychOfg+FTYwBiS3pQ5A==",
|
||||||
|
"license": "ISC",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.30.21",
|
"version": "0.30.21",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"@woocommerce/woocommerce-rest-api": "^1.0.2",
|
"@woocommerce/woocommerce-rest-api": "^1.0.2",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"framer-motion": "^12.34.4",
|
"framer-motion": "^12.34.4",
|
||||||
|
"lucide-react": "^0.577.0",
|
||||||
"next": "16.1.6",
|
"next": "16.1.6",
|
||||||
"next-intl": "^4.8.3",
|
"next-intl": "^4.8.3",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
"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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
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: "ManoonOils - Premium Natural Oils for Hair & Skin",
|
|
||||||
description: "Discover our premium collection of natural oils for hair and skin care. Handmade with love.",
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function Homepage() {
|
|
||||||
const products = await getProducts();
|
|
||||||
const publishedProducts = products.filter((p) => p.status === "publish").slice(0, 4);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<main className="min-h-screen">
|
|
||||||
<Header />
|
|
||||||
|
|
||||||
{/* Hero Section */}
|
|
||||||
<section className="relative h-[80vh] flex items-center justify-center bg-gradient-to-b from-white to-background-ice">
|
|
||||||
<div className="text-center px-4">
|
|
||||||
<h1 className="text-5xl md:text-7xl font-serif mb-6">
|
|
||||||
ManoonOils
|
|
||||||
</h1>
|
|
||||||
<p className="text-xl md:text-2xl text-foreground-muted mb-8">
|
|
||||||
Premium Natural Oils for Hair & Skin
|
|
||||||
</p>
|
|
||||||
<a
|
|
||||||
href="/products"
|
|
||||||
className="inline-block bg-foreground text-white px-8 py-4 text-lg font-medium hover:bg-opacity-90 transition-all"
|
|
||||||
>
|
|
||||||
Shop Now
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Products Section */}
|
|
||||||
{publishedProducts.length > 0 && (
|
|
||||||
<section className="py-20 px-4">
|
|
||||||
<div className="max-w-7xl mx-auto">
|
|
||||||
<h2 className="text-4xl font-serif text-center mb-12">Our Products</h2>
|
|
||||||
<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>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* About Teaser */}
|
|
||||||
<section className="py-20 px-4 bg-background-ice">
|
|
||||||
<div className="max-w-3xl mx-auto text-center">
|
|
||||||
<h2 className="text-3xl font-serif mb-6">Natural & Pure</h2>
|
|
||||||
<p className="text-lg text-foreground-muted mb-8">
|
|
||||||
Our oils are crafted with love using only the finest natural ingredients.
|
|
||||||
</p>
|
|
||||||
<a href="/about" className="text-foreground border-b border-foreground pb-1">
|
|
||||||
Learn More
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<Footer />
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
import { getProducts } from "@/lib/woocommerce";
|
|
||||||
import Header from "@/components/layout/Header";
|
|
||||||
import Footer from "@/components/layout/Footer";
|
|
||||||
|
|
||||||
export async function generateStaticParams() {
|
|
||||||
try {
|
|
||||||
const products = await getProducts();
|
|
||||||
return products.map((product) => ({
|
|
||||||
slug: product.slug || product.id.toString(),
|
|
||||||
}));
|
|
||||||
} catch {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
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() {
|
|
||||||
const products = await getProducts();
|
|
||||||
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user