Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions src/components/CheckoutForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { useState } from 'react';
import {
Box,
Typography,
TextField,
Button,
Grid,
Paper,
Snackbar,
Alert,
Divider,
} from '@mui/material';
import CreditCardIcon from '@mui/icons-material/CreditCard';
import LocalShippingIcon from '@mui/icons-material/LocalShipping';
import { useCart } from '../context/CartContext';

export default function CheckoutForm() {
const { clearCart, total } = useCart();
const [snackOpen, setSnackOpen] = useState(false);

const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
setSnackOpen(true);
clearCart();
};

return (
<Paper elevation={0} sx={{ p: 4, borderRadius: 4, border: '1px solid #e0e0e0' }}>
<Box component="form" onSubmit={handleSubmit}>
{/* Shipping */}
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 3 }}>
<LocalShippingIcon color="primary" />
<Typography variant="h6" fontWeight={600}>
Shipping Details
</Typography>
</Box>
<Grid container spacing={2}>
<Grid size={{ xs: 12 }}>
<TextField fullWidth label="Full Name" placeholder="John Doe" size="small" />
</Grid>
<Grid size={{ xs: 12 }}>
<TextField fullWidth label="Email" type="email" placeholder="example@example.com" size="small" />
</Grid>
<Grid size={{ xs: 12 }}>
<TextField fullWidth label="Address" placeholder="1234 Street" size="small" />
</Grid>
<Grid size={{ xs: 12, sm: 4 }}>
<TextField fullWidth label="City" placeholder="Miami" size="small" />
</Grid>
<Grid size={{ xs: 12, sm: 4 }}>
<TextField fullWidth label="State" placeholder="Florida" size="small" />
</Grid>
<Grid size={{ xs: 12, sm: 4 }}>
<TextField fullWidth label="Zip Code" placeholder="12345" size="small" />
</Grid>
</Grid>

<Divider sx={{ my: 3 }} />

{/* Payment */}
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 3 }}>
<CreditCardIcon color="primary" />
<Typography variant="h6" fontWeight={600}>
Payment Details
</Typography>
<Box
component="img"
src="/card_img.png"
alt="Accepted cards"
sx={{ height: 28, ml: 'auto', filter: 'drop-shadow(0 0 1px #000)' }}
/>
</Box>
<Grid container spacing={2}>
<Grid size={{ xs: 12 }}>
<TextField fullWidth label="Name on Card" placeholder="John Doe" size="small" />
</Grid>
<Grid size={{ xs: 12 }}>
<TextField fullWidth label="Card Number" placeholder="1111-2222-3333-4444" size="small" />
</Grid>
<Grid size={{ xs: 12, sm: 4 }}>
<TextField fullWidth label="Exp Month" placeholder="January" size="small" />
</Grid>
<Grid size={{ xs: 12, sm: 4 }}>
<TextField fullWidth label="Exp Year" placeholder="2026" type="number" size="small" />
</Grid>
<Grid size={{ xs: 12, sm: 4 }}>
<TextField fullWidth label="CVV" placeholder="123" size="small" />
</Grid>
</Grid>

<Button
type="submit"
variant="contained"
fullWidth
size="large"
disabled={total === 0}
sx={{
mt: 3,
py: 1.5,
fontSize: '1.1rem',
borderRadius: 3,
}}
>
Checkout · ${total.toFixed(2)}
</Button>
</Box>

<Snackbar open={snackOpen} autoHideDuration={4000} onClose={() => setSnackOpen(false)}>
<Alert severity="success" onClose={() => setSnackOpen(false)}>
Order placed successfully! Thank you for shopping with Jenna's Recipes.
</Alert>
</Snackbar>
</Paper>
);
}
185 changes: 185 additions & 0 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import { useState } from 'react';
import {
Box,
Container,
Grid,
Typography,
TextField,
Button,
IconButton,
Snackbar,
Alert,
} from '@mui/material';
import EmailIcon from '@mui/icons-material/Email';
import PhoneIcon from '@mui/icons-material/Phone';
import HomeIcon from '@mui/icons-material/Home';
import InfoIcon from '@mui/icons-material/Info';
import LockIcon from '@mui/icons-material/Lock';
import GavelIcon from '@mui/icons-material/Gavel';
import FacebookIcon from '@mui/icons-material/Facebook';
import InstagramIcon from '@mui/icons-material/Instagram';
import TwitterIcon from '@mui/icons-material/Twitter';

