Trying the docker buildx using git repository.
Static mostly done. good progress on store
This commit is contained in:
@ -16,7 +16,7 @@ export default function AboutUsPage() {
|
||||
<div className='w-full text-s-headline font-normal text-center font-montera'>
|
||||
Welcome to the World of Mozimo Magic
|
||||
</div>
|
||||
<div className='w-full text-s-normal text-justify p-12'>
|
||||
<div className='w-full text-s-normal text-justify px-12 pb-12'>
|
||||
Indulge in the Luxurious. Immerse in the Captivating. Savor the Fresh. At Mozimo, we curate a chocolate
|
||||
experience that transports you to a world of opulence, captivates your senses with mesmerizing aromas and
|
||||
visuals, and delights your taste buds with the vibrant flavors of freshly crafted chocolates. Join us on a
|
||||
@ -40,9 +40,10 @@ export default function AboutUsPage() {
|
||||
</div>
|
||||
{/* Right Column - Text with Header */}
|
||||
<div className='w-full md:w-1/2'>
|
||||
<div className='m-8 space-y-10'>
|
||||
<p className='text-s-title font-normal text-justify font-montera'>Our Founders Priyanka and Amritanshu</p>
|
||||
<p className='text-s-normal text-justify'>
|
||||
<div className='m-8'>
|
||||
<p className='text-s-title font-normal text-justify font-montera'>Our Founders</p>
|
||||
<p className='text-s-title font-normal text-justify font-montera'>Priyanka and Amritanshu</p>
|
||||
<p className='text-s-normal text-justify mt-10'>
|
||||
are the proud founders of Mozimo, a bean-to-bar chocolate shop that celebrates the rich and distinctive
|
||||
flavors of single origin cocoa beans. Their journey with Mozimo has been a passionate pursuit of creating
|
||||
exceptional chocolate that tantalizes the taste buds and tells the unique story of each cocoa bean's
|
||||
@ -53,10 +54,10 @@ export default function AboutUsPage() {
|
||||
</section>
|
||||
<section className='flex flex-col md:flex-row items-center'>
|
||||
<div className='w-full md:w-1/2'>
|
||||
<div className='m-8 space-y-10'>
|
||||
<div className='m-8'>
|
||||
<h2 className='text-s-title font-normal text-justify font-montera'>Capturing the essence of</h2>
|
||||
<h3 className='text-s-headline font-normal text-justify font-samantha'>Italian Chocolate</h3>
|
||||
<p className='text-s-normal text-justify'>
|
||||
<p className='text-s-normal text-justify mt-10'>
|
||||
With over 15 years of hospitality experience, these avid travelers scoured the globe for the finest cocoa
|
||||
beans and techniques. Deep in remote cocoa farms, they cultivated relationships with farmers committed to
|
||||
sustainability. Carefully selecting beans, they honor each harvest's stories. In their cozy workshop,
|
||||
|
||||
43
src/app/(static)/festival/actions.tsx
Normal file
43
src/app/(static)/festival/actions.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
'use server';
|
||||
|
||||
export type ContactFormState = {
|
||||
name: string;
|
||||
phone: string;
|
||||
email: string;
|
||||
message: string;
|
||||
status: string;
|
||||
};
|
||||
|
||||
export async function saveContactForm(state: ContactFormState, formData: FormData): Promise<ContactFormState> {
|
||||
const url =
|
||||
'https://script.google.com/macros/s/AKfycby7wfGy1A23Ja5p3NCKd1qFFDGy1Prd9ZfMdz7aBQKHV3WTh0eWWP-3dRoUcE0lVLCIKg/exec';
|
||||
try {
|
||||
const payload = {
|
||||
name: formData.get('name') as string,
|
||||
phone: formData.get('phone') as string,
|
||||
email: formData.get('email') as string,
|
||||
message: formData.get('message') as string,
|
||||
};
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
|
||||
await response.body;
|
||||
return {
|
||||
...payload,
|
||||
// ...await response.json(),
|
||||
status: 'success',
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error sending form data:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
7
src/app/(static)/festival/contact-form.module.css
Normal file
7
src/app/(static)/festival/contact-form.module.css
Normal file
@ -0,0 +1,7 @@
|
||||
.formInput {
|
||||
@apply mt-1 w-full p-2 border border-[hsl(358,39%,32%)];
|
||||
}
|
||||
|
||||
.formButton {
|
||||
@apply w-full py-2 px-4 bg-[#703133] text-white font-semibold shadow focus:outline-none;
|
||||
}
|
||||
40
src/app/(static)/festival/contact-form.tsx
Normal file
40
src/app/(static)/festival/contact-form.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
'use client';
|
||||
import { useRef } from 'react';
|
||||
import { useFormState, useFormStatus } from 'react-dom';
|
||||
|
||||
import { saveContactForm, ContactFormState } from './actions';
|
||||
import styles from './contact-form.module.css';
|
||||
|
||||
export function ContactForm() {
|
||||
const formRef = useRef<HTMLFormElement>(null);
|
||||
const init: ContactFormState = {
|
||||
name: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
message: '',
|
||||
status: '',
|
||||
};
|
||||
const [state, action] = useFormState<ContactFormState, FormData>(saveContactForm, init);
|
||||
|
||||
if (state.status === 'success') {
|
||||
formRef.current?.reset();
|
||||
}
|
||||
return (
|
||||
<form ref={formRef} action={action} className='space-y-4 mx-8'>
|
||||
<input type='text' name='name' className={styles.formInput} placeholder='Your Name' required />
|
||||
<input type='text' name='phone' className={styles.formInput} placeholder='Phone number' required />
|
||||
<input type='email' name='email' className={styles.formInput} placeholder='E-Mail Address' required />
|
||||
<textarea name='message' className={styles.formInput} rows={4} placeholder='Your message' required></textarea>
|
||||
<SubmitButton state={state.status} />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
export function SubmitButton({ state }: { state: string }) {
|
||||
const status = useFormStatus();
|
||||
return (
|
||||
<button type='submit' className={styles.formButton}>
|
||||
{status.pending ? 'Submitting' : state !== 'success' ? 'Submit' : 'Submitted'}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@ -7,7 +7,10 @@ import redBarkBoxPic from '/public/images/diwali/06-red-bark-box.jpg';
|
||||
|
||||
import { AnimatedImage } from '@/components/animated-image';
|
||||
import { AnimatedText } from '@/components/animated-text';
|
||||
// import blueSpreadPic from '/public/images/diwali/07-blue-spread.jpg';
|
||||
|
||||
import blueSpreadPic from '/public/images/diwali/07-blue-spread.jpg';
|
||||
|
||||
import { ContactForm } from './contact-form';
|
||||
|
||||
export default function FestivalPage() {
|
||||
return (
|
||||
@ -17,7 +20,7 @@ export default function FestivalPage() {
|
||||
<AnimatedImage
|
||||
src={bannerPic}
|
||||
alt='Praline'
|
||||
className='w-full h-full object-cover object-center'
|
||||
className='w-full h-full object-cover object-[-8rem]'
|
||||
sizes='100vw'
|
||||
/>
|
||||
<a
|
||||
@ -32,7 +35,7 @@ export default function FestivalPage() {
|
||||
<AnimatedText finishClass='delay-300'>
|
||||
<h2 className='text-s-headline font-normal text-justify font-samantha p-12'>Sweet Moments with Mozimo</h2>
|
||||
</AnimatedText>
|
||||
<AnimatedText startClass='translate-y-8' finishClass='translate-y-0'>
|
||||
<AnimatedText startClass='translate-y-8' finishClass='translate-y-0 mx-8'>
|
||||
<div className='w-full text-s-normal text-justify pb-12'>
|
||||
“Transforming cacao beans sourced straight from the pod into rich, velvety smooth chocolate is pure magic.
|
||||
This is why we take great pride in being called the 'Alchemists of the Chocolate World'.”
|
||||
@ -110,7 +113,7 @@ export default function FestivalPage() {
|
||||
</div>
|
||||
</AnimatedText>
|
||||
<AnimatedText startClass='translate-y-8' finishClass='translate-y-0'>
|
||||
<div className='text-s-normal text-justify pb-12'>
|
||||
<div className='text-s-normal text-justify pb-12 mx-8'>
|
||||
Every creation of Mozimo's chocolate is a specimen of craftsmanship of the highest quality by the
|
||||
finest chocolatiers.
|
||||
</div>
|
||||
@ -142,20 +145,31 @@ export default function FestivalPage() {
|
||||
<p className='text-s-headline text-center font-montera p-12'>Experience the art of gifting this Diwali</p>
|
||||
</AnimatedText>
|
||||
<AnimatedText startClass='translate-y-8' finishClass='translate-y-0'>
|
||||
<p className='text-s-normal text-center pb-12'>
|
||||
<p className='text-s-normal text-justify md:text-center mx-8 pb-12'>
|
||||
It’s time to celebrate the joy of togetherness, love, and the luxury of Mozimo’s chocolates. This Diwali,
|
||||
let’s embrace the sweetness of life with our exquisite single-origin handcrafted chocolates, crafted to
|
||||
elevate your festive moments.
|
||||
</p>
|
||||
</AnimatedText>
|
||||
<AnimatedText startClass='translate-y-8' finishClass='translate-y-0'>
|
||||
<p className='text-s-normal text-center pb-12'>
|
||||
<p className='text-s-normal text-justify mx-8 md:text-center pb-12'>
|
||||
Let our handcrafted chocolates be a part of your Diwali rituals. Whether you’re enjoying them during family
|
||||
gatherings, using them as a centerpiece for your celebrations, or gifting them to friends or colleagues,
|
||||
they are sure to bring warmth and sweetness to every moment.
|
||||
</p>
|
||||
</AnimatedText>
|
||||
</section>
|
||||
<section className='flex flex-col md:flex-row items-center pb-12'>
|
||||
<div className='flex'>
|
||||
<AnimatedImage src={blueSpreadPic} alt='Boxes and spreads' className='w-full h-auto' sizes='100vw' />
|
||||
</div>
|
||||
<div className='flex flex-col'>
|
||||
<p className='text-s-normal text-center pb-12'>
|
||||
For queries and bulk orders, please fill the following Enquiry Form:
|
||||
</p>
|
||||
<ContactForm />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -4,8 +4,15 @@ import { ReactNode } from 'react';
|
||||
|
||||
import { Footer } from '@/components/footer';
|
||||
import { Navbar } from '@/components/navbar';
|
||||
import { CartProvider } from '@/providers/cart';
|
||||
import { CustomerProvider } from '@/providers/customer';
|
||||
import { RegionProvider } from '@/providers/region';
|
||||
|
||||
export default function RootLayout({ children }: { children: ReactNode }) {
|
||||
interface RootLayoutProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export default function RootLayout({ children }: RootLayoutProps) {
|
||||
return (
|
||||
<html lang='en'>
|
||||
<head>
|
||||
@ -13,7 +20,11 @@ export default function RootLayout({ children }: { children: ReactNode }) {
|
||||
</head>
|
||||
<body>
|
||||
<Navbar />
|
||||
<main>{children}</main>
|
||||
<RegionProvider>
|
||||
<CustomerProvider>
|
||||
<CartProvider>{children}</CartProvider>
|
||||
</CustomerProvider>
|
||||
</RegionProvider>
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -91,7 +91,7 @@ export default function HomePage() {
|
||||
<InstagramFeed />
|
||||
</section>
|
||||
<section className='flex flex-col items-center bg-white py-12 px-4 sm:px-6 lg:px-8'>
|
||||
<div className='w-full text-s-headline font-normal font-montera text-center py-12 px-4 sm:px-6 lg:px-8'>
|
||||
<div className='w-full text-s-headline font-normal font-montera text-center pt-12 px-4 sm:px-6 lg:px-8'>
|
||||
In the Spotlight
|
||||
</div>
|
||||
<Spotlight />
|
||||
|
||||
@ -15,6 +15,9 @@ interface RootLayoutProps {
|
||||
export default function RootLayout({ children }: RootLayoutProps) {
|
||||
return (
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1' />
|
||||
</head>
|
||||
<body>
|
||||
<Navbar />
|
||||
<RegionProvider>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { HttpTypes } from '@medusajs/types';
|
||||
import { ChevronLeft, ChevronRight, ShoppingCart, Star } from 'lucide-react';
|
||||
import { ShoppingCart, Star } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
|
||||
@ -18,7 +18,6 @@ interface ProductDetailsProps {
|
||||
|
||||
const ProductDetails: FC<ProductDetailsProps> = ({ handle }) => {
|
||||
const [quantity, setQuantity] = useState(1);
|
||||
const [currentImage, setCurrentImage] = useState(0);
|
||||
const [product, setProduct] = useState<HttpTypes.StoreProduct | null>();
|
||||
const [selectedVariant, setSelectedVariant] = useState<HttpTypes.StoreProductVariant | null>(null);
|
||||
|
||||
@ -28,18 +27,6 @@ const ProductDetails: FC<ProductDetailsProps> = ({ handle }) => {
|
||||
const { region } = useRegion();
|
||||
const { cart, addToCart } = useCart();
|
||||
|
||||
const nextImage = () => {
|
||||
if (product && product.images) {
|
||||
setCurrentImage((currentImage + 1) % product.images.length);
|
||||
}
|
||||
};
|
||||
|
||||
const prevImage = () => {
|
||||
if (product && product.images) {
|
||||
setCurrentImage((currentImage - 1 + product.images.length) % product.images.length);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!region || !cart) {
|
||||
return;
|
||||
@ -92,44 +79,30 @@ const ProductDetails: FC<ProductDetailsProps> = ({ handle }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='container mx-auto px-4 py-8 pt-28'>
|
||||
<div className='grid md:grid-cols-2 gap-8'>
|
||||
<div className='relative'>
|
||||
<Image
|
||||
width={200}
|
||||
height={192}
|
||||
src={product.images?.[currentImage].url as string}
|
||||
alt={`${product.title} image ${currentImage + 1}`}
|
||||
className='w-full h-auto rounded-lg shadow-lg'
|
||||
/>
|
||||
<Button
|
||||
variant='outline'
|
||||
size='icon'
|
||||
className='absolute left-2 top-1/2 transform -translate-y-1/2'
|
||||
onClick={prevImage}
|
||||
>
|
||||
<ChevronLeft className='h-4 w-4' />
|
||||
<span className='sr-only'>Previous image</span>
|
||||
</Button>
|
||||
<Button
|
||||
variant='outline'
|
||||
size='icon'
|
||||
className='absolute right-2 top-1/2 transform -translate-y-1/2'
|
||||
onClick={nextImage}
|
||||
>
|
||||
<ChevronRight className='h-4 w-4' />
|
||||
<span className='sr-only'>Next image</span>
|
||||
</Button>
|
||||
<div className='flex justify-center mt-4 space-x-2'>
|
||||
<div className='px-4 py-8 pt-28'>
|
||||
<div className='grid md:grid-cols-2 gap-8 overflow-visible'>
|
||||
<div>
|
||||
{product.images?.map((image, index) => (
|
||||
<Image
|
||||
key={index}
|
||||
width={200}
|
||||
height={192}
|
||||
src={image.url as string}
|
||||
alt={`${product.title} image ${index + 1}`}
|
||||
className='w-full h-auto'
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* <div className='flex justify-center mt-4 space-x-2'>
|
||||
{product.images?.map((_, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`w-3 h-3 rounded-full ${index === currentImage ? 'bg-primary' : 'bg-gray-300'}`}
|
||||
className={`w-3 h-3 rounded-full ${index === 1 ? 'bg-primary' : 'bg-gray-300'}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
<div>
|
||||
<div className='sticky top-20 self-start'>
|
||||
<h1 className='text-3xl font-bold mb-4'>{product.title}</h1>
|
||||
<div className='flex items-center mb-4'>
|
||||
<div className='flex text-yellow-400'>
|
||||
@ -154,7 +127,7 @@ const ProductDetails: FC<ProductDetailsProps> = ({ handle }) => {
|
||||
<div key={variant.id} className='flex items-center space-x-2'>
|
||||
<RadioGroupItem value={variant.id} id={variant.id} />
|
||||
<Label htmlFor={variant.id}>
|
||||
{variant.title} - ${variant.calculated_price?.calculated_amount?.toFixed(2)}
|
||||
{variant.title} - ₹{variant.calculated_price?.calculated_amount?.toFixed(2)}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
@ -173,18 +146,16 @@ const ProductDetails: FC<ProductDetailsProps> = ({ handle }) => {
|
||||
<Button className='w-full md:w-auto' onClick={() => addToCart(selectedVariant?.id as string, quantity)}>
|
||||
<ShoppingCart className='mr-2 h-4 w-4' /> Add to Cart
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='mt-12'>
|
||||
<h2 className='text-2xl font-bold mb-4'>Product Details</h2>
|
||||
<ul className='list-disc pl-5 space-y-2 text-gray-600'>
|
||||
<li>Single-origin cocoa beans from Ecuador</li>
|
||||
<li>Fair trade certified</li>
|
||||
<li>No artificial flavors or preservatives</li>
|
||||
<li>100g (3.5oz) bar</li>
|
||||
<li>Available in different cocoa percentages</li>
|
||||
</ul>
|
||||
<h2 className='text-2xl font-bold mb-4'>Product Details</h2>
|
||||
<ul className='list-disc pl-5 space-y-2 text-gray-600'>
|
||||
<li>Single-origin cocoa beans from Ecuador</li>
|
||||
<li>Fair trade certified</li>
|
||||
<li>No artificial flavors or preservatives</li>
|
||||
<li>100g (3.5oz) bar</li>
|
||||
<li>Available in different cocoa percentages</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='mt-12'>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { HttpTypes } from '@medusajs/types';
|
||||
import Image from 'next/image';
|
||||
// import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
@ -36,22 +36,36 @@ export default function ProductsPage() {
|
||||
|
||||
return (
|
||||
<div className='container mx-auto py-12 pt-28'>
|
||||
<h1 className='text-3xl font-bold mb-8'>Handbags Collection</h1>
|
||||
<div className='grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-8'>
|
||||
{products?.map((product) => (
|
||||
<Link key={product.id} href={`/products/${product.handle}`}>
|
||||
<div className='border border-gray-200 p-4 rounded-lg shadow-lg'>
|
||||
<Image
|
||||
{/* Products Grid */}
|
||||
<div
|
||||
className='grid gap-8 mb-8'
|
||||
style={{
|
||||
gridTemplateColumns: 'repeat(auto-fit, clamp(200px, 20vw, 300px))',
|
||||
marginLeft: 'clamp(10px, 5vw, 30px)',
|
||||
marginRight: 'clamp(10px, 5vw, 30px)',
|
||||
}}
|
||||
>
|
||||
{products.map((product) => (
|
||||
<Link
|
||||
key={product.id}
|
||||
className='p-0 flex flex-col h-full cursor-pointer'
|
||||
href={`/products/${product.handle}`}
|
||||
>
|
||||
<div className='group relative'>
|
||||
<img
|
||||
src={product.images?.[0].url as string}
|
||||
alt={product.title as string}
|
||||
width={300}
|
||||
height={300}
|
||||
className='w-full h-auto object-cover rounded-md'
|
||||
className='w-full h-auto flex-grow group-hover:opacity-80 transition-opacity duration-1000 group-hover:rounded-lg group-hover:shadow-lg'
|
||||
/>
|
||||
<h2 className='mt-4 text-lg font-semibold'>{product.title}</h2>
|
||||
<p className='mt-2 text-gray-600'>{product.description}</p>
|
||||
<p className='mt-2 text-lg font-bold text-gray-900'>
|
||||
{/* ${product.variants?[0]?.calculated_price / 100} */}
|
||||
<button className='bg-black text-white px-4 py-2 rounded hover:bg-gray-800 transition-colors duration-300 absolute bottom-4 left-1/2 transform -translate-x-1/2 opacity-0 group-hover:opacity-100'>
|
||||
Add to Cart
|
||||
</button>
|
||||
</div>
|
||||
<div className='p-4 text-left flex-shrink-0'>
|
||||
<h3 className='text-lg font-bold mb-2'>{product.title as string}</h3>
|
||||
<p className='text-sm text-gray-600 mb-1'>Category: {product.title as string}</p>
|
||||
<p className='text-sm text-gray-800 font-semibold mb-4'>
|
||||
Price: ₹{product.variants?.[0].calculated_price?.calculated_amount?.toFixed(2)}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@ -3,16 +3,26 @@
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
--background: 20, 18%, 97%;
|
||||
--foreground: 358, 39%, 32%;
|
||||
--normal-font: 1.25rem;
|
||||
--title-font: 3rem;
|
||||
--headline-font: 5rem;
|
||||
--items-font: 6.25rem;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: 20, 18%, 97%;
|
||||
--foreground: 358, 39%, 32%;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: var(--background);
|
||||
color: hsl(var(--foreground));
|
||||
background-color: hsl(var(--background));
|
||||
font-family: Renner, sans-serif;
|
||||
font-weight: 300;
|
||||
font-size: var(--normal-font);
|
||||
@ -30,6 +40,10 @@ body {
|
||||
font-size: var(--headline-font);
|
||||
}
|
||||
|
||||
.font-samantha {
|
||||
font-size: calc(100% + 3rem);
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.text-balance {
|
||||
text-wrap: balance;
|
||||
@ -120,7 +134,7 @@ animation-range-end: contain; */
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
/* @layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 240 10% 3.9%;
|
||||
@ -183,7 +197,7 @@ animation-range-end: contain; */
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
.pillLink {
|
||||
@apply bg-white text-black rounded-full px-6 py-2 text-lg font-sans shadow-md transition duration-300 ease-in-out;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
.productImage {
|
||||
width: 8rem; /* Set the width of the image */
|
||||
width: 100%; /* Set the width of the image */
|
||||
height: auto;
|
||||
aspect-ratio: 1;
|
||||
border-radius: 50%; /* Make the image circular */
|
||||
object-fit: cover; /* Ensure the image covers the container */
|
||||
|
||||
@ -20,8 +20,8 @@ export function ChocolateCategories() {
|
||||
const finishClass = 'translate-x-0 delay-300';
|
||||
|
||||
return (
|
||||
<section className='flex flex-col md:flex-row bg-white py-12 px-4 sm:px-6 lg:px-8'>
|
||||
<ul className='w-full md:w-1/2 bg-white h-auto m-8 space-y-10 text-[#5a352a] text-left'>
|
||||
<section className='flex flex-col md:flex-row bg-white py-12 px-4 sm:px-6 lg:px-8 h-[90vh]'>
|
||||
<ul className='w-full md:w-1/2 bg-white h-auto m-8 text-[#5a352a] text-left'>
|
||||
{categories.map((category) => (
|
||||
<AnimatedLi
|
||||
key={category.name}
|
||||
@ -30,7 +30,7 @@ export function ChocolateCategories() {
|
||||
startClass={startClass}
|
||||
finishClass={finishClass}
|
||||
>
|
||||
<Image className={styles.productImage} alt={category.name} src={category.image} width={100} height={100} />
|
||||
<img className={styles.productImage} alt={category.name} src={category.image} />
|
||||
<span>{category.name}</span>
|
||||
</AnimatedLi>
|
||||
))}
|
||||
|
||||
21
src/components/footer.module.css
Normal file
21
src/components/footer.module.css
Normal file
@ -0,0 +1,21 @@
|
||||
.grid {
|
||||
display: grid;
|
||||
gap: 2rem /* 32px */;
|
||||
grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
|
||||
|
||||
padding-top: 3rem /* 48px */;
|
||||
padding-bottom: 3rem /* 48px */;
|
||||
padding-left: 1rem /* 16px */;
|
||||
padding-right: 1rem /* 16px */;
|
||||
|
||||
|
||||
border-top-width: 2px;
|
||||
border-color: hsl(0, 0%, 0%);
|
||||
background-color: hsl(20, 18%, 97%);
|
||||
}
|
||||
|
||||
@media screen and (width >= 768px) {
|
||||
.productImage {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@ -2,19 +2,21 @@ import Image from 'next/image';
|
||||
import { FaFacebook, FaInstagram, FaLinkedin, FaPhoneAlt, FaYoutube } from 'react-icons/fa';
|
||||
import { FaMapLocationDot } from 'react-icons/fa6';
|
||||
|
||||
import styles from './footer.module.css';
|
||||
|
||||
import logoPic from '/public/images/logo-puce-red.svg';
|
||||
|
||||
export function Footer() {
|
||||
return (
|
||||
<footer className='bg-[#f8f6f5] flex flex-col md:flex-row py-12 border-t-2 border-black max-w-7xl mx-auto gap-8 px-4'>
|
||||
<footer className={styles.grid}>
|
||||
{/* First Column: Logo and Description */}
|
||||
<div className='space-y-4 flex flex-col basis-1/4 flex-shrink'>
|
||||
<div className='space-y-4 flex flex-col'>
|
||||
<Image src={logoPic} alt='Mozimo Logo' width={100} height={100} className='h-full logo' />
|
||||
<p className='text-sm'>India's Premier European style bean-to-bar chocolate experience.</p>
|
||||
</div>
|
||||
|
||||
{/* Second Column: Contact Information */}
|
||||
<div className='space-y-4 flex flex-col basis-1/4'>
|
||||
<div className='space-y-4 flex flex-col'>
|
||||
<h3 className='font-semibold'>Get in touch</h3>
|
||||
<p className='text-sm flex items-center'>
|
||||
<FaPhoneAlt />
|
||||
@ -27,7 +29,7 @@ export function Footer() {
|
||||
</div>
|
||||
|
||||
{/* Third Column: Links */}
|
||||
<div className='space-y-4 flex flex-col basis-1/4'>
|
||||
<div className='space-y-4 flex flex-col'>
|
||||
<h3 className='font-semibold'>Know more</h3>
|
||||
<ul className='space-y-2'>
|
||||
<li>
|
||||
@ -54,7 +56,7 @@ export function Footer() {
|
||||
</div>
|
||||
|
||||
{/* Additional Links */}
|
||||
<div className='space-y-4 flex flex-col basis-1/4'>
|
||||
<div className='space-y-4 flex flex-col'>
|
||||
<ul className='space-y-2'>
|
||||
<li>
|
||||
<a href='/faq' className='text-sm text-brown-600 hover:underline'>
|
||||
|
||||
39
src/components/instagram-client.tsx
Normal file
39
src/components/instagram-client.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
'use client';
|
||||
import Image from 'next/image';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { fetchInstagramPosts, InstagramPost } from '@/lib/instagram';
|
||||
|
||||
export function InstagramFeed() {
|
||||
const [posts, setPosts] = useState<InstagramPost[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
async function getInstagramData() {
|
||||
const data = await fetchInstagramPosts();
|
||||
setPosts(data);
|
||||
}
|
||||
|
||||
getInstagramData();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className='grid grid-cols-1 md:grid-cols-5 gap-8'>
|
||||
{posts.map((post) => (
|
||||
<div key={post.id} className='flex flex-col items-center'>
|
||||
<a href={post.permalink} target='_blank' rel='noopener noreferrer'>
|
||||
<Image
|
||||
src={post.media_url}
|
||||
alt={post.caption}
|
||||
className='rounded-lg shadow-lg w-full h-auto'
|
||||
fill
|
||||
// sizes="100vw"
|
||||
style={{
|
||||
objectFit: 'cover',
|
||||
}}
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,31 +1,13 @@
|
||||
'use client';
|
||||
import Image from 'next/image';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { fetchInstagramPosts, InstagramPost } from '@/lib/instagram';
|
||||
|
||||
export function InstagramFeed() {
|
||||
const [posts, setPosts] = useState<InstagramPost[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
async function getInstagramData() {
|
||||
const data = await fetchInstagramPosts();
|
||||
setPosts(data);
|
||||
}
|
||||
|
||||
getInstagramData();
|
||||
}, []);
|
||||
import { fetchInstagramPosts } from '@/lib/instagram';
|
||||
|
||||
export async function InstagramFeed() {
|
||||
const posts = await fetchInstagramPosts();
|
||||
return (
|
||||
<div className='grid grid-cols-1 md:grid-cols-5 gap-8'>
|
||||
{posts.map((post) => (
|
||||
{posts?.map((post) => (
|
||||
<div key={post.id} className='flex flex-col items-center'>
|
||||
<a href={post.permalink} target='_blank' rel='noopener noreferrer'>
|
||||
<Image
|
||||
src={post.media_url}
|
||||
alt={post.caption}
|
||||
className='rounded-lg shadow-lg'
|
||||
/>
|
||||
<img src={post.media_url} alt={post.caption} className='rounded-lg shadow-lg w-full h-auto object-cover' />
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@ -9,8 +9,9 @@
|
||||
left: 0;
|
||||
padding: 2rem;
|
||||
z-index: 1000;
|
||||
background: hsl(0 0% 100% / .2);
|
||||
backdrop-filter: blur(1rem);
|
||||
background: hsl(0 0% 100% / 1);
|
||||
/* background: hsl(0 0% 100% / .2);
|
||||
backdrop-filter: blur(1rem); */
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
@ -69,9 +69,12 @@ export function Navbar() {
|
||||
<nav data-visible={isVisible} className={navClasses}>
|
||||
{/* Left side */}
|
||||
<div>
|
||||
<Link href='/about-us' className='font-medium hover:underline'>
|
||||
<Link href='/about-us' className='font-light hover:underline'>
|
||||
About Us
|
||||
</Link>
|
||||
<Link href='/products' className='font-light hover:underline'>
|
||||
Shop
|
||||
</Link>
|
||||
</div>
|
||||
{/* Middle */}
|
||||
<div className='flex-shrink'>
|
||||
@ -88,14 +91,14 @@ export function Navbar() {
|
||||
</div>
|
||||
{/* Right side */}
|
||||
<div className=''>
|
||||
<button aria-label='Search'>
|
||||
<FiSearch size={20} />
|
||||
<button aria-label='Search' className='rounded-full hover:shadow-md'>
|
||||
<FiSearch size={20} className='m-2.5' />
|
||||
</button>
|
||||
<button aria-label='Profile'>
|
||||
<FiUser size={20} />
|
||||
<button aria-label='Profile' className='rounded-full hover:shadow-md'>
|
||||
<FiUser size={20} className='m-2.5' />
|
||||
</button>
|
||||
<a aria-label='Shopping Cart' href='/cart'>
|
||||
<HiShoppingBag size={20} />
|
||||
<a aria-label='Shopping Cart' href='/cart' className='rounded-full hover:shadow-md'>
|
||||
<HiShoppingBag size={20} className='m-2.5' />
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import Image from 'next/image';
|
||||
// import Image from 'next/image';
|
||||
|
||||
import styles from './our-collection.module.css';
|
||||
|
||||
@ -23,13 +23,7 @@ export function Collections() {
|
||||
{collections.map((collection, index) => (
|
||||
<div key={index} className='basis-1/3'>
|
||||
<div className='overflow-hidden'>
|
||||
<Image
|
||||
src={collection.image}
|
||||
alt={collection.title}
|
||||
width={500}
|
||||
height={300}
|
||||
className={styles.ourCollection}
|
||||
/>
|
||||
<img src={collection.image} alt={collection.title} className={styles.ourCollection} />
|
||||
</div>
|
||||
<div className='p-4'>
|
||||
<h3 className='text-center font-light'>{collection.title}</h3>
|
||||
|
||||
@ -1,20 +1,15 @@
|
||||
// components/Spotlight.tsx
|
||||
import Image from 'next/image';
|
||||
|
||||
const logos = [
|
||||
{ src: '/images/logo.png', alt: 'TOI' }, // Replace with actual logo path
|
||||
{ src: '/images/logo.png', alt: 'The Tribune' }, // Replace with actual logo path
|
||||
{ src: '/images/logo.png', alt: 'ET' }, // Replace with actual logo path
|
||||
{ src: '/images/logo.png', alt: 'The Hindu' }, // Replace with actual logo path
|
||||
{ src: '/images/spotlight/toi.png', alt: 'TOI' },
|
||||
{ src: '/images/spotlight/tribune.png', alt: 'The Tribune' },
|
||||
{ src: '/images/spotlight/et.png', alt: 'ET' },
|
||||
{ src: '/images/spotlight/hindu.png', alt: 'The Hindu' },
|
||||
];
|
||||
// { src: '/images/logos/toi-logo.png', alt: 'TOI' }, // Replace with actual logo path
|
||||
// { src: '/images/logos/tribune-logo.png', alt: 'The Tribune' }, // Replace with actual logo path
|
||||
// { src: '/images/logos/et-logo.png', alt: 'ET' }, // Replace with actual logo path
|
||||
// { src: '/images/logos/hindu-logo.png', alt: 'The Hindu' }, // Replace with actual logo path
|
||||
|
||||
export function Spotlight() {
|
||||
return (
|
||||
<div className='flex flex-row justify-center items-center space-x-8 py-16'>
|
||||
<div className='flex flex-row justify-center items-center space-x-8 pb-16'>
|
||||
{logos.map((logo, index) => (
|
||||
<div key={index} className='flex flex-col items-center'>
|
||||
<div className='w-32 h-32 bg-white rounded-full shadow-lg flex items-center justify-center'>
|
||||
@ -25,18 +20,3 @@ export function Spotlight() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// return (
|
||||
// <div className="flex flex-col items-center py-16">
|
||||
// <h2 className="text-3xl font-semibold mb-8">In the Spotlight</h2>
|
||||
// <div className="flex justify-center space-x-8">
|
||||
// {logos.map((logo, index) => (
|
||||
// <div key={index} className="flex flex-col items-center">
|
||||
// <div className="w-32 h-32 bg-white rounded-full shadow-lg flex items-center justify-center">
|
||||
// <Image src={logo.src} alt={logo.alt} width={80} height={80} className="object-contain" />
|
||||
// </div>
|
||||
// </div>
|
||||
// ))}
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
|
||||
@ -8,6 +8,7 @@ import { cn } from '@/lib/utils';
|
||||
const Separator = React.forwardRef<
|
||||
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
|
||||
// eslint-disable-next-line react/prop-types
|
||||
>(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => (
|
||||
<SeparatorPrimitive.Root
|
||||
ref={ref}
|
||||
|
||||
23
src/middleware.ts.disable
Normal file
23
src/middleware.ts.disable
Normal file
@ -0,0 +1,23 @@
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { NextRequest, NextResponse } from "next/server"
|
||||
|
||||
const BACKEND_URL = process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL
|
||||
const PUBLISHABLE_API_KEY = process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY
|
||||
|
||||
const regionMapCache = {
|
||||
regionMap: new Map<string, HttpTypes.StoreRegion>(),
|
||||
regionMapUpdated: Date.now(),
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Middleware to handle region selection and onboarding status.
|
||||
*/
|
||||
export async function middleware(request: NextRequest) {
|
||||
|
||||
|
||||
|
||||
return NextResponse.next()
|
||||
|
||||
}
|
||||
@ -172,7 +172,7 @@ export const CustomerProvider = ({ children }: CustomerProviderProps) => {
|
||||
};
|
||||
const getCustomer = async () => {
|
||||
try {
|
||||
if (!jwt || customer) {
|
||||
if (!jwt) {
|
||||
return;
|
||||
}
|
||||
// get customer
|
||||
|
||||
Reference in New Issue
Block a user