added coming soon page #1

Merged
mihir merged 1 commits from feature/coming_soon into main 2025-09-11 17:00:23 +05:30
11 changed files with 5819 additions and 35 deletions
Showing only changes of commit 185b3d0c0a - Show all commits

58
.drone.yml Normal file
View File

@ -0,0 +1,58 @@
kind: pipeline
name: Build Image
clone:
depth: 1
steps:
- name: Lint Check
image: node:22-alpine
commands:
# Enable Corepack and prepare Yarn 4
- corepack enable
- corepack prepare yarn@4.9.2 --activate
# Install dependencies with Yarn 4
- yarn install --immutable
- yarn lint
- name: Build Docker Image
image: plugins/docker
settings:
build_args: 'API_BASE_URL=https://TheKalawati.com/api'
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: git.TheKalawati.com/midastix/TheKalawati
registry: git.TheKalawati.com
when:
branch:
- main
event:
- push
- name: Deploy image
image: appleboy/drone-ssh
settings:
host: midastix.com
username: TheKalawati
key:
from_secret: server_ssh_pkey
port: 22
command_timeout: 3m
script:
- echo "Deploying image"
- sudo /opt/deployable/Navigo_website/docker/deploy.sh
- echo "Completed Deployment"
when:
branch:
- main
event:
- push
# trigger:
# branch:
# - main
# - feature/env_api_url
# event:
# - push

BIN
.yarn/install-state.gz Normal file

Binary file not shown.

1
.yarnrc.yml Normal file
View File

@ -0,0 +1 @@
nodeLinker: node-modules

47
Dockerfile Normal file
View File

@ -0,0 +1,47 @@
# ------------------------
# Build stage
# ------------------------
FROM node:22-bullseye AS builder
ARG API_BASE_URL="https://navigolabs.com/api"
# Enable Corepack and Yarn 4
RUN corepack enable && corepack prepare yarn@4.9.2 --activate
WORKDIR /app
# Copy Yarn 4 files
COPY package.json yarn.lock .yarnrc.yml ./
COPY .yarn .yarn
# Install dependencies (immutable to match lockfile)
RUN yarn install --immutable
# Copy all source files
COPY . .
# Pass API URL to Vite
ENV VITE_API_BASE_URL=$API_BASE_URL
# Build the app
RUN yarn build
# ------------------------
# Production stage
# ------------------------
FROM node:22-alpine AS production
WORKDIR /app
# Copy built files from builder stage
COPY --from=builder /app/dist ./dist
# Install a lightweight static server
RUN npm install -g serve@14
# Expose port (optional but recommended)
EXPOSE 3000
# Start the static server
CMD ["serve", "-s", "dist", "-l", "3000"]

View File

@ -10,8 +10,13 @@
"preview": "vite preview"
},
"dependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@mui/icons-material": "^7.3.2",
"@mui/material": "^7.3.2",
"react": "^19.1.1",
"react-dom": "^19.1.1"
"react-dom": "^19.1.1",
"react-intersection-observer": "^9.16.0"
},
"devDependencies": {
"@eslint/js": "^9.33.0",

View File

@ -1,7 +1,7 @@
#root {
max-width: 1280px;
width: 100vw;
margin: 0 auto;
padding: 2rem;
/* padding: 2rem; */
text-align: center;
}
@ -11,9 +11,11 @@
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
@ -22,6 +24,7 @@
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
@ -39,4 +42,4 @@
.read-the-docs {
color: #888;
}
}

View File

@ -1,35 +1,18 @@
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
// import reactLogo from './assets/react.svg'
// import viteLogo from '/vite.svg'
import './App.css'
// import VintageComingSoon from './comingsoon/comingsoon'
import VintageComingSoonPage from './comingsoon/comingsoon'
function App() {
const [count, setCount] = useState(0)
return (
<>
<div>
<a href="https://vite.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
)
<VintageComingSoonPage />
);
}
export default App

View File