export default function Footer() {
const [email, setEmail] = useState('');
const [snackOpen, setSnackOpen] = useState(false);

const handleSubscribe = () => {
if (email) {
setSnackOpen(true);
setEmail('');
}
};

return (
<Box
component="footer"
sx={{
background: 'linear-gradient(135deg, #1b5e20 0%, #2e7d32 50%, #388e3c 100%)',
color: 'white',
mt: 'auto',
pt: 6,
pb: 3,
}}
>
<Container maxWidth="lg">
<Grid container spacing={4}>
{/* Contact */}
<Grid size={{ xs: 12, md: 4 }}>
<Typography variant="h5" gutterBottom sx={{ fontFamily: '"Playfair Display", serif' }}>
Contact
</Typography>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5, mt: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
<HomeIcon fontSize="small" sx={{ opacity: 0.8 }} />
<Typography variant="body2" sx={{ opacity: 0.9 }}>
Po Box 186, Miami, FL, 33211
</Typography>
</Box>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
<EmailIcon fontSize="small" sx={{ opacity: 0.8 }} />
<Typography
component="a"
href="mailto:JennaRecipe@gmail.com"
variant="body2"
sx={{ color: 'rgba(255,255,255,0.9)', textDecoration: 'none', '&:hover': { textDecoration: 'underline' } }}
>
JennaRecipe@gmail.com
</Typography>
</Box>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
<PhoneIcon fontSize="small" sx={{ opacity: 0.8 }} />
<Typography variant="body2" sx={{ opacity: 0.9 }}>
(305) 967-8098
</Typography>
</Box>
</Box>
<Box sx={{ display: 'flex', gap: 1, mt: 2 }}>
<IconButton size="small" sx={{ color: 'rgba(255,255,255,0.7)', '&:hover': { color: 'white' } }}>
<FacebookIcon />
</IconButton>
<IconButton size="small" sx={{ color: 'rgba(255,255,255,0.7)', '&:hover': { color: 'white' } }}>
<InstagramIcon />
</IconButton>
<IconButton size="small" sx={{ color: 'rgba(255,255,255,0.7)', '&:hover': { color: 'white' } }}>
<TwitterIcon />
</IconButton>
</Box>
</Grid>

{/* About */}
<Grid size={{ xs: 12, md: 4 }}>
<Typography variant="h5" gutterBottom sx={{ fontFamily: '"Playfair Display", serif' }}>
About
</Typography>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5, mt: 2 }}>
{[
{ icon: <InfoIcon fontSize="small" />, label: 'About Us' },
{ icon: <LockIcon fontSize="small" />, label: 'Privacy' },
{ icon: <GavelIcon fontSize="small" />, label: 'Terms and Conditions' },
].map((item) => (
<Box
key={item.label}
sx={{
display: 'flex',
alignItems: 'center',
gap: 1.5,
cursor: 'pointer',
opacity: 0.8,
transition: 'opacity 0.2s',
'&:hover': { opacity: 1 },
}}
>
{item.icon}
<Typography variant="body2">{item.label}</Typography>
</Box>
))}
</Box>
</Grid>

{/* Newsletter */}
<Grid size={{ xs: 12, md: 4 }}>
<Typography variant="h5" gutterBottom sx={{ fontFamily: '"Playfair Display", serif' }}>
Newsletter
</Typography>
<Typography variant="body2" sx={{ opacity: 0.8, mt: 2, mb: 2 }}>
Subscribe to get the latest recipes and exclusive offers!
</Typography>
<Box sx={{ display: 'flex', gap: 1 }}>
<TextField
size="small"
placeholder="Your email"
value={email}
onChange={(e) => setEmail(e.target.value)}
sx={{
flex: 1,
'& .MuiOutlinedInput-root': {
bgcolor: 'rgba(255,255,255,0.15)',
borderRadius: 2,
color: 'white',
'& fieldset': { borderColor: 'rgba(255,255,255,0.3)' },
'&:hover fieldset': { borderColor: 'rgba(255,255,255,0.5)' },
'&.Mui-focused fieldset': { borderColor: 'white' },
},
'& .MuiInputBase-input::placeholder': { color: 'rgba(255,255,255,0.5)' },
}}
/>
<Button
variant="contained"
onClick={handleSubscribe}
sx={{
bgcolor: '#ff8c69',
'&:hover': { bgcolor: '#ff613b' },
borderRadius: 2,
px: 3,
background: 'linear-gradient(135deg, #ff8c69 0%, #ff613b 100%)',
}}
>
Subscribe
</Button>
</Box>
</Grid>
</Grid>

<Box
sx={{
borderTop: '1px solid rgba(255,255,255,0.15)',
mt: 4,
pt: 2,
textAlign: 'center',
}}
>
<Typography variant="body2" sx={{ opacity: 0.6 }}>
© 2026 Jenna's Recipes. Made with love. ❤️
</Typography>
</Box>
</Container>

<Snackbar open={snackOpen} autoHideDuration={3000} onClose={() => setSnackOpen(false)}>
<Alert severity="success" onClose={() => setSnackOpen(false)}>
Thanks for subscribing!
</Alert>
</Snackbar>
</Box>
);
}
Loading
Loading