398
src/app/page.tsx
398
src/app/page.tsx
@ -7,9 +7,9 @@ import Section from "@/components/Section";
|
|||||||
import Button from "@/components/Button";
|
import Button from "@/components/Button";
|
||||||
import BannerSlider from "@/components/BannerSlider";
|
import BannerSlider from "@/components/BannerSlider";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useState, useEffect, useRef, useCallback, useMemo } from "react";
|
import { useState, useEffect, useRef, useCallback } from "react";
|
||||||
import { AnimatePresence } from "framer-motion";
|
import ProductCategory from "@/components/ProductCategory";
|
||||||
import { useInstagram } from "@/hooks/useInstagram";
|
import SocialMedia from "@/components/SocialMedia";
|
||||||
|
|
||||||
// Premium animation variants
|
// Premium animation variants
|
||||||
const fadeInUp = {
|
const fadeInUp = {
|
||||||
@ -46,14 +46,6 @@ const categories = [
|
|||||||
"Dragees",
|
"Dragees",
|
||||||
"Gelatos",
|
"Gelatos",
|
||||||
];
|
];
|
||||||
const categoryImages = [
|
|
||||||
"/categories/c1.svg",
|
|
||||||
"/categories/c2.svg",
|
|
||||||
"/categories/c3.svg",
|
|
||||||
"/categories/c4.svg",
|
|
||||||
"/categories/c5.svg",
|
|
||||||
"/categories/c6.svg",
|
|
||||||
];
|
|
||||||
|
|
||||||
const partnerImages = [
|
const partnerImages = [
|
||||||
"/partners/p1.svg",
|
"/partners/p1.svg",
|
||||||
@ -127,14 +119,18 @@ export default function Home() {
|
|||||||
return () => clearInterval(timer);
|
return () => clearInterval(timer);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const { posts, loading, error, isTokenExpired } = useInstagram();
|
|
||||||
|
|
||||||
// Memoize expensive components
|
// Memoize expensive components
|
||||||
const BrandStorySection = useMemo(
|
|
||||||
() => (
|
return (
|
||||||
|
<div className="min-h-screen bg-white font-renner">
|
||||||
|
<Header />
|
||||||
|
<BannerSlider />
|
||||||
|
|
||||||
|
{/* Brand Story */}
|
||||||
|
|
||||||
<Section background="white" id="about">
|
<Section background="white" id="about">
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 md:gap-12 lg:gap-16 items-center">
|
<div className="grid grid-cols-1 lg:grid-cols-2 items-center">
|
||||||
{/* Left Column - Text */}
|
{/* Brand Story - Left Text */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial="initial"
|
initial="initial"
|
||||||
whileInView="animate"
|
whileInView="animate"
|
||||||
@ -143,7 +139,7 @@ export default function Home() {
|
|||||||
className="space-y-6 md:space-y-8 order-2 lg:order-1 px-4 md:px-0" // ← Added mobile padding
|
className="space-y-6 md:space-y-8 order-2 lg:order-1 px-4 md:px-0" // ← Added mobile padding
|
||||||
>
|
>
|
||||||
<motion.h2
|
<motion.h2
|
||||||
className="text-3xl md:text-4xl lg:text-5xl font-bold text-[#3C2A21] font-moneta text-gradient"
|
className="text-3xl md:text-4xl lg:text-5xl font-bold text-[#3C2A21] font-moneta text-gradient p-4 md:p-0"
|
||||||
style={{
|
style={{
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
fontSize: "clamp(32px, 5vw, 58px)",
|
fontSize: "clamp(32px, 5vw, 58px)",
|
||||||
@ -208,21 +204,17 @@ export default function Home() {
|
|||||||
</Button>
|
</Button>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
{/* Brand Story - Right Image */}
|
||||||
{/* Right Column - Image */}
|
|
||||||
<motion.div
|
<motion.div
|
||||||
initial="initial"
|
initial="initial"
|
||||||
whileInView="animate"
|
whileInView="animate"
|
||||||
viewport={{ once: true, margin: "-50px" }}
|
viewport={{ once: true, margin: "-50px" }}
|
||||||
variants={fadeInRight}
|
variants={fadeInRight}
|
||||||
className="relative order-1 lg:order-2 w-screen md:w-auto -mx-4 md:mx-0" // ← Made full-width on mobile
|
className="relative order-1 lg:order-2 w-screen md:w-auto -mx-4 md:mx-0"
|
||||||
>
|
>
|
||||||
<motion.div
|
<motion.div
|
||||||
className="relative w-full h-[300px] md:h-[400px] lg:h-[500px] rounded-none md:rounded-xl overflow-hidden shadow-premium hover:shadow-premium-hover transition-all duration-500" // ← Removed rounded corners on mobile
|
className="relative w-full h-[300px] md:h-[400px] lg:h-[500px] overflow-hidden shadow-premium hover:shadow-premium-hover transition-all duration-500 clip-diagonal-bottom-left"
|
||||||
whileHover={{
|
whileHover={{ scale: 1.02, transition: { duration: 0.3 } }}
|
||||||
scale: 1.02,
|
|
||||||
transition: { duration: 0.3 },
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src="/bst/bs1.svg"
|
src="/bst/bs1.svg"
|
||||||
@ -232,40 +224,21 @@ export default function Home() {
|
|||||||
draggable={false}
|
draggable={false}
|
||||||
quality={85}
|
quality={85}
|
||||||
/>
|
/>
|
||||||
{/* Premium overlay for depth */}
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-t from-black/20 via-transparent to-transparent" />
|
<div className="absolute inset-0 bg-gradient-to-t from-black/20 via-transparent to-transparent" />
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
|
||||||
</Section>
|
|
||||||
),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
{/* Chocolate Tempering - Left Video */}
|
||||||
<div className="min-h-screen bg-white font-renner">
|
|
||||||
<Header />
|
|
||||||
<BannerSlider />
|
|
||||||
|
|
||||||
{BrandStorySection}
|
|
||||||
|
|
||||||
{/* Chocolate Tempering Section */}
|
|
||||||
<Section background="white">
|
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 md:gap-12 lg:gap-16 items-center">
|
|
||||||
{/* Left Column - Image */}
|
|
||||||
<motion.div
|
<motion.div
|
||||||
initial="initial"
|
initial="initial"
|
||||||
whileInView="animate"
|
whileInView="animate"
|
||||||
viewport={{ once: true, margin: "-50px" }}
|
viewport={{ once: true, margin: "-50px" }}
|
||||||
variants={fadeInLeft}
|
variants={fadeInLeft}
|
||||||
className="relative order-1 lg:order-1 w-screen md:w-auto -mx-4 md:mx-0" // ← Added for mobile edge-to-edge
|
className="relative order-3 lg:order-3 w-screen md:w-auto -mx-4 md:mx-0 py-4 md:py-0"
|
||||||
>
|
>
|
||||||
<motion.div
|
<motion.div
|
||||||
className="relative w-full h-[400px] md:h-[500px] lg:h-[700px] rounded-none md:rounded-xl overflow-hidden shadow-premium hover:shadow-premium-hover transition-all duration-500" // ← Changed to rounded-none for mobile
|
className="relative w-full h-[400px] md:h-[500px] lg:h-[700px] overflow-hidden shadow-premium hover:shadow-premium-hover transition-all duration-500 clip-diagonal-top-right"
|
||||||
whileHover={{
|
whileHover={{ scale: 1.02, transition: { duration: 0.3 } }}
|
||||||
scale: 1.02,
|
|
||||||
transition: { duration: 0.3 },
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<video
|
<video
|
||||||
src="/bst/v1.mp4"
|
src="/bst/v1.mp4"
|
||||||
@ -276,20 +249,18 @@ export default function Home() {
|
|||||||
playsInline
|
playsInline
|
||||||
preload="auto"
|
preload="auto"
|
||||||
aria-label="Chocolate pouring from metallic spout - Mozimo chocolate tempering process"
|
aria-label="Chocolate pouring from metallic spout - Mozimo chocolate tempering process"
|
||||||
style={{ display: "block" }}
|
|
||||||
/>
|
/>
|
||||||
{/* Premium overlay for depth */}
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-t from-black/20 via-transparent to-transparent" />
|
<div className="absolute inset-0 bg-gradient-to-t from-black/20 via-transparent to-transparent" />
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Right Column - Text */}
|
{/* Chocolate Tempering - Right Text */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial="initial"
|
initial="initial"
|
||||||
whileInView="animate"
|
whileInView="animate"
|
||||||
viewport={{ once: true, margin: "-50px" }}
|
viewport={{ once: true, margin: "-50px" }}
|
||||||
variants={fadeInRight}
|
variants={fadeInRight}
|
||||||
className="space-y-4 md:space-y-6 order-2 lg:order-2 px-4 md:px-0" // ← Added px-4 for mobile padding
|
className="space-y-4 md:space-y-6 order-4 lg:order-4 px-4 md:px-0 ml-4 md:ml-8 lg:ml-12"
|
||||||
>
|
>
|
||||||
<div className="space-y-3 md:space-y-4">
|
<div className="space-y-3 md:space-y-4">
|
||||||
<motion.h2
|
<motion.h2
|
||||||
@ -316,6 +287,7 @@ export default function Home() {
|
|||||||
letterSpacing: "0%",
|
letterSpacing: "0%",
|
||||||
fontStyle: "italic",
|
fontStyle: "italic",
|
||||||
color: "#703133",
|
color: "#703133",
|
||||||
|
fontFamily: "Renner*",
|
||||||
}}
|
}}
|
||||||
whileHover={{ scale: 1.02 }}
|
whileHover={{ scale: 1.02 }}
|
||||||
transition={{ duration: 0.3 }}
|
transition={{ duration: 0.3 }}
|
||||||
@ -324,7 +296,6 @@ export default function Home() {
|
|||||||
</motion.h3>
|
</motion.h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Premium decorative line */}
|
|
||||||
<motion.div
|
<motion.div
|
||||||
className="w-100 h-px bg-gradient-to-r from-transparent via-[#8B4513] to-transparent"
|
className="w-100 h-px bg-gradient-to-r from-transparent via-[#8B4513] to-transparent"
|
||||||
initial={{ scaleX: 0 }}
|
initial={{ scaleX: 0 }}
|
||||||
@ -442,318 +413,9 @@ export default function Home() {
|
|||||||
</motion.div>
|
</motion.div>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
{/* Product Categories Section */}
|
<ProductCategory />
|
||||||
<Section background="white" id="categories">
|
|
||||||
<div
|
|
||||||
ref={categoriesSectionRef}
|
|
||||||
className="grid grid-cols-1 lg:grid-cols-2 gap-0 items-stretch min-h-[400px] md:min-h-[500px]"
|
|
||||||
>
|
|
||||||
{/* Left Column - Categories List */}
|
|
||||||
<motion.div
|
|
||||||
initial="initial"
|
|
||||||
whileInView="animate"
|
|
||||||
viewport={{ once: true, margin: "-50px" }}
|
|
||||||
variants={fadeInLeft}
|
|
||||||
className="flex flex-col justify-center h-full bg-white px-4 md:px-8 py-6 md:py-12 order-2 lg:order-1"
|
|
||||||
>
|
|
||||||
<ul className="space-y-4 md:space-y-6">
|
|
||||||
{categories.map((category, idx) => (
|
|
||||||
<motion.li
|
|
||||||
key={category}
|
|
||||||
initial={{ opacity: 0, x: -20 }}
|
|
||||||
whileInView={{ opacity: 1, x: 0 }}
|
|
||||||
transition={{ duration: 0.6, delay: idx * 0.1 }}
|
|
||||||
viewport={{ once: true }}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
className={`group flex items-center gap-4 transition-all duration-700 ease-out w-full text-left font-moneta hover:scale-105
|
|
||||||
${
|
|
||||||
idx === currentCategory
|
|
||||||
? "text-[#703133] font-normal"
|
|
||||||
: "text-[#703133] opacity-60 font-light"
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
style={{
|
|
||||||
fontFamily: "MonetaSans-Regular",
|
|
||||||
fontWeight: idx === currentCategory ? 400 : 300,
|
|
||||||
fontSize:
|
|
||||||
idx === currentCategory
|
|
||||||
? "clamp(22px, 5vw, 64px)"
|
|
||||||
: "clamp(18px, 4vw, 56px)",
|
|
||||||
lineHeight: "120%",
|
|
||||||
letterSpacing: "0%",
|
|
||||||
transition: "all 0.7s cubic-bezier(0.25,0.46,0.45,0.94)",
|
|
||||||
}}
|
|
||||||
onClick={() => setCurrentCategory(idx)}
|
|
||||||
onMouseEnter={() => setCurrentCategory(idx)}
|
|
||||||
tabIndex={-1}
|
|
||||||
>
|
|
||||||
{/* Show only on mobile */}
|
|
||||||
<div className="block lg:hidden w-10 h-10 rounded-full overflow-hidden shrink-0">
|
|
||||||
<img
|
|
||||||
src={categoryImages[idx]}
|
|
||||||
alt={category}
|
|
||||||
className="w-full h-full object-cover"
|
|
||||||
draggable={false}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Category name */}
|
|
||||||
<span className="text-left">{category}</span>
|
|
||||||
</button>
|
|
||||||
</motion.li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</motion.div>
|
|
||||||
|
|
||||||
{/* Right Column - Large Category Image (desktop only) */}
|
|
||||||
<motion.div
|
|
||||||
initial="initial"
|
|
||||||
whileInView="animate"
|
|
||||||
viewport={{ once: true, margin: "-50px" }}
|
|
||||||
variants={fadeInRight}
|
|
||||||
className="relative hidden lg:flex items-center justify-center h-full min-h-[300px] md:min-h-[400px] bg-white order-1 lg:order-2"
|
|
||||||
>
|
|
||||||
<AnimatePresence mode="wait">
|
|
||||||
<motion.img
|
|
||||||
key={currentCategory}
|
|
||||||
src={categoryImages[currentCategory]}
|
|
||||||
alt={categories[currentCategory]}
|
|
||||||
initial={{ opacity: 0, scale: 1.05 }}
|
|
||||||
animate={{ opacity: 1, scale: 1 }}
|
|
||||||
exit={{ opacity: 0, scale: 0.95 }}
|
|
||||||
transition={{ duration: 0.7, ease: [0.25, 0.46, 0.45, 0.94] }}
|
|
||||||
className="w-full h-full object-cover rounded-2xl shadow-premium hover:shadow-premium-hover transition-all duration-500 img-premium"
|
|
||||||
draggable={false}
|
|
||||||
style={{ maxHeight: "600px", maxWidth: "100%" }}
|
|
||||||
/>
|
|
||||||
</AnimatePresence>
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
|
||||||
</Section>
|
|
||||||
|
|
||||||
{/* Social Media Call to Action */}
|
{/* Social Media Call to Action */}
|
||||||
<Section background="cream" padding="md">
|
<SocialMedia />
|
||||||
<motion.div
|
|
||||||
initial="initial"
|
|
||||||
whileInView="animate"
|
|
||||||
viewport={{ once: true, margin: "-50px" }}
|
|
||||||
variants={fadeInUp}
|
|
||||||
className="text-center mb-8 md:mb-12"
|
|
||||||
>
|
|
||||||
<h2
|
|
||||||
className="text-3xl md:text-4xl lg:text-5xl font-moneta text-[#703133] mb-6 md:mb-8 text-gradient"
|
|
||||||
style={{
|
|
||||||
fontWeight: 400,
|
|
||||||
fontSize: "clamp(28px, 5vw, 48px)",
|
|
||||||
lineHeight: "120%",
|
|
||||||
letterSpacing: "0%",
|
|
||||||
fontFamily: "MonetaSans-Regular",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Follow us on Instagram
|
|
||||||
</h2>
|
|
||||||
</motion.div>
|
|
||||||
|
|
||||||
<div className="flex overflow-x-auto no-scrollbar snap-x snap-mandatory gap-4 px-4 sm:grid sm:grid-cols-2 lg:grid-cols-3 sm:gap-6 md:gap-8 max-w-7xl mx-auto">
|
|
||||||
{loading ? (
|
|
||||||
<>
|
|
||||||
{[1, 2, 3].map((i) => (
|
|
||||||
<motion.div
|
|
||||||
key={i}
|
|
||||||
className="bg-white rounded-lg shadow-premium h-64 md:h-96 skeleton snap-start w-[calc(80vw-1rem)] flex-shrink-0 sm:w-auto"
|
|
||||||
initial={{ opacity: 0, y: 20 }}
|
|
||||||
whileInView={{ opacity: 1, y: 0 }}
|
|
||||||
transition={{ duration: 0.6, delay: i * 0.1 }}
|
|
||||||
viewport={{ once: true }}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
) : error ? (
|
|
||||||
isTokenExpired ? (
|
|
||||||
<div className="col-span-full text-center py-12 sm:col-span-2 lg:col-span-3">
|
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0, y: 20 }}
|
|
||||||
whileInView={{ opacity: 1, y: 0 }}
|
|
||||||
transition={{ duration: 0.6 }}
|
|
||||||
viewport={{ once: true }}
|
|
||||||
className="max-w-md mx-auto"
|
|
||||||
>
|
|
||||||
<div className="w-16 h-16 bg-gradient-to-br from-amber-200 to-orange-300 rounded-full mx-auto mb-4 flex items-center justify-center shadow-premium">
|
|
||||||
<span className="text-2xl">🔗</span>
|
|
||||||
</div>
|
|
||||||
<h3 className="text-xl font-semibold text-[#703133] mb-2">
|
|
||||||
Instagram Connection Expired
|
|
||||||
</h3>
|
|
||||||
<p className="text-gray-600 mb-4">
|
|
||||||
Our Instagram connection needs to be refreshed. We're
|
|
||||||
working on getting it back up!
|
|
||||||
</p>
|
|
||||||
<div className="text-sm text-gray-500">
|
|
||||||
In the meantime, follow us @mozimo_chocolate
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{/* Left Block - Chocolate Spread Jar */}
|
|
||||||
<motion.div
|
|
||||||
initial="initial"
|
|
||||||
whileInView="animate"
|
|
||||||
viewport={{ once: true, margin: "-50px" }}
|
|
||||||
variants={fadeInLeft}
|
|
||||||
className="bg-white rounded-lg shadow-premium overflow-hidden hover:shadow-premium-hover transition-all duration-500 transform hover:-translate-y-2 snap-start w-[calc(80vw-1rem)] flex-shrink-0 sm:w-auto"
|
|
||||||
whileHover={{ scale: 1.02 }}
|
|
||||||
>
|
|
||||||
<div className="relative h-64 md:h-96 bg-gradient-to-br from-amber-50 to-orange-50 flex items-center justify-center">
|
|
||||||
<motion.div
|
|
||||||
className="text-center"
|
|
||||||
whileHover={{ scale: 1.05 }}
|
|
||||||
transition={{ duration: 0.3 }}
|
|
||||||
>
|
|
||||||
<div className="w-32 h-32 bg-gradient-to-br from-amber-200 to-orange-300 rounded-full mx-auto mb-4 flex items-center justify-center shadow-premium">
|
|
||||||
<span className="text-4xl">🍫</span>
|
|
||||||
</div>
|
|
||||||
<div className="bg-white rounded-lg p-4 mx-4 shadow-premium">
|
|
||||||
<div className="font-semibold text-[#703133] text-lg">
|
|
||||||
MOZIMO
|
|
||||||
</div>
|
|
||||||
<div className="text-sm text-gray-600">
|
|
||||||
SINGLE ORIGIN HAZELNUT SPREAD 45%
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
|
||||||
|
|
||||||
{/* Middle Block - Magazine Article */}
|
|
||||||
<motion.div
|
|
||||||
initial="initial"
|
|
||||||
whileInView="animate"
|
|
||||||
viewport={{ once: true, margin: "-50px" }}
|
|
||||||
variants={fadeInUp}
|
|
||||||
className="bg-white rounded-lg shadow-premium overflow-hidden hover:shadow-premium-hover transition-all duration-500 transform hover:-translate-y-2 snap-start w-[calc(80vw-1rem)] flex-shrink-0 sm:w-auto"
|
|
||||||
whileHover={{ scale: 1.02 }}
|
|
||||||
>
|
|
||||||
<div className="p-4 md:p-6">
|
|
||||||
<div className="bg-red-600 h-32 rounded-lg mb-4 flex items-center justify-center shadow-premium">
|
|
||||||
<span className="text-white text-2xl">🍫</span>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-2 gap-4 mb-4">
|
|
||||||
<div className="bg-gray-200 h-20 rounded-lg flex items-center justify-center shadow-premium">
|
|
||||||
<span className="text-lg">🍰</span>
|
|
||||||
</div>
|
|
||||||
<div className="bg-gray-200 h-20 rounded-lg flex items-center justify-center shadow-premium">
|
|
||||||
<span className="text-lg">👨🍳</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="text-xs text-gray-700 space-y-2 leading-relaxed">
|
|
||||||
<p>
|
|
||||||
<strong>By RUPALI DEAN</strong>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<strong>
|
|
||||||
MOZIMO'S CHOCOLATE PIE BY PRIYANKA GUPTA
|
|
||||||
</strong>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
isolat[ing] beans to not only single ori- but also to
|
|
||||||
single farms so as to express unique complexity.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
|
||||||
|
|
||||||
{/* Right Block - World Chocolate Day */}
|
|
||||||
<motion.div
|
|
||||||
initial="initial"
|
|
||||||
whileInView="animate"
|
|
||||||
viewport={{ once: true, margin: "-50px" }}
|
|
||||||
variants={fadeInRight}
|
|
||||||
className="bg-white rounded-lg shadow-premium overflow-hidden hover:shadow-premium-hover transition-all duration-500 transform hover:-translate-y-2 snap-start w-[calc(80vw-1rem)] flex-shrink-0 sm:w-auto"
|
|
||||||
whileHover={{ scale: 1.02 }}
|
|
||||||
>
|
|
||||||
<div className="p-4 md:p-6 text-center">
|
|
||||||
<div className="mb-4">
|
|
||||||
<h3 className="text-2xl font-bold text-[#8B4513] mb-2 text-gradient">
|
|
||||||
World Chocolate Day
|
|
||||||
</h3>
|
|
||||||
<p className="text-gray-600">
|
|
||||||
Celebrating the art of chocolate making
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="bg-gradient-to-br from-amber-100 to-orange-100 rounded-lg p-4 shadow-premium">
|
|
||||||
<div className="text-4xl mb-2">🍫</div>
|
|
||||||
<p className="text-sm text-gray-700">
|
|
||||||
Join us in celebrating the world's favorite treat
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
posts?.slice(0, 3).map((post, index) => (
|
|
||||||
<motion.div
|
|
||||||
key={post.id}
|
|
||||||
initial="initial"
|
|
||||||
whileInView="animate"
|
|
||||||
viewport={{ once: true, margin: "-50px" }}
|
|
||||||
variants={
|
|
||||||
index === 0
|
|
||||||
? fadeInLeft
|
|
||||||
: index === 1
|
|
||||||
? fadeInUp
|
|
||||||
: fadeInRight
|
|
||||||
}
|
|
||||||
className="snap-start w-[calc(80vw-1rem)] flex-shrink-0 sm:w-auto bg-white rounded-lg shadow-premium overflow-hidden hover:shadow-premium-hover transition-all duration-500 transform hover:-translate-y-2"
|
|
||||||
whileHover={{ scale: 1.02 }}
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href={post.permalink}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="block"
|
|
||||||
>
|
|
||||||
<div className="relative h-64 md:h-96">
|
|
||||||
<Image
|
|
||||||
src={post.mediaUrl}
|
|
||||||
alt={post.caption || "Instagram post"}
|
|
||||||
fill
|
|
||||||
className="object-cover img-premium"
|
|
||||||
draggable={false}
|
|
||||||
quality={85}
|
|
||||||
onError={(e) => {
|
|
||||||
const target = e.target as HTMLImageElement;
|
|
||||||
target.src = "/bst/bs1.svg";
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-t from-black/30 via-transparent to-transparent" />
|
|
||||||
{post.mediaType === "VIDEO" && (
|
|
||||||
<div className="absolute top-4 right-4 bg-black/50 rounded-full p-2">
|
|
||||||
<svg
|
|
||||||
className="w-4 h-4 text-white"
|
|
||||||
fill="currentColor"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
>
|
|
||||||
<path d="M8 5v10l8-5-8-5z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="absolute bottom-4 left-4 right-4">
|
|
||||||
<div className="glass rounded-lg p-3 border border-white/20">
|
|
||||||
<p className="text-sm text-gray-800 line-clamp-2">
|
|
||||||
{post.caption?.slice(0, 100)}...
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</motion.div>
|
|
||||||
))
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Section>
|
|
||||||
|
|
||||||
{/* In the Spotlight Section */}
|
{/* In the Spotlight Section */}
|
||||||
<Section background="white">
|
<Section background="white">
|
||||||
@ -785,7 +447,6 @@ export default function Home() {
|
|||||||
animate={{ x: `-${spotlightIndex * 152}px` }}
|
animate={{ x: `-${spotlightIndex * 152}px` }}
|
||||||
transition={{ type: "spring", stiffness: 80, damping: 18 }}
|
transition={{ type: "spring", stiffness: 80, damping: 18 }}
|
||||||
>
|
>
|
||||||
{/* Create 12 tiles (3 sets of 4 logos) */}
|
|
||||||
{Array(12)
|
{Array(12)
|
||||||
.fill(0)
|
.fill(0)
|
||||||
.map((_, i) => {
|
.map((_, i) => {
|
||||||
@ -795,7 +456,10 @@ export default function Home() {
|
|||||||
<motion.div
|
<motion.div
|
||||||
key={i}
|
key={i}
|
||||||
className="w-24 h-24 md:w-32 md:h-32 lg:w-36 lg:h-36 bg-white rounded-full flex items-center justify-center shadow-premium hover:shadow-premium-hover flex-shrink-0 transition-all duration-300"
|
className="w-24 h-24 md:w-32 md:h-32 lg:w-36 lg:h-36 bg-white rounded-full flex items-center justify-center shadow-premium hover:shadow-premium-hover flex-shrink-0 transition-all duration-300"
|
||||||
style={{ boxShadow: "0 2px 12px 0 rgba(60,42,33,0.10)" }}
|
style={{
|
||||||
|
boxShadow: "0 4px 20px 0 rgba(60,42,33,0.15)", // Increased blur and opacity
|
||||||
|
margin: "8px", // Added margin to give space for shadow
|
||||||
|
}}
|
||||||
whileHover={{
|
whileHover={{
|
||||||
scale: 1.1,
|
scale: 1.1,
|
||||||
rotate: 5,
|
rotate: 5,
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
'use client';
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect, useRef } from 'react';
|
import { useState, useEffect, useRef } from "react";
|
||||||
import { motion, AnimatePresence } from 'framer-motion';
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
import Image from 'next/image';
|
import Image from "next/image";
|
||||||
|
|
||||||
const banners = [
|
const banners = [
|
||||||
{ id: 1, src: '/banners/b1.svg', alt: 'Mozimo Chocolate Banner 1' },
|
{ id: 1, src: "/banners/b1.svg", alt: "Mozimo Chocolate Banner 1" },
|
||||||
{ id: 2, src: '/banners/b2.svg', alt: 'Mozimo Chocolate Banner 2' },
|
{ id: 2, src: "/banners/b3.svg", alt: "Mozimo Chocolate Banner 2" },
|
||||||
{ id: 3, src: '/banners/b3.svg', alt: 'Mozimo Chocolate Banner 3' },
|
{ id: 3, src: "/banners/b2.svg", alt: "Mozimo Chocolate Banner 3" },
|
||||||
{ id: 4, src: '/banners/b4.svg', alt: 'Mozimo Chocolate Banner 4' },
|
{ id: 4, src: "/banners/b4.svg", alt: "Mozimo Chocolate Banner 4" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function BannerSlider() {
|
export default function BannerSlider() {
|
||||||
@ -49,7 +49,7 @@ export default function BannerSlider() {
|
|||||||
|
|
||||||
const slideVariants = {
|
const slideVariants = {
|
||||||
enter: (direction: number) => ({
|
enter: (direction: number) => ({
|
||||||
x: direction > 0 ? '100%' : '-100%',
|
x: direction > 0 ? "100%" : "-100%",
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
}),
|
}),
|
||||||
center: {
|
center: {
|
||||||
@ -57,9 +57,9 @@ export default function BannerSlider() {
|
|||||||
opacity: 1,
|
opacity: 1,
|
||||||
},
|
},
|
||||||
exit: (direction: number) => ({
|
exit: (direction: number) => ({
|
||||||
x: direction < 0 ? '100%' : '-100%',
|
x: direction < 0 ? "100%" : "-100%",
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
})
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const swipeConfidenceThreshold = 10000;
|
const swipeConfidenceThreshold = 10000;
|
||||||
@ -105,7 +105,7 @@ export default function BannerSlider() {
|
|||||||
exit="exit"
|
exit="exit"
|
||||||
transition={{
|
transition={{
|
||||||
x: { type: "spring", stiffness: 300, damping: 30 },
|
x: { type: "spring", stiffness: 300, damping: 30 },
|
||||||
duration: 0.4
|
duration: 0.4,
|
||||||
}}
|
}}
|
||||||
drag="x"
|
drag="x"
|
||||||
dragConstraints={{ left: 0, right: 0 }}
|
dragConstraints={{ left: 0, right: 0 }}
|
||||||
@ -128,7 +128,7 @@ export default function BannerSlider() {
|
|||||||
className="object-cover img-premium"
|
className="object-cover img-premium"
|
||||||
draggable={false}
|
draggable={false}
|
||||||
priority={currentIndex === 0}
|
priority={currentIndex === 0}
|
||||||
loading={currentIndex === 0 ? 'eager' : 'lazy'}
|
loading={currentIndex === 0 ? "eager" : "lazy"}
|
||||||
sizes="100vw"
|
sizes="100vw"
|
||||||
quality={85}
|
quality={85}
|
||||||
/>
|
/>
|
||||||
@ -139,6 +139,7 @@ export default function BannerSlider() {
|
|||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
|
|
||||||
{/* Premium Shop Now Button */}
|
{/* Premium Shop Now Button */}
|
||||||
|
{currentIndex === 0 && (
|
||||||
<div className="absolute bottom-16 md:bottom-20 left-1/2 transform -translate-x-1/2 z-10">
|
<div className="absolute bottom-16 md:bottom-20 left-1/2 transform -translate-x-1/2 z-10">
|
||||||
<motion.button
|
<motion.button
|
||||||
initial={{ opacity: 0, y: 30 }}
|
initial={{ opacity: 0, y: 30 }}
|
||||||
@ -147,22 +148,23 @@ export default function BannerSlider() {
|
|||||||
whileHover={{
|
whileHover={{
|
||||||
scale: 1.05,
|
scale: 1.05,
|
||||||
y: -2,
|
y: -2,
|
||||||
transition: { duration: 0.3 }
|
transition: { duration: 0.3 },
|
||||||
}}
|
}}
|
||||||
whileTap={{ scale: 0.95 }}
|
whileTap={{ scale: 0.95 }}
|
||||||
className="glass text-[#3C2A21] px-8 md:px-12 py-4 md:py-5 rounded-full font-semibold text-base md:text-lg shadow-premium hover:shadow-premium-hover transition-all duration-300 font-renner border border-white/20 hover:border-white/40"
|
className="bg-white text-[#3C2A21] px-8 md:px-12 py-4 md:py-5 rounded-full font-semibold text-base md:text-lg shadow-premium hover:shadow-premium-hover transition-all duration-300 font-renner border border-white/20 hover:border-white/40"
|
||||||
style={{
|
style={{
|
||||||
fontWeight: 300,
|
fontWeight: 300,
|
||||||
fontSize: '16px',
|
fontFamily: "Renner*",
|
||||||
lineHeight: '100%',
|
fontSize: "22px",
|
||||||
letterSpacing: '0%',
|
lineHeight: "100%",
|
||||||
fontFamily: 'Renner'
|
letterSpacing: "0%",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="relative z-10">Shop Now</span>
|
<span className="relative z-10">Shop Now</span>
|
||||||
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent -translate-x-full hover:translate-x-full transition-transform duration-700 ease-out rounded-full" />
|
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent -translate-x-full hover:translate-x-full transition-transform duration-700 ease-out rounded-full" />
|
||||||
</motion.button>
|
</motion.button>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Premium Navigation Arrows - Hidden on mobile */}
|
{/* Premium Navigation Arrows - Hidden on mobile */}
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
@ -179,8 +181,18 @@ export default function BannerSlider() {
|
|||||||
whileTap={{ scale: 0.95 }}
|
whileTap={{ scale: 0.95 }}
|
||||||
aria-label="Previous banner"
|
aria-label="Previous banner"
|
||||||
>
|
>
|
||||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
|
className="w-5 h-5"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M15 19l-7-7 7-7"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</motion.button>
|
</motion.button>
|
||||||
|
|
||||||
@ -195,8 +207,18 @@ export default function BannerSlider() {
|
|||||||
whileTap={{ scale: 0.95 }}
|
whileTap={{ scale: 0.95 }}
|
||||||
aria-label="Next banner"
|
aria-label="Next banner"
|
||||||
>
|
>
|
||||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
className="w-5 h-5"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M9 5l7 7-7 7"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</motion.button>
|
</motion.button>
|
||||||
</>
|
</>
|
||||||
@ -212,8 +234,18 @@ export default function BannerSlider() {
|
|||||||
whileTap={{ scale: 0.95 }}
|
whileTap={{ scale: 0.95 }}
|
||||||
aria-label="Previous banner"
|
aria-label="Previous banner"
|
||||||
>
|
>
|
||||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
|
className="w-4 h-4"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M15 19l-7-7 7-7"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</motion.button>
|
</motion.button>
|
||||||
|
|
||||||
@ -224,22 +256,32 @@ export default function BannerSlider() {
|
|||||||
whileTap={{ scale: 0.95 }}
|
whileTap={{ scale: 0.95 }}
|
||||||
aria-label="Next banner"
|
aria-label="Next banner"
|
||||||
>
|
>
|
||||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
className="w-4 h-4"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M9 5l7 7-7 7"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</motion.button>
|
</motion.button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Premium Dots Indicator */}
|
{/* Premium Dots Indicator */}
|
||||||
<div className="absolute bottom-6 md:bottom-8 left-1/2 transform -translate-x-1/2 z-20 flex space-x-2 md:space-x-3">
|
<div className="absolute bottom-6 md:bottom-8 left-1/2 transform -translate-x-1/2 z-20 hidden md:flex space-x-2 md:space-x-3">
|
||||||
{banners.map((_, index) => (
|
{banners.map((_, index) => (
|
||||||
<motion.button
|
<motion.button
|
||||||
key={index}
|
key={index}
|
||||||
onClick={() => goToSlide(index)}
|
onClick={() => goToSlide(index)}
|
||||||
className={`w-2 h-2 md:w-3 md:h-3 rounded-full transition-all duration-300 ${
|
className={`w-2 h-2 md:w-3 md:h-3 rounded-full transition-all duration-300 ${
|
||||||
index === currentIndex
|
index === currentIndex
|
||||||
? 'bg-white scale-110 shadow-glow'
|
? "bg-white scale-110 shadow-glow"
|
||||||
: 'bg-white/50 hover:bg-white/70 hover:scale-110'
|
: "bg-white/50 hover:bg-white/70 hover:scale-110"
|
||||||
}`}
|
}`}
|
||||||
whileHover={{ scale: 1.2 }}
|
whileHover={{ scale: 1.2 }}
|
||||||
whileTap={{ scale: 0.9 }}
|
whileTap={{ scale: 0.9 }}
|
||||||
|
|||||||
@ -60,7 +60,7 @@ export default function Header() {
|
|||||||
<>
|
<>
|
||||||
{/* Mobile Header - Only visible on mobile */}
|
{/* Mobile Header - Only visible on mobile */}
|
||||||
<motion.header
|
<motion.header
|
||||||
className="fixed top-0 z-[60] w-full md:hidden"
|
className="fixed top-0 z-[60] w-full md:hidden p-1 "
|
||||||
initial={false}
|
initial={false}
|
||||||
animate={{
|
animate={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
@ -75,7 +75,7 @@ export default function Header() {
|
|||||||
ease: [0.25, 0.46, 0.45, 0.94],
|
ease: [0.25, 0.46, 0.45, 0.94],
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<nav className="relative bg-white border border-white/20 shadow-premium w-full h-full flex items-center px-4">
|
<nav className="relative bg-white border border-white/20 shadow-premium w-full h-full flex items-center px-4 rounded-[15px]">
|
||||||
{/* Left: Hamburger Menu */}
|
{/* Left: Hamburger Menu */}
|
||||||
<div className="absolute left-4 top-1/2 -translate-y-1/2">
|
<div className="absolute left-4 top-1/2 -translate-y-1/2">
|
||||||
<motion.button
|
<motion.button
|
||||||
@ -136,7 +136,7 @@ export default function Header() {
|
|||||||
fill
|
fill
|
||||||
className="object-contain drop-shadow-lg"
|
className="object-contain drop-shadow-lg"
|
||||||
priority
|
priority
|
||||||
sizes="40px"
|
sizes="60px"
|
||||||
quality={95}
|
quality={95}
|
||||||
placeholder="blur"
|
placeholder="blur"
|
||||||
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAIAAoDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAv/xAAhEAACAQMDBQAAAAAAAAAAAAABAgMABAUGIWGRkqGx0f/EABUBAQEAAAAAAAAAAAAAAAAAAAMF/8QAGhEAAgIDAAAAAAAAAAAAAAAAAAECEgMRkf/aAAwDAQACEQMRAD8AltJagyeH0AthI5xdrLcNM91BF5pX2HaH9bcfaSXWGaRmknyJckliyjqTzSlT54b6bk+h0R//2Q=="
|
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAIAAoDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAv/xAAhEAACAQMDBQAAAAAAAAAAAAABAgMABAUGIWGRkqGx0f/EABUBAQEAAAAAAAAAAAAAAAAAAAMF/8QAGhEAAgIDAAAAAAAAAAAAAAAAAAECEgMRkf/aAAwDAQACEQMRAD8AltJagyeH0AthI5xdrLcNM91BF5pX2HaH9bcfaSXWGaRmknyJckliyjqTzSlT54b6bk+h0R//2Q=="
|
||||||
@ -215,7 +215,7 @@ export default function Header() {
|
|||||||
|
|
||||||
{/* Desktop Header - Only visible on desktop */}
|
{/* Desktop Header - Only visible on desktop */}
|
||||||
<motion.header
|
<motion.header
|
||||||
className="fixed top-0 z-50 hidden md:block"
|
className="fixed top-0 z-50 hidden md:block "
|
||||||
initial={false}
|
initial={false}
|
||||||
animate={{
|
animate={{
|
||||||
width: isScrolled ? "100%" : "1440px",
|
width: isScrolled ? "100%" : "1440px",
|
||||||
@ -242,9 +242,9 @@ export default function Header() {
|
|||||||
href="#about"
|
href="#about"
|
||||||
className="text-gray-800 hover:text-[#8B4513] transition-all duration-300 font-renner relative group"
|
className="text-gray-800 hover:text-[#8B4513] transition-all duration-300 font-renner relative group"
|
||||||
style={{
|
style={{
|
||||||
fontWeight: 100,
|
fontWeight: 300,
|
||||||
fontFamily: "Renner",
|
fontFamily: "Renner*",
|
||||||
fontSize: "18px",
|
fontSize: "22px",
|
||||||
lineHeight: "100%",
|
lineHeight: "100%",
|
||||||
letterSpacing: "0%",
|
letterSpacing: "0%",
|
||||||
}}
|
}}
|
||||||
@ -257,9 +257,9 @@ export default function Header() {
|
|||||||
href="#shop"
|
href="#shop"
|
||||||
className="text-gray-800 hover:text-[#8B4513] transition-all duration-300 font-renner relative group"
|
className="text-gray-800 hover:text-[#8B4513] transition-all duration-300 font-renner relative group"
|
||||||
style={{
|
style={{
|
||||||
fontWeight: 100,
|
fontWeight: 300,
|
||||||
fontFamily: "Renner",
|
fontFamily: "Renner*",
|
||||||
fontSize: "18px",
|
fontSize: "22px",
|
||||||
lineHeight: "100%",
|
lineHeight: "100%",
|
||||||
letterSpacing: "0%",
|
letterSpacing: "0%",
|
||||||
}}
|
}}
|
||||||
@ -309,9 +309,9 @@ export default function Header() {
|
|||||||
<motion.button
|
<motion.button
|
||||||
className="flex items-center space-x-1 text-gray-800 hover:text-[#8B4513] transition-all duration-300 font-renner relative group"
|
className="flex items-center space-x-1 text-gray-800 hover:text-[#8B4513] transition-all duration-300 font-renner relative group"
|
||||||
style={{
|
style={{
|
||||||
fontWeight: 100,
|
fontWeight: 300,
|
||||||
fontFamily: "Renner",
|
fontFamily: "Renner*",
|
||||||
fontSize: "18px",
|
fontSize: "22px",
|
||||||
lineHeight: "100%",
|
lineHeight: "100%",
|
||||||
letterSpacing: "0%",
|
letterSpacing: "0%",
|
||||||
}}
|
}}
|
||||||
@ -427,7 +427,7 @@ export default function Header() {
|
|||||||
className="block text-lg font-renner text-gray-800 hover:text-[#8B4513] transition-all duration-300 py-3 border-b border-gray-100"
|
className="block text-lg font-renner text-gray-800 hover:text-[#8B4513] transition-all duration-300 py-3 border-b border-gray-100"
|
||||||
style={{
|
style={{
|
||||||
fontWeight: 300,
|
fontWeight: 300,
|
||||||
fontFamily: "Renner",
|
fontFamily: "Renner*",
|
||||||
fontSize: "18px",
|
fontSize: "18px",
|
||||||
lineHeight: "100%",
|
lineHeight: "100%",
|
||||||
letterSpacing: "0%",
|
letterSpacing: "0%",
|
||||||
@ -442,7 +442,7 @@ export default function Header() {
|
|||||||
className="block text-lg font-renner text-gray-800 hover:text-[#8B4513] transition-all duration-300 py-3 border-b border-gray-100"
|
className="block text-lg font-renner text-gray-800 hover:text-[#8B4513] transition-all duration-300 py-3 border-b border-gray-100"
|
||||||
style={{
|
style={{
|
||||||
fontWeight: 300,
|
fontWeight: 300,
|
||||||
fontFamily: "Renner",
|
fontFamily: "Renner*",
|
||||||
fontSize: "18px",
|
fontSize: "18px",
|
||||||
lineHeight: "100%",
|
lineHeight: "100%",
|
||||||
letterSpacing: "0%",
|
letterSpacing: "0%",
|
||||||
@ -457,7 +457,7 @@ export default function Header() {
|
|||||||
className="block text-lg font-renner text-gray-800 hover:text-[#8B4513] transition-all duration-300 py-3 border-b border-gray-100"
|
className="block text-lg font-renner text-gray-800 hover:text-[#8B4513] transition-all duration-300 py-3 border-b border-gray-100"
|
||||||
style={{
|
style={{
|
||||||
fontWeight: 300,
|
fontWeight: 300,
|
||||||
fontFamily: "Renner",
|
fontFamily: "Renner*",
|
||||||
fontSize: "18px",
|
fontSize: "18px",
|
||||||
lineHeight: "100%",
|
lineHeight: "100%",
|
||||||
letterSpacing: "0%",
|
letterSpacing: "0%",
|
||||||
|
|||||||
152
src/components/ProductCategory.tsx
Normal file
152
src/components/ProductCategory.tsx
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
"use client";
|
||||||
|
import { useState, useRef, useCallback, useMemo } from "react";
|
||||||
|
import { AnimatePresence } from "framer-motion";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
import Section from "@/components/Section";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
export default function ProductCategory() {
|
||||||
|
const [currentCategory, setCurrentCategory] = useState(0);
|
||||||
|
const categoriesSectionRef = useRef<HTMLDivElement>(null);
|
||||||
|
const fadeInLeft = {
|
||||||
|
initial: { opacity: 0, x: -30 },
|
||||||
|
animate: { opacity: 1, x: 0 },
|
||||||
|
transition: { duration: 0.8, ease: [0.25, 0.46, 0.45, 0.94] },
|
||||||
|
};
|
||||||
|
|
||||||
|
const fadeInRight = {
|
||||||
|
initial: { opacity: 0, x: 30 },
|
||||||
|
animate: { opacity: 1, x: 0 },
|
||||||
|
transition: { duration: 0.8, ease: [0.25, 0.46, 0.45, 0.94] },
|
||||||
|
};
|
||||||
|
const categories = [
|
||||||
|
"Bars",
|
||||||
|
"Barks",
|
||||||
|
"Pralines",
|
||||||
|
"Spreads",
|
||||||
|
"Dragees",
|
||||||
|
"Gelatos",
|
||||||
|
];
|
||||||
|
const categoryImages = [
|
||||||
|
"/categories/c1.svg",
|
||||||
|
"/categories/c2.svg",
|
||||||
|
"/categories/c3.svg",
|
||||||
|
"/categories/c4.svg",
|
||||||
|
"/categories/c5.svg",
|
||||||
|
"/categories/c6.svg",
|
||||||
|
];
|
||||||
|
|
||||||
|
// Memoize category change handler for better performance
|
||||||
|
const handleCategoryChange = useCallback((idx: number) => {
|
||||||
|
setCurrentCategory(idx);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Memoize category buttons to prevent unnecessary re-renders
|
||||||
|
const categoryButtons = useMemo(() => {
|
||||||
|
return categories.map((category, idx) => (
|
||||||
|
<motion.li
|
||||||
|
key={category}
|
||||||
|
initial={{ opacity: 0, x: -20 }}
|
||||||
|
whileInView={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.4, delay: idx * 0.05 }} // Reduced delay
|
||||||
|
viewport={{ once: true }}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className={`group flex items-center gap-4 transition-all duration-200 ease-out w-full text-left font-moneta hover:scale-105
|
||||||
|
${
|
||||||
|
idx === currentCategory
|
||||||
|
? "text-[#703133] font-normal"
|
||||||
|
: "text-[#703133] opacity-60 font-light"
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
style={{
|
||||||
|
fontFamily: "MonetaSans-Regular",
|
||||||
|
fontWeight: idx === currentCategory ? 400 : 300,
|
||||||
|
fontSize:
|
||||||
|
idx === currentCategory
|
||||||
|
? "clamp(22px, 5vw, 64px)"
|
||||||
|
: "clamp(18px, 4vw, 56px)",
|
||||||
|
lineHeight: "120%",
|
||||||
|
letterSpacing: "0%",
|
||||||
|
transition: "all 0.2s cubic-bezier(0.4, 0.0, 0.2, 1)", // Even faster transition
|
||||||
|
}}
|
||||||
|
onClick={() => handleCategoryChange(idx)}
|
||||||
|
onMouseEnter={() => handleCategoryChange(idx)}
|
||||||
|
onTouchStart={() => handleCategoryChange(idx)} // Add this for mobile touch
|
||||||
|
tabIndex={-1}
|
||||||
|
>
|
||||||
|
{/* Show only on mobile */}
|
||||||
|
<div className="block lg:hidden w-16 h-16 rounded-full overflow-hidden shrink-0">
|
||||||
|
<Image
|
||||||
|
src={categoryImages[idx]}
|
||||||
|
alt={category}
|
||||||
|
width={56}
|
||||||
|
height={56}
|
||||||
|
className="w-full h-full object-cover"
|
||||||
|
draggable={false}
|
||||||
|
quality={85}
|
||||||
|
sizes="(max-width: 375px) 40px, (max-width: 640px) 44px, (max-width: 768px) 48px, 56px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/* Category name */}
|
||||||
|
<span className="text-left">{category}</span>
|
||||||
|
</button>
|
||||||
|
</motion.li>
|
||||||
|
));
|
||||||
|
}, [currentCategory, handleCategoryChange]);
|
||||||
|
|
||||||
|
// Memoize the category image component
|
||||||
|
const categoryImageComponent = useMemo(
|
||||||
|
() => (
|
||||||
|
<AnimatePresence mode="wait">
|
||||||
|
<motion.img
|
||||||
|
key={currentCategory}
|
||||||
|
src={categoryImages[currentCategory]}
|
||||||
|
alt={categories[currentCategory]}
|
||||||
|
initial={{ opacity: 0, scale: 1.01 }}
|
||||||
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
|
exit={{ opacity: 0, scale: 0.99 }}
|
||||||
|
transition={{ duration: 0.25, ease: [0.4, 0.0, 0.2, 1] }} // Super fast transition
|
||||||
|
className="w-full h-full object-cover rounded-2xl shadow-premium hover:shadow-premium-hover transition-all duration-200 img-premium" // Faster shadow
|
||||||
|
draggable={false}
|
||||||
|
style={{ maxHeight: "600px", maxWidth: "100%" }}
|
||||||
|
/>
|
||||||
|
</AnimatePresence>
|
||||||
|
),
|
||||||
|
[currentCategory]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-white font-renner">
|
||||||
|
{/* Product Categories Section */}
|
||||||
|
<Section background="white" id="categories">
|
||||||
|
<div
|
||||||
|
ref={categoriesSectionRef}
|
||||||
|
className="grid grid-cols-1 lg:grid-cols-2 gap-0 items-stretch min-h-[400px] md:min-h-[500px]"
|
||||||
|
>
|
||||||
|
{/* Left Column - Categories List */}
|
||||||
|
<motion.div
|
||||||
|
initial="initial"
|
||||||
|
whileInView="animate"
|
||||||
|
viewport={{ once: true, margin: "-50px" }}
|
||||||
|
variants={fadeInLeft}
|
||||||
|
className="flex flex-col justify-center h-full bg-white px-4 md:px-8 py-6 md:py-12 order-2 lg:order-1"
|
||||||
|
>
|
||||||
|
<ul className="space-y-4 md:space-y-6">{categoryButtons}</ul>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Right Column - Large Category Image (desktop only) */}
|
||||||
|
<motion.div
|
||||||
|
initial="initial"
|
||||||
|
whileInView="animate"
|
||||||
|
viewport={{ once: true, margin: "-50px" }}
|
||||||
|
variants={fadeInRight}
|
||||||
|
className="relative hidden lg:flex items-center justify-center h-full min-h-[300px] md:min-h-[400px] bg-white order-1 lg:order-2"
|
||||||
|
>
|
||||||
|
{categoryImageComponent}
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
284
src/components/SocialMedia.tsx
Normal file
284
src/components/SocialMedia.tsx
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
"use client";
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
import Image from "next/image";
|
||||||
|
import Section from "./Section";
|
||||||
|
import { useInstagram } from "@/hooks/useInstagram";
|
||||||
|
|
||||||
|
export default function SocialMedia() {
|
||||||
|
const { posts, loading, error, isTokenExpired } = useInstagram();
|
||||||
|
const scrollRef = useRef<HTMLDivElement>(null);
|
||||||
|
const fadeInUp = {
|
||||||
|
initial: { opacity: 0, y: 30 },
|
||||||
|
animate: { opacity: 1, y: 0 },
|
||||||
|
transition: { duration: 0.8, ease: [0.25, 0.46, 0.45, 0.94] },
|
||||||
|
};
|
||||||
|
|
||||||
|
const fadeInLeft = {
|
||||||
|
initial: { opacity: 0, x: -30 },
|
||||||
|
animate: { opacity: 1, x: 0 },
|
||||||
|
transition: { duration: 0.8, ease: [0.25, 0.46, 0.45, 0.94] },
|
||||||
|
};
|
||||||
|
|
||||||
|
const fadeInRight = {
|
||||||
|
initial: { opacity: 0, x: 30 },
|
||||||
|
animate: { opacity: 1, x: 0 },
|
||||||
|
transition: { duration: 0.8, ease: [0.25, 0.46, 0.45, 0.94] },
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Only auto-scroll on mobile (<768px)
|
||||||
|
if (window.innerWidth >= 768) return;
|
||||||
|
|
||||||
|
const container = scrollRef.current;
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
let scrollAmount = 0;
|
||||||
|
const cardWidth = container.firstElementChild?.clientWidth || 300;
|
||||||
|
const scrollStep = cardWidth + 16; // 16px gap between items
|
||||||
|
let direction = 1; // 1 = right, -1 = left
|
||||||
|
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
if (!container) return;
|
||||||
|
scrollAmount += scrollStep * direction;
|
||||||
|
|
||||||
|
// Reverse direction if hitting ends
|
||||||
|
if (
|
||||||
|
scrollAmount >= container.scrollWidth - container.clientWidth ||
|
||||||
|
scrollAmount <= 0
|
||||||
|
) {
|
||||||
|
direction *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
container.scrollTo({
|
||||||
|
left: scrollAmount,
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
}, 3000); // scroll every 3s
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section background="cream" padding="md">
|
||||||
|
<motion.div
|
||||||
|
initial="initial"
|
||||||
|
whileInView="animate"
|
||||||
|
viewport={{ once: true, margin: "-50px" }}
|
||||||
|
variants={fadeInUp}
|
||||||
|
className="text-center mb-8 md:mb-12"
|
||||||
|
>
|
||||||
|
<h2
|
||||||
|
className="text-3xl md:text-4xl lg:text-5xl font-moneta text-[#703133] mb-6 md:mb-8 text-gradient"
|
||||||
|
style={{
|
||||||
|
fontWeight: 400,
|
||||||
|
fontSize: "clamp(28px, 5vw, 48px)",
|
||||||
|
lineHeight: "120%",
|
||||||
|
letterSpacing: "0%",
|
||||||
|
fontFamily: "MonetaSans-Regular",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Follow us on Instagram
|
||||||
|
</h2>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
ref={scrollRef}
|
||||||
|
className="flex overflow-x-auto no-scrollbar snap-x snap-mandatory gap-4 px-4 sm:grid sm:grid-cols-2 lg:grid-cols-3 sm:gap-6 md:gap-8 max-w-7xl mx-auto"
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<>
|
||||||
|
{[1, 2, 3].map((i) => (
|
||||||
|
<motion.div
|
||||||
|
key={i}
|
||||||
|
className="bg-white rounded-lg shadow-premium h-64 md:h-96 skeleton snap-start w-[calc(80vw-1rem)] flex-shrink-0 sm:w-auto"
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.6, delay: i * 0.1 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
) : error ? (
|
||||||
|
isTokenExpired ? (
|
||||||
|
<div className="col-span-full text-center py-12 sm:col-span-2 lg:col-span-3">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.6 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
className="max-w-md mx-auto"
|
||||||
|
>
|
||||||
|
<div className="w-16 h-16 bg-gradient-to-br from-amber-200 to-orange-300 rounded-full mx-auto mb-4 flex items-center justify-center shadow-premium">
|
||||||
|
<span className="text-2xl">🔗</span>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-semibold text-[#703133] mb-2">
|
||||||
|
Instagram Connection Expired
|
||||||
|
</h3>
|
||||||
|
<p className="text-gray-600 mb-4">
|
||||||
|
Our Instagram connection needs to be refreshed. We're
|
||||||
|
working on getting it back up!
|
||||||
|
</p>
|
||||||
|
<div className="text-sm text-gray-500">
|
||||||
|
In the meantime, follow us @mozimo_chocolate
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{/* Left Block - Chocolate Spread Jar */}
|
||||||
|
<motion.div
|
||||||
|
initial="initial"
|
||||||
|
whileInView="animate"
|
||||||
|
viewport={{ once: true, margin: "-50px" }}
|
||||||
|
variants={fadeInLeft}
|
||||||
|
className="bg-white rounded-lg shadow-premium overflow-hidden hover:shadow-premium-hover transition-all duration-500 transform hover:-translate-y-2 snap-start w-[calc(80vw-1rem)] flex-shrink-0 sm:w-auto"
|
||||||
|
whileHover={{ scale: 1.02 }}
|
||||||
|
>
|
||||||
|
<div className="relative h-64 md:h-96 bg-gradient-to-br from-amber-50 to-orange-50 flex items-center justify-center">
|
||||||
|
<motion.div
|
||||||
|
className="text-center"
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
transition={{ duration: 0.3 }}
|
||||||
|
>
|
||||||
|
<div className="w-32 h-32 bg-gradient-to-br from-amber-200 to-orange-300 rounded-full mx-auto mb-4 flex items-center justify-center shadow-premium">
|
||||||
|
<span className="text-4xl">🍫</span>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white rounded-lg p-4 mx-4 shadow-premium">
|
||||||
|
<div className="font-semibold text-[#703133] text-lg">
|
||||||
|
MOZIMO
|
||||||
|
</div>
|
||||||
|
<div className="text-sm text-gray-600">
|
||||||
|
SINGLE ORIGIN HAZELNUT SPREAD 45%
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Middle Block - Magazine Article */}
|
||||||
|
<motion.div
|
||||||
|
initial="initial"
|
||||||
|
whileInView="animate"
|
||||||
|
viewport={{ once: true, margin: "-50px" }}
|
||||||
|
variants={fadeInUp}
|
||||||
|
className="bg-white rounded-lg shadow-premium overflow-hidden hover:shadow-premium-hover transition-all duration-500 transform hover:-translate-y-2 snap-start w-[calc(80vw-1rem)] flex-shrink-0 sm:w-auto"
|
||||||
|
whileHover={{ scale: 1.02 }}
|
||||||
|
>
|
||||||
|
<div className="p-4 md:p-6">
|
||||||
|
<div className="bg-red-600 h-32 rounded-lg mb-4 flex items-center justify-center shadow-premium">
|
||||||
|
<span className="text-white text-2xl">🍫</span>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-2 gap-4 mb-4">
|
||||||
|
<div className="bg-gray-200 h-20 rounded-lg flex items-center justify-center shadow-premium">
|
||||||
|
<span className="text-lg">🍰</span>
|
||||||
|
</div>
|
||||||
|
<div className="bg-gray-200 h-20 rounded-lg flex items-center justify-center shadow-premium">
|
||||||
|
<span className="text-lg">👨🍳</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-gray-700 space-y-2 leading-relaxed">
|
||||||
|
<p>
|
||||||
|
<strong>By RUPALI DEAN</strong>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>
|
||||||
|
MOZIMO'S CHOCOLATE PIE BY PRIYANKA GUPTA
|
||||||
|
</strong>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
isolat[ing] beans to not only single ori- but also to
|
||||||
|
single farms so as to express unique complexity.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Right Block - World Chocolate Day */}
|
||||||
|
<motion.div
|
||||||
|
initial="initial"
|
||||||
|
whileInView="animate"
|
||||||
|
viewport={{ once: true, margin: "-50px" }}
|
||||||
|
variants={fadeInRight}
|
||||||
|
className="bg-white rounded-lg shadow-premium overflow-hidden hover:shadow-premium-hover transition-all duration-500 transform hover:-translate-y-2 snap-start w-[calc(80vw-1rem)] flex-shrink-0 sm:w-auto"
|
||||||
|
whileHover={{ scale: 1.02 }}
|
||||||
|
>
|
||||||
|
<div className="p-4 md:p-6 text-center">
|
||||||
|
<div className="mb-4">
|
||||||
|
<h3 className="text-2xl font-bold text-[#8B4513] mb-2 text-gradient">
|
||||||
|
World Chocolate Day
|
||||||
|
</h3>
|
||||||
|
<p className="text-gray-600">
|
||||||
|
Celebrating the art of chocolate making
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="bg-gradient-to-br from-amber-100 to-orange-100 rounded-lg p-4 shadow-premium">
|
||||||
|
<div className="text-4xl mb-2">🍫</div>
|
||||||
|
<p className="text-sm text-gray-700">
|
||||||
|
Join us in celebrating the world's favorite treat
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
posts?.slice(0, 3).map((post, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={post.id}
|
||||||
|
initial="initial"
|
||||||
|
whileInView="animate"
|
||||||
|
viewport={{ once: true, margin: "-50px" }}
|
||||||
|
variants={
|
||||||
|
index === 0 ? fadeInLeft : index === 1 ? fadeInUp : fadeInRight
|
||||||
|
}
|
||||||
|
className="snap-start w-[calc(80vw-1rem)] flex-shrink-0 sm:w-auto bg-white rounded-lg shadow-premium overflow-hidden hover:shadow-premium-hover transition-all duration-500 transform hover:-translate-y-2"
|
||||||
|
whileHover={{ scale: 1.02 }}
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href={post.permalink}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="block"
|
||||||
|
>
|
||||||
|
<div className="relative h-64 md:h-96">
|
||||||
|
<Image
|
||||||
|
src={post.mediaUrl}
|
||||||
|
alt={post.caption || "Instagram post"}
|
||||||
|
fill
|
||||||
|
className="object-cover img-premium"
|
||||||
|
draggable={false}
|
||||||
|
quality={85}
|
||||||
|
onError={(e) => {
|
||||||
|
const target = e.target as HTMLImageElement;
|
||||||
|
target.src = "/bst/bs1.svg";
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-t from-black/30 via-transparent to-transparent" />
|
||||||
|
{post.mediaType === "VIDEO" && (
|
||||||
|
<div className="absolute top-4 right-4 bg-black/50 rounded-full p-2">
|
||||||
|
<svg
|
||||||
|
className="w-4 h-4 text-white"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path d="M8 5v10l8-5-8-5z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="absolute bottom-4 left-4 right-4">
|
||||||
|
<div className="glass rounded-lg p-3 border border-white/20">
|
||||||
|
<p className="text-sm text-gray-800 line-clamp-2">
|
||||||
|
{post.caption?.slice(0, 100)}...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</motion.div>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user