@ -0,0 +1,891 @@
import React, { useState, useEffect, useRef } from 'react';
import { Box, Typography, Button, Container, IconButton, Grid } from '@mui/material';
import { useInView } from 'react-intersection-observer';
import InstagramIcon from '@mui/icons-material/Instagram';
import FacebookIcon from '@mui/icons-material/Facebook';
import TwitterIcon from '@mui/icons-material/Twitter';
import EmailIcon from '@mui/icons-material/Email';
import { keyframes } from '@emotion/react';
import { styled } from '@mui/system';
// Color palette inspired by Indian heritage
const colors = {
paper: '#F5F5EF', // Aged paper
ink: '#1A2526', // Deep charcoal
accent: '#D4A017', // Saffron gold
secondary: '#7B4F3A', // Terracotta
highlight: '#FFF4CC', // Light sandalwood
border: '#B89A6E', // Antique brass
dark: '#3A1F0F', // Rich teak
};
// Animations
const fadeIn = keyframes`
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
`;
const scaleIn = keyframes`
from { transform: scale(0.8); opacity: 0; }
to { transform: scale(1); opacity: 1; }
`;
const rotateIn = keyframes`
from { transform: rotate(5deg) scale(0.9); opacity: 0; }
to { transform: rotate(0deg) scale(1); opacity: 1; }
`;
const drawUnderline = keyframes`
0% { width: 0; }
100% { width: 100%; }
`;
const vintagePulse = keyframes`
0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(212, 160, 23, 0.4); }
70% { transform: scale(1.02); box-shadow: 0 0 0 10px rgba(212, 160, 23, 0); }
100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(212, 160, 23, 0); }
`;
const float = keyframes`
0% { transform: translateY(0px); }
50% { transform: translateY(-10px); }
100% { transform: translateY(0px); }
`;
const scrollReveal = keyframes`
from { opacity: 0; transform: translateY(50px); }
to { opacity: 1; transform: translateY(0); }
`;
// Styled components
const VintageBox = styled(Box)({
position: 'relative',
'&::before': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: `url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 18c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm48 25c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm-43-7c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm63 31c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM34 90c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm56-76c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM12 86c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm28-65c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm23-11c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-6 60c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm29 22c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zM32 63c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm57-13c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-9-21c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM60 91c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM35 41c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM12 60c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2z' fill='%233A1F0F' fill-opacity='0.05' fill-rule='evenodd'/%3E%3C/svg%3E")`,
opacity: 0.15,
zIndex: 0,
},
});
const VintageButton = styled(Button)({
position: 'relative',
overflow: 'hidden',
border: `1px solid ${colors.border}`,
color: colors.ink,
backgroundColor: colors.paper,
fontWeight: 400,
letterSpacing: '1px',
textTransform: 'uppercase',
padding: '12px 24px',
borderRadius: '0',
transition: 'all 0.3s ease',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
'&:hover': {
backgroundColor: colors.highlight,
color: colors.dark,
borderColor: colors.accent,
transform: 'translateY(-2px)',
boxShadow: '0 4px 8px rgba(0,0,0,0.2)',
},
'&::after': {
content: '""',
position: 'absolute',
bottom: 0,
left: 0,
width: '100%',
height: '1px',
backgroundColor: colors.accent,
transform: 'scaleX(0)',
transformOrigin: 'right',
transition: 'transform 0.3s ease',
},
'&:hover::after': {
transform: 'scaleX(1)',
transformOrigin: 'left',
},
});
const VintagePulseButton = styled(VintageButton)({
animation: `${vintagePulse} 2s infinite`,
'&:hover': {
animation: 'none',
},
});
const VintageUnderline = styled(Box)({
position: 'relative',
display: 'inline-block',
'&::after': {
content: '""',
position: 'absolute',
bottom: '-5px',
left: 0,
width: '0',
height: '2px',
backgroundColor: colors.accent,
animation: `${drawUnderline} 1.5s forwards`,
animationDelay: '0.5s',
},
});
const VintageImageFrame = styled(Box)({
border: `12px solid ${colors.paper}`,
boxShadow: `8px 8px 0 ${colors.secondary}80, 0 4px 8px rgba(0,0,0,0.1)`,
position: 'relative',
overflow: 'hidden',
'&::before': {
content: '""',
position: 'absolute',
top: '-15px',
left: '-15px',
right: '-15px',
bottom: '-15px',
border: `1px solid ${colors.border}`,
zIndex: -1,
opacity: 0.7,
},
});
const AnimatedSection = styled(Box)({
opacity: 0,
transform: 'translateY(50px)',
animation: `${scrollReveal} 1s forwards`,
});
// Kalawati story sections with updated Pexels images
const storyChapters = [
{
year: '2019',
title: 'Where Curiosity Met Craft',
content:
'Fresh out of fashion school, I found myself drawn to looms, dye pits, and village homes. I organized workshops to listen, learn, and share space with artisans, forging a bond between design, community, and culture.',
image: 'https://images.pexels.com/photos/28382914/pexels-photo-28382914.jpeg?auto=compress&cs=tinysrgb&w=500',
},
{
year: '2020',
title: 'A Name Was Born',
content:
'During the pandemic, I launched a campaign to highlight artisans hit by lockdowns. The Kalawati was born—named after women who hold culture in their palms and creativity in their hearts.',
image: 'https://images.pexels.com/photos/31308739/pexels-photo-31308739.jpeg?auto=compress&cs=tinysrgb&w=500',
},
{
year: '2021',
title: 'Strengthening the Circle',
content:
'I spent the year mapping artisan strengths, connecting traditional skills to modern demand, and building trust for a long-term vision of community and craft.',
image: 'https://images.pexels.com/photos/3772504/pexels-photo-3772504.jpeg?auto=compress&cs=tinysrgb&w=500',
},
{
year: '2022',
title: 'Systems That Serve People',
content:
'Through the JSW Foundation Fellowship, I built systems blending business and empathy—brand building for rural women, value chain development, and sustainable income pathways.',
image: 'https://images.pexels.com/photos/163064/pexels-photo-163064.jpeg?auto=compress&cs=tinysrgb&w=500',
},
{
year: '2023',
title: 'Quiet Creation',
content:
'Working with artisan clusters, we prototyped collections with handloom, embroidery, and natural dyes—crafting stories you could wear.',
image: 'https://images.pexels.com/photos/145939/pexels-photo-145939.jpeg?auto=compress&cs=tinysrgb&w=500',
},
{
year: '2024',
title: 'Kalawati Arrives',
content:
'The Kalawati opens its doors as a brand and movement, offering ethically made handcrafted apparel and decor. Join us to co-create, support heritage, and connect to roots.',
image: 'https://images.pexels.com/photos/774859/pexels-photo-774859.jpeg?auto=compress&cs=tinysrgb&w=500',
},
];
// Process steps with updated Pexels images
const processSteps = [
{
title: 'Design Inspiration',
description: 'Drawing from traditional Indian motifs and contemporary aesthetics',
image: 'https://images.pexels.com/photos/28382914/pexels-photo-28382914.jpeg?auto=compress&cs=tinysrgb&w=500',
},
{
title: 'Material Selection',
description: 'Choosing the finest natural fibers and dyes',
image: 'https://images.pexels.com/photos/145939/pexels-photo-145939.jpeg?auto=compress&cs=tinysrgb&w=500',
},
{
title: 'Artisan Crafting',
description: 'Skilled hands weaving stories into fabric',
image: 'https://images.pexels.com/photos/163064/pexels-photo-163064.jpeg?auto=compress&cs=tinysrgb&w=500',
},
{
title: 'Quality Assurance',
description: 'Meticulous inspection ensuring perfection',
image: 'https://images.pexels.com/photos/3772504/pexels-photo-3772504.jpeg?auto=compress&cs=tinysrgb&w=500',
},
];
export const VintageComingSoonPage: React.FC = () => {
const [days, setDays] = useState(10);
const [hours, setHours] = useState(0);
const [minutes, setMinutes] = useState(0);
const [seconds, setSeconds] = useState(0);
const [email, setEmail] = useState('');
const [subscribed, setSubscribed] = useState(false);
const [currentChapter, setCurrentChapter] = useState(0);
const [scrollPosition, setScrollPosition] = useState(0);
const containerRef = useRef<HTMLDivElement>(null);
// Intersection Observer for scroll animations
const [heroRef, heroInView] = useInView({ threshold: 0.1, triggerOnce: true });
const [storyRef, storyInView] = useInView({ threshold: 0.1, triggerOnce: true });
const [processRef, processInView] = useInView({ threshold: 0.1, triggerOnce: true });
const [footerRef, footerInView] = useInView({ threshold: 0.1, triggerOnce: true });
// Countdown timer
useEffect(() => {
const timer = setInterval(() => {
const now = new Date();
const launchDate = new Date();
launchDate.setDate(now.getDate() + 10);
launchDate.setHours(0, 0, 0, 0);
const diff = launchDate.getTime() - now.getTime();
setDays(Math.floor(diff / (1000 * 60 * 60 * 24)));
setHours(Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)));
setMinutes(Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)));
setSeconds(Math.floor((diff % (1000 * 60)) / 1000));
}, 1000);
return () => clearInterval(timer);
}, []);
// Rotate story chapters for main image
useEffect(() => {
const interval = setInterval(() => {
setCurrentChapter((prev) => (prev + 1) % storyChapters.length);
}, 8000);
return () => clearInterval(interval);
}, []);
// Scroll position for parallax effects
useEffect(() => {
const handleScroll = () => {
const position = window.pageYOffset;
setScrollPosition(position);
};
window.addEventListener('scroll', handleScroll, { passive: true });
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
const handleSubscribe = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
console.log('Subscribed with email:', email);
setSubscribed(true);
setEmail('');
setTimeout(() => setSubscribed(false), 3000);
};
return (
<VintageBox sx={{ minHeight: '100vh', background: colors.paper, color: colors.ink, overflow: 'hidden', position: 'relative' }}>
{/* Paper texture overlay */}
<Box
sx={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundImage:
'url("data:image/svg+xml,%3Csvg width=\'600\' height=\'600\' viewBox=\'0 0 600 600\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cfilter id=\'noiseFilter\'%3E%3CfeTurbulence type=\'fractalNoise\' baseFrequency=\'0.65\' numOctaves=\'3\' stitchTiles=\'stitch\'/%3E%3C/filter%3E%3Crect width=\'100%25\' height=\'100%25\' filter=\'url(%23noiseFilter)\' opacity=\'0.1\'/%3E%3C/svg%3E")',
opacity: 0.3,
zIndex: 0,
}}
/>
{/* Parallax background elements */}
<Box
sx={{
position: 'fixed',
top: `${scrollPosition * 0.1}px`,
right: '5%',
width: '200px',
height: '200px',
backgroundImage: 'url(https://images.pexels.com/photos/28382914/pexels-photo-28382914.jpeg?auto=compress&cs=tinysrgb&w=500)',
backgroundSize: 'cover',
opacity: 0.1,
zIndex: 0,
transform: `rotate(${scrollPosition * 0.02}deg)`,
transition: 'transform 0.3s ease-out',
}}
/>
<Box
sx={{
position: 'fixed',
top: `${400 + scrollPosition * 0.05}px`,
left: '5%',
width: '150px',
height: '150px',
backgroundImage: 'url(https://images.pexels.com/photos/145939/pexels-photo-145939.jpeg?auto=compress&cs=tinysrgb&w=500)',
backgroundSize: 'cover',
opacity: 0.1,
zIndex: 0,
transform: `rotate(${-scrollPosition * 0.03}deg)`,
transition: 'transform 0.3s ease-out',
}}
/>
<Container maxWidth="lg" sx={{ position: 'relative', zIndex: 1, py: 6 }} ref={containerRef}>
{/* Header */}
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', borderBottom: `1px solid ${colors.border}`, py: 4, mb: 4 }}>
<AnimatedSection ref={heroRef} style={{ animationDelay: heroInView ? '0.1s' : '0s' }}>
<Typography
variant="h3"
sx={{
fontWeight: 300,
color: colors.ink,
letterSpacing: '3px',
fontFamily: '"Playfair Display", serif',
textTransform: 'uppercase',
}}
>
<VintageUnderline>The Kalawati</VintageUnderline>
</Typography>
</AnimatedSection>
<AnimatedSection ref={heroRef} style={{ animationDelay: heroInView ? '0.2s' : '0s' }}>
<Box sx={{ display: 'flex', gap: 2 }}>
<IconButton
href="https://instagram.com"
target="_blank"
sx={{ color: colors.secondary, '&:hover': { color: colors.accent, transform: 'scale(1.1)' }, transition: 'all 0.3s ease' }}
>
<InstagramIcon />
</IconButton>
<IconButton
href="https://facebook.com"
target="_blank"
sx={{ color: colors.secondary, '&:hover': { color: colors.accent, transform: 'scale(1.1)' }, transition: 'all 0.3s ease' }}
>
<FacebookIcon />
</IconButton>
<IconButton
href="https://twitter.com"
target="_blank"
sx={{ color: colors.secondary, '&:hover': { color: colors.accent, transform: 'scale(1.1)' }, transition: 'all 0.3s ease' }}
>
<TwitterIcon />
</IconButton>
</Box>
</AnimatedSection>
</Box>
{/* Hero Section with Rotating Image */}
<Box
sx={{
display: 'flex',
flexDirection: { xs: 'column', md: 'row-reverse' },
alignItems: 'center',
gap: 8,
py: 8,
minHeight: '80vh',
}}
>
<AnimatedSection
ref={heroRef}
style={{
animationDelay: heroInView ? '0.3s' : '0s',
flex: 1,
}}
>
<VintageImageFrame
sx={{
height: { xs: '400px', md: '550px' },
background: colors.dark,
backgroundImage: `url(${storyChapters[currentChapter].image})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
filter: 'sepia(0.2) contrast(1.05)',
animation: `${scaleIn} 1.5s ease, ${float} 6s ease-in-out infinite`,
transition: 'background-image 1.5s ease-in-out',
}}
>
<Box
sx={{
position: 'absolute',
bottom: 0,
width: '100%',
background: `linear-gradient(to top, ${colors.dark}CC, transparent)`,
color: colors.paper,
p: 5,
textAlign: 'center',
}}
>
<Typography variant="h6" sx={{ fontWeight: 300, mb: 1, letterSpacing: '2px', fontFamily: '"Playfair Display", serif' }}>
{storyChapters[currentChapter].year}
</Typography>
<Typography
variant="h5"
sx={{ fontWeight: 400, mb: 2, textTransform: 'uppercase', letterSpacing: '2px', fontFamily: '"Playfair Display", serif' }}
>
{storyChapters[currentChapter].title}
</Typography>
<Typography variant="body2" sx={{ opacity: 0.9, fontStyle: 'italic', fontFamily: '"Cormorant Garamond", serif', lineHeight: 1.6 }}>
{storyChapters[currentChapter].content}
</Typography>
</Box>
</VintageImageFrame>
</AnimatedSection>
<AnimatedSection
ref={heroRef}
style={{
animationDelay: heroInView ? '0.4s' : '0s',
flex: 1,
}}
>
<Typography
variant="h1"
sx={{
fontWeight: 300,
mb: 4,
fontSize: { xs: '3rem', md: '4rem' },
lineHeight: 1.2,
color: colors.ink,
fontFamily: '"Playfair Display", serif',
}}
>
<span style={{ fontWeight: 400, color: colors.dark }}>A Journey</span> Woven with Stories, People & Purpose
</Typography>
<Typography
variant="h5"
sx={{
mb: 6,
color: colors.secondary,
fontWeight: 300,
fontStyle: 'italic',
fontFamily: '"Cormorant Garamond", serif',
pl: 4,
position: 'relative',
'&::before': {
content: '""',
position: 'absolute',
left: 0,
top: 0,
height: '100%',
width: '2px',
background: colors.accent,
},
}}
>
Preserving Indian crafts, empowering artisans, and creating timeless pieces for the modern world.
</Typography>
{/* Countdown Timer */}
<Box sx={{ mb: 6 }}>
<Typography
variant="h6"
sx={{
mb: 4,
fontWeight: 300,
color: colors.secondary,
letterSpacing: '2px',
fontFamily: '"Cormorant Garamond", serif',
textTransform: 'uppercase',
}}
>
Collection Unveiling
</Typography>
<Box sx={{ display: 'flex', gap: 3, flexWrap: 'wrap', justifyContent: { xs: 'center', md: 'flex-start' } }}>
{[{ value: days, label: 'Days' }, { value: hours, label: 'Hours' }, { value: minutes, label: 'Minutes' }, { value: seconds, label: 'Seconds' }].map(
(item, index) => (
<Box
key={item.label}
sx={{
background: colors.paper,
borderRadius: '0',
p: 3,
minWidth: '90px',
border: `1px solid ${colors.border}`,
textAlign: 'center',
boxShadow: '0 2px 4px rgba(0,0,0,0.05)',
transition: 'all 0.3s ease',
'&:hover': { transform: 'translateY(-2px)', boxShadow: '0 4px 8px rgba(0,0,0,0.1)' },
animation: `${scaleIn} 1s ease`,
animationDelay: `${index * 0.1}s`,
}}
>
<Typography variant="h4" sx={{ fontWeight: 300, color: colors.ink, fontFamily: '"Playfair Display", serif' }}>
{item.value}
</Typography>
<Typography
variant="body2"
sx={{
color: colors.secondary,
letterSpacing: '1px',
textTransform: 'uppercase',
fontSize: '0.8rem',
fontFamily: '"Cormorant Garamond", serif',
}}
>
{item.label}
</Typography>
</Box>
)
)}
</Box>
</Box>
{/* Email Subscription */}
<Box>
<Box sx={{ display: 'flex', gap: 3, mb: 3, flexDirection: { xs: 'column', sm: 'row' } }}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Your email address"
required
style={{
flex: 1,
padding: '16px 24px',
borderRadius: '0',
border: `1px solid ${colors.border}`,
fontSize: '16px',
outline: 'none',
background: colors.paper,
color: colors.ink,
fontFamily: '"Cormorant Garamond", serif',
transition: 'all 0.3s ease',
}}
/>
<VintagePulseButton
onClick={handleSubscribe}
variant="contained"
sx={{
px: 5,
py: 2,
fontWeight: 300,
fontFamily: '"Cormorant Garamond", serif',
letterSpacing: '2px',
color: colors.ink,
'&:hover': { background: colors.highlight },
}}
>
Notify Me
</VintagePulseButton>
</Box>
{subscribed && (
<Typography
sx={{
color: colors.accent,
fontWeight: 300,
fontSize: '1rem',
display: 'flex',
alignItems: 'center',
gap: 1,
fontFamily: '"Cormorant Garamond", serif',
animation: `${fadeIn} 0.5s ease`,
}}
>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.5 4L6 12L2.5 8.5" stroke={colors.accent} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg>
Thank you! We'll keep you informed.
</Typography>
)}
</Box>
</AnimatedSection>
</Box>
{/* Story Timeline */}
<Box
ref={storyRef}
sx={{
my: 10,
py: 10,
position: 'relative',
'&::before': {
content: '""',
position: 'absolute',
top: 0,
left: '50%',
transform: 'translateX(-50%)',
width: '1px',
height: '100%',
background: colors.border,
zIndex: 0,
},
}}
>
<Container maxWidth="lg">
<AnimatedSection style={{ animationDelay: storyInView ? '0.1s' : '0s' }}>
<Typography
variant="h3"
sx={{
mb: 8,
fontWeight: 300,
textAlign: 'center',
color: colors.ink,
fontFamily: '"Playfair Display", serif',
position: 'relative',
'&::after': {
content: '""',
position: 'absolute',
bottom: '-15px',
left: '50%',
transform: 'translateX(-50%)',
width: '150px',
height: '1px',
background: colors.accent,
},
}}
>
Our Story Woven in Time
</Typography>
</AnimatedSection>
<Grid container spacing={4}>
{storyChapters.map((chapter, index) => (
<Grid key={chapter.year}>
<AnimatedSection
style={{
animationDelay: storyInView ? `${index * 0.2}s` : '0s',
}}
>
<Box
sx={{
display: 'flex',
flexDirection: { xs: 'column', md: index % 2 === 0 ? 'row' : 'row-reverse' },
alignItems: 'center',
gap: 6,
p: 4,
borderRadius: '4px',
boxShadow: '0 2px 8px rgba(0,0,0,0.05)',
background: `${colors.paper}ee`,
}}
>
<Box
sx={{
flex: 1,
textAlign: { xs: 'center', md: index % 2 === 0 ? 'right' : 'left' },
px: { xs: 2, md: 4 },
}}
>
<Typography variant="h5" sx={{ fontWeight: 400, color: colors.dark, mb: 2, fontFamily: '"Playfair Display", serif' }}>
{chapter.year}
</Typography>
<Typography
variant="h4"
sx={{
fontWeight: 300,
color: colors.ink,
mb: 3,
textTransform: 'uppercase',
letterSpacing: '1.5px',
fontFamily: '"Playfair Display", serif',
}}
>
{chapter.title}
</Typography>
<Typography variant="body1" sx={{ color: colors.secondary, fontFamily: '"Cormorant Garamond", serif', lineHeight: 1.8, fontSize: '1.1rem' }}>
{chapter.content}
</Typography>
</Box>
<Box
sx={{
flex: 1,
position: 'relative',
minHeight: '250px',
width: '100%',
'&::before': {
content: '""',
position: 'absolute',
top: '50%',
left: { xs: '50%', md: index % 2 === 0 ? '100%' : 'auto' },
right: { xs: 'auto', md: index % 2 === 0 ? 'auto' : '100%' },
transform: 'translate(-50%, -50%)',
width: '24px',
height: '24px',
borderRadius: '50%',
background: colors.accent,
border: `4px solid ${colors.paper}`,
zIndex: 1,
},
}}
>
<VintageImageFrame
sx={{
height: '250px',
width: '100%',
backgroundImage: `url(${chapter.image})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
filter: 'sepia(0.2) contrast(1.05)',
animation: `${rotateIn} 1.2s ease`,
}}
/>
</Box>
</Box>
</AnimatedSection>
</Grid>
))}
</Grid>
</Container>
</Box>
{/* Process Section */}
<Box ref={processRef} sx={{ my: 10, py: 10, background: colors.highlight, position: 'relative', overflow: 'hidden' }}>
<Container maxWidth="lg">
<AnimatedSection style={{ animationDelay: processInView ? '0.1s' : '0s' }}>
<Typography
variant="h3"
sx={{
mb: 8,
fontWeight: 300,
textAlign: 'center',
color: colors.dark,
fontFamily: '"Playfair Display", serif',
position: 'relative',
'&::after': {
content: '""',
position: 'absolute',
bottom: '-15px',
left: '50%',
transform: 'translateX(-50%)',
width: '150px',
height: '1px',
background: colors.accent,
},
}}
>
The Art of Creation
</Typography>
</AnimatedSection>
<Grid container spacing={4} justifyContent="center">
{processSteps.map((step, index) => (
<Grid key={index}>
<AnimatedSection
style={{
animationDelay: processInView ? `${index * 0.2}s` : '0s',
}}
>
<Box
sx={{
textAlign: 'center',
p: 3,
borderRadius: '4px',
background: colors.paper,
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
transition: 'transform 0.3s ease',
'&:hover': {
transform: 'translateY(-5px)',
},
}}
>
<VintageImageFrame
sx={{
height: '200px',
width: '100%',
backgroundImage: `url(${step.image})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
mb: 3,
filter: 'sepia(0.2) contrast(1.05)',
animation: `${scaleIn} 1s ease`,
}}
/>
<Typography variant="h6" sx={{ fontWeight: 400, color: colors.ink, mb: 2, fontFamily: '"Playfair Display", serif' }}>
{step.title}
</Typography>
<Typography variant="body2" sx={{ color: colors.secondary, fontFamily: '"Cormorant Garamond", serif', lineHeight: 1.6 }}>
{step.description}
</Typography>
</Box>
</AnimatedSection>
</Grid>
))}
</Grid>
</Container>
</Box>
{/* Footer */}
<Box ref={footerRef} sx={{ py: 6, textAlign: 'center', borderTop: `1px solid ${colors.border}` }}>
<AnimatedSection style={{ animationDelay: footerInView ? '0.1s' : '0s' }}>
<Typography
variant="h6"
sx={{
mb: 3,
fontWeight: 300,
color: colors.ink,
letterSpacing: '4px',
fontFamily: '"Playfair Display", serif',
textTransform: 'uppercase',
}}
>
The Kalawati
</Typography>
<Typography
variant="body2"
sx={{
color: colors.secondary,
mb: 4,
maxWidth: '600px',
margin: '0 auto',
fontSize: '1rem',
fontFamily: '"Cormorant Garamond", serif',
lineHeight: 1.6,
}}
>
Join our journey to weave stories, empower artisans, and celebrate Indian heritage. Be the first to experience our handcrafted collections.
</Typography>
<Box sx={{ display: 'flex', justifyContent: 'center', gap: 3, mb: 4 }}>
<IconButton
href="https://instagram.com"
target="_blank"
sx={{ color: colors.secondary, '&:hover': { color: colors.accent, transform: 'scale(1.1)' }, transition: 'all 0.3s ease' }}
>
<InstagramIcon />
</IconButton>
<IconButton
href="https://facebook.com"
target="_blank"
sx={{ color: colors.secondary, '&:hover': { color: colors.accent, transform: 'scale(1.1)' }, transition: 'all 0.3s ease' }}
>
<FacebookIcon />
</IconButton>
<IconButton
href="https://twitter.com"
target="_blank"
sx={{ color: colors.secondary, '&:hover': { color: colors.accent, transform: 'scale(1.1)' }, transition: 'all 0.3s ease' }}
>
<TwitterIcon />
</IconButton>
<IconButton
href="mailto:contact@thekalawati.com"
sx={{ color: colors.secondary, '&:hover': { color: colors.accent, transform: 'scale(1.1)' }, transition: 'all 0.3s ease' }}
>
<EmailIcon />
</IconButton>
</Box>
<Typography
variant="caption"
sx={{ color: colors.secondary, opacity: 0.7, fontSize: '0.8rem', fontFamily: '"Cormorant Garamond", serif' }}
>
© {new Date().getFullYear()} The Kalawati. All rights reserved.
</Typography>
</AnimatedSection>
</Box>
</Container>
</VintageBox>
);
};
export default VintageComingSoonPage;

View File

@ -1,9 +1,19 @@
/* simple defaults (no Tailwind) */
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body, #root { height: 100%; }
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html,
body,
#root {
height: 100%;
}
body {
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
background: #f7fafc;
color: #0f172a;
line-height: 1.4;
}
}

View File

@ -2,7 +2,11 @@
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"lib": [
"DOM",
"DOM.Iterable",
"ESNext"
],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
@ -16,5 +20,7 @@
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"]
}
"include": [
"src"
]
}

4780
yarn.lock Normal file

File diff suppressed because it is too large Load Diff