added css

This commit is contained in:
hardik 2025-07-14 11:36:18 +05:30
parent 300ba97431
commit 43b60b5a78
11 changed files with 1442 additions and 139 deletions

View File

@ -0,0 +1,132 @@
const API_BASE_URL = "http://localhost:3000";
interface ApiResponse {
success: boolean;
data?: any;
error?: string;
}
export const postCategory = async (categoryData: {
name: string;
description: string;
parent_category_id?: number;
}): Promise<ApiResponse> => {
try {
const response = await fetch(`${API_BASE_URL}/categories`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
body: JSON.stringify(categoryData),
});
if (!response.ok) {
throw new Error("Failed to post category");
}
return { success: true, data: await response.json() };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : "Unknown error",
};
}
};
export const postBrand = async (brandData: {
name: string;
description: string;
website: string;
}): Promise<ApiResponse> => {
try {
const response = await fetch(`${API_BASE_URL}/brands`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
body: JSON.stringify(brandData),
});
if (!response.ok) {
throw new Error("Failed to post brand");
}
return { success: true, data: await response.json() };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : "Unknown error",
};
}
};
export const postProduct = async (productData: {
name: string;
description: string;
category_id: number;
brand_id: number;
is_active: boolean;
}): Promise<ApiResponse> => {
try {
const response = await fetch(`${API_BASE_URL}/products`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
body: JSON.stringify(productData),
});
if (!response.ok) {
throw new Error("Failed to post product");
}
return { success: true, data: await response.json() };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : "Unknown error",
};
}
};
export const getCategories = async (): Promise<ApiResponse> => {
try {
const response = await fetch(`${API_BASE_URL}/categories`);
if (!response.ok) throw new Error("Failed to fetch categories");
return { success: true, data: await response.json() };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : "Unknown error",
};
}
};
export const getBrands = async (): Promise<ApiResponse> => {
try {
const response = await fetch(`${API_BASE_URL}/brands`);
if (!response.ok) throw new Error("Failed to fetch brands");
return { success: true, data: await response.json() };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : "Unknown error",
};
}
};
export const getProducts = async (): Promise<ApiResponse> => {
try {
const response = await fetch(`${API_BASE_URL}/products`);
if (!response.ok) throw new Error("Failed to fetch products");
return { success: true, data: await response.json() };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : "Unknown error",
};
}
};

View File

@ -0,0 +1,26 @@
import * as React from "react";
import { AppBar, Toolbar, Typography, IconButton, Avatar } from "@mui/material";
import MenuIcon from "@mui/icons-material/Menu";
const AdminAppBar: React.FC = () => {
return (
<AppBar
position="fixed"
sx={{ zIndex: (theme) => theme.zIndex.drawer + 1 }}
>
<Toolbar>
<IconButton color="inherit" edge="start" sx={{ mr: 2 }}>
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1 }}>
Furniture Admin
</Typography>
<IconButton color="inherit">
<Avatar sx={{ width: 32, height: 32 }}>A</Avatar>
</IconButton>
</Toolbar>
</AppBar>
);
};
export default AdminAppBar;

View File

@ -0,0 +1,27 @@
// AdminLayout.tsx
import { Outlet } from "react-router-dom";
import { Box, CssBaseline, styled } from "@mui/material";
import AdminAppBar from "./adminappbar";
import AdminSidebar from "./adminsidebar";
const MainContent = styled(Box)(({ theme }) => ({
flexGrow: 1,
padding: theme.spacing(3),
backgroundColor: "#f5f7fa",
minHeight: "100vh",
}));
const AdminLayout = () => {
return (
<Box sx={{ display: "flex", bgcolor: "background.default" }}>
<CssBaseline />
<AdminAppBar />
<AdminSidebar />
<MainContent>
<Outlet />
</MainContent>
</Box>
);
};
export default AdminLayout;

View File

@ -0,0 +1,79 @@
import * as React from "react";
import {
Drawer,
List,
ListItem,
ListItemButton,
ListItemIcon,
ListItemText,
Divider,
Toolbar,
Box,
} from "@mui/material";
import {
Dashboard as DashboardIcon,
Category as CategoryIcon,
BrandingWatermark as BrandIcon,
Inventory as ProductIcon,
} from "@mui/icons-material";
import { useNavigate } from "react-router-dom";
const drawerWidth = 240;
const AdminSidebar: React.FC = () => {
const navigate = useNavigate();
return (
<Drawer
variant="permanent"
sx={{
width: drawerWidth,
flexShrink: 0,
[`& .MuiDrawer-paper`]: { width: drawerWidth, boxSizing: "border-box" },
}}
>
<Toolbar />
<Box sx={{ overflow: "auto" }}>
<List>
<ListItem disablePadding>
<ListItemButton onClick={() => navigate("/admin")}>
<ListItemIcon>
<DashboardIcon />
</ListItemIcon>
<ListItemText primary="Dashboard" />
</ListItemButton>
</ListItem>
</List>
<Divider />
<List>
<ListItem disablePadding>
<ListItemButton onClick={() => navigate("/admin/categoriesform")}>
<ListItemIcon>
<CategoryIcon />
</ListItemIcon>
<ListItemText primary="Categories" />
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton onClick={() => navigate("/admin/brands")}>
<ListItemIcon>
<BrandIcon />
</ListItemIcon>
<ListItemText primary="Brands" />
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton onClick={() => navigate("/admin/products")}>
<ListItemIcon>
<ProductIcon />
</ListItemIcon>
<ListItemText primary="Products" />
</ListItemButton>
</ListItem>
</List>
</Box>
</Drawer>
);
};
export default AdminSidebar;

View File

@ -0,0 +1,191 @@
// BrandPage.tsx
import React, { useState, useEffect } from "react";
import {
Box,
Typography,
TextField,
Button,
Paper,
Alert,
Grid,
Card,
CardContent,
CardMedia,
Link,
Chip,
} from "@mui/material";
import { Add, Public } from "@mui/icons-material";
import { postBrand, getBrands } from "./adminAPIservices";
const BrandPage = () => {
const [formData, setFormData] = useState({
name: "",
description: "",
website: "",
});
const [brands, setBrands] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
fetchBrands();
}, []);
const fetchBrands = async () => {
const result = await getBrands();
if (result.success) setBrands(result.data);
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
const result = await postBrand(formData);
if (result.success) {
setFormData({ name: "", description: "", website: "" });
fetchBrands();
}
setLoading(false);
};
return (
<Box sx={{ p: 3 }}>
<Typography
variant="h4"
gutterBottom
sx={{ mb: 3, color: "primary.main" }}
>
Brand Management
</Typography>
<Grid container spacing={3}>
<Grid item xs={12} md={4}>
<Paper elevation={3} sx={{ p: 3, borderRadius: 2 }}>
<Typography variant="h6" gutterBottom>
Add New Brand
</Typography>
<form onSubmit={handleSubmit}>
<TextField
fullWidth
label="Brand Name"
name="name"
value={formData.name}
onChange={(e) =>
setFormData({ ...formData, name: e.target.value })
}
margin="normal"
required
/>
<TextField
fullWidth
label="Description"
name="description"
value={formData.description}
onChange={(e) =>
setFormData({ ...formData, description: e.target.value })
}
margin="normal"
multiline
rows={3}
/>
<TextField
fullWidth
label="Website"
name="website"
value={formData.website}
onChange={(e) =>
setFormData({ ...formData, website: e.target.value })
}
margin="normal"
type="url"
/>
<Button
type="submit"
variant="contained"
color="primary"
startIcon={<Add />}
sx={{ mt: 2 }}
disabled={loading}
>
{loading ? "Creating..." : "Create Brand"}
</Button>
</form>
</Paper>
</Grid>
<Grid item xs={12} md={8}>
<Typography variant="h6" gutterBottom sx={{ mb: 2 }}>
Brand Directory ({brands.length})
</Typography>
<Grid container spacing={2}>
{brands.map((brand) => (
<Grid item xs={12} sm={6} md={4} key={brand.id}>
<Card
sx={{
height: "100%",
display: "flex",
flexDirection: "column",
boxShadow: 3,
"&:hover": { boxShadow: 6 },
}}
>
<CardMedia
component="div"
sx={{
pt: "56.25%", // 16:9 ratio
background: `linear-gradient(45deg, ${stringToColor(
brand.name
)} 30%, ${stringToHoverColor(brand.name)} 90%)`,
}}
/>
<CardContent>
<Typography gutterBottom variant="h6" component="div">
{brand.name}
</Typography>
<Typography
variant="body2"
color="text.secondary"
sx={{ mb: 1 }}
>
{brand.description || "No description"}
</Typography>
{brand.website && (
<Link href={brand.website} target="_blank" rel="noopener">
<Chip
icon={<Public fontSize="small" />}
label="Website"
clickable
color="primary"
size="small"
/>
</Link>
)}
</CardContent>
</Card>
</Grid>
))}
</Grid>
</Grid>
</Grid>
</Box>
);
};
// Helper functions for card colors
function stringToColor(string: string) {
let hash = 0;
for (let i = 0; i < string.length; i++) {
hash = string.charCodeAt(i) + ((hash << 5) - hash);
}
let color = "#";
for (let i = 0; i < 3; i++) {
const value = (hash >> (i * 8)) & 0xff;
color += `00${value.toString(16)}`.slice(-2);
}
return color;
}
function stringToHoverColor(string: string) {
return `${stringToColor(string)}80`; // Add opacity
}
export default BrandPage;

View File

@ -0,0 +1,177 @@
// CategoryPage.tsx
import React, { useState, useEffect } from "react";
import {
Box,
Typography,
TextField,
Button,
Paper,
Alert,
Grid,
Card,
CardContent,
CardActions,
Chip,
IconButton,
} from "@mui/material";
import { Add, Edit, Delete } from "@mui/icons-material";
import { postCategory, getCategories } from "./adminAPIservices";
const CategoryForm = () => {
const [formData, setFormData] = useState({
name: "",
description: "",
parent_category_id: 0,
});
const [categories, setCategories] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(false);
const [error, setError] = useState("");
useEffect(() => {
fetchCategories();
}, []);
const fetchCategories = async () => {
const result = await getCategories();
if (result.success) {
setCategories(result.data);
}
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
const result = await postCategory(formData);
if (result.success) {
setSuccess(true);
setFormData({ name: "", description: "", parent_category_id: 0 });
fetchCategories();
} else {
setError(result.error || "Failed to create category");
}
setLoading(false);
};
return (
<Box sx={{ p: 3 }}>
<Typography
variant="h4"
gutterBottom
sx={{ mb: 3, color: "primary.main" }}
>
Category Management
</Typography>
<Grid container spacing={3}>
{/* Form Section */}
<Grid item xs={12} md={4}>
<Paper elevation={3} sx={{ p: 3, borderRadius: 2 }}>
<Typography variant="h6" gutterBottom>
Add New Category
</Typography>
{error && (
<Alert severity="error" sx={{ mb: 2 }}>
{error}
</Alert>
)}
{success && (
<Alert severity="success" sx={{ mb: 2 }}>
Category created!
</Alert>
)}
<form onSubmit={handleSubmit}>
<TextField
fullWidth
label="Name"
name="name"
value={formData.name}
onChange={(e) =>
setFormData({ ...formData, name: e.target.value })
}
margin="normal"
required
/>
<TextField
fullWidth
label="Description"
name="description"
value={formData.description}
onChange={(e) =>
setFormData({ ...formData, description: e.target.value })
}
margin="normal"
multiline
rows={3}
/>
<Button
type="submit"
variant="contained"
color="primary"
startIcon={<Add />}
sx={{ mt: 2 }}
disabled={loading}
>
{loading ? "Creating..." : "Create Category"}
</Button>
</form>
</Paper>
</Grid>
{/* Categories List */}
<Grid item xs={12} md={8}>
<Typography variant="h6" gutterBottom sx={{ mb: 2 }}>
Existing Categories ({categories.length})
</Typography>
<Grid container spacing={2}>
{categories.map((category) => (
<Grid item xs={12} sm={6} md={4} key={category.id}>
<Card
sx={{
height: "100%",
display: "flex",
flexDirection: "column",
transition: "transform 0.2s",
"&:hover": { transform: "scale(1.02)" },
}}
>
<CardContent sx={{ flexGrow: 1 }}>
<Typography gutterBottom variant="h6" component="div">
{category.name}
</Typography>
<Typography
variant="body2"
color="text.secondary"
sx={{ mb: 1 }}
>
{category.description || "No description"}
</Typography>
{category.parent_category_id > 0 && (
<Chip
label={`Parent ID: ${category.parent_category_id}`}
size="small"
sx={{ mr: 1 }}
/>
)}
</CardContent>
<CardActions sx={{ justifyContent: "flex-end" }}>
<IconButton size="small" color="primary">
<Edit fontSize="small" />
</IconButton>
<IconButton size="small" color="error">
<Delete fontSize="small" />
</IconButton>
</CardActions>
</Card>
</Grid>
))}
</Grid>
</Grid>
</Grid>
</Box>
);
};
export default CategoryForm;

View File

@ -0,0 +1,203 @@
import * as React from "react";
import { useState } from "react";
import {
Box,
Typography,
TextField,
Button,
Paper,
Alert,
FormControl,
InputLabel,
Select,
MenuItem,
Checkbox,
FormControlLabel,
} from "@mui/material";
import { SelectChangeEvent } from "@mui/material/Select";
import { postProduct } from "./adminAPIservices";
import Layout from "./adminlayout";
const mockCategories = [
{ id: 1, name: "Sofas" },
{ id: 2, name: "Chairs" },
{ id: 3, name: "Tables" },
{ id: 4, name: "Beds" },
];
const mockBrands = [
{ id: 1, name: "IKEA" },
{ id: 2, name: "Ashley" },
{ id: 3, name: "Herman Miller" },
{ id: 4, name: "West Elm" },
];
interface ProductFormData {
name: string;
description: string;
category_id: number;
brand_id: number;
is_active: boolean;
}
const ProductForm: React.FC = () => {
const [formData, setFormData] = useState<ProductFormData>({
name: "",
description: "",
category_id: 1,
brand_id: 1,
is_active: true,
});
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(false);
const [error, setError] = useState("");
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData((prev) => ({ ...prev, [name]: value }));
};
const handleSelectChange = (e: SelectChangeEvent<number>) => {
const { name, value } = e.target;
setFormData((prev) => ({ ...prev, [name]: value as number }));
};
const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, checked } = e.target;
setFormData((prev) => ({ ...prev, [name]: checked }));
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
setError("");
setSuccess(false);
try {
const result = await postProduct(formData);
if (result.success) {
setSuccess(true);
setFormData({
name: "",
description: "",
category_id: 1,
brand_id: 1,
is_active: true,
});
} else {
setError(result.error || "Failed to create product");
}
} catch (err) {
setError("An unexpected error occurred");
} finally {
setLoading(false);
}
};
return (
<>
<Box sx={{ mb: 4 }}>
<Typography variant="h4" gutterBottom>
Add New Product
</Typography>
<Typography variant="body1" color="text.secondary">
Manage furniture products for your e-commerce store
</Typography>
</Box>
<Paper sx={{ p: 3, mb: 3 }}>
{error && (
<Alert severity="error" sx={{ mb: 3 }}>
{error}
</Alert>
)}
{success && (
<Alert severity="success" sx={{ mb: 3 }}>
Product created successfully!
</Alert>
)}
<form onSubmit={handleSubmit}>
<TextField
fullWidth
label="Product Name"
name="name"
value={formData.name}
onChange={handleInputChange}
margin="normal"
required
/>
<TextField
fullWidth
label="Description"
name="description"
value={formData.description}
onChange={handleInputChange}
margin="normal"
multiline
rows={4}
/>
<FormControl fullWidth margin="normal">
<InputLabel>Category</InputLabel>
<Select
name="category_id"
value={formData.category_id}
onChange={handleSelectChange}
label="Category"
>
{mockCategories.map((category) => (
<MenuItem key={category.id} value={category.id}>
{category.name}
</MenuItem>
))}
</Select>
</FormControl>
<FormControl fullWidth margin="normal">
<InputLabel>Brand</InputLabel>
<Select
name="brand_id"
value={formData.brand_id}
onChange={handleSelectChange}
label="Brand"
>
{mockBrands.map((brand) => (
<MenuItem key={brand.id} value={brand.id}>
{brand.name}
</MenuItem>
))}
</Select>
</FormControl>
<FormControlLabel
control={
<Checkbox
name="is_active"
checked={formData.is_active}
onChange={handleCheckboxChange}
color="primary"
/>
}
label="Active Product"
sx={{ mt: 2 }}
/>
<Box sx={{ mt: 3 }}>
<Button
type="submit"
variant="contained"
color="primary"
disabled={loading}
size="large"
>
{loading ? "Creating..." : "Create Product"}
</Button>
</Box>
</form>
</Paper>
</>
);
};
export default ProductForm;

View File

@ -1,4 +1,4 @@
import React, { useEffect } from "react"; import React from "react";
import { import {
Box, Box,
Container, Container,
@ -8,6 +8,8 @@ import {
Card, Card,
Paper, Paper,
Divider, Divider,
useTheme,
useMediaQuery,
} from "@mui/material"; } from "@mui/material";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { Category } from "./types"; import { Category } from "./types";
@ -15,6 +17,9 @@ import chairone from "../images/chairone.png";
import chairtwo from "../images/chairtwo.png"; import chairtwo from "../images/chairtwo.png";
import chairthree from "../images/chairthree.png"; import chairthree from "../images/chairthree.png";
import carimage from "../images/caraone.png"; import carimage from "../images/caraone.png";
import ContactForm from "../contactus/contactus";
import Footer from "../foorter";
import HeaderSection from "../header";
export const categories: Category[] = [ export const categories: Category[] = [
{ {
@ -70,32 +75,57 @@ export const categories: Category[] = [
const CategoryPage = () => { const CategoryPage = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
return ( return (
<Box sx={{ backgroundColor: "#f5f5f5", minHeight: "100vh" }}> <Box sx={{ backgroundColor: "#f9f9f9", minHeight: "100vh" }}>
<HeaderSection />
{/* Hero Section */} {/* Hero Section */}
<Box <Box
sx={{ sx={{
height: { xs: "60vh", md: "80vh" }, height: { xs: "70vh", md: "85vh" },
backgroundImage: `url(${carimage})`, backgroundImage: `linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)), url(${carimage})`,
backgroundSize: "cover", backgroundSize: "cover",
backgroundPosition: "center", backgroundPosition: "center",
backgroundAttachment: isMobile ? "scroll" : "fixed",
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
textAlign: "center", textAlign: "center",
color: "#fff", color: "#fff",
position: "relative", position: "relative",
overflow: "hidden",
animation: "fadeIn 1.5s ease-in-out",
"@keyframes fadeIn": {
"0%": { opacity: 0 },
"100%": { opacity: 1 },
},
}}
>
<Box
sx={{
position: "relative",
zIndex: 2,
maxWidth: "800px",
px: 3,
transform: "translateY(0)",
transition: "transform 0.5s ease",
"&:hover": {
transform: "translateY(-10px)",
},
}} }}
> >
<Box sx={{ position: "relative", zIndex: 2, maxWidth: "800px", px: 3 }}>
<Typography <Typography
variant="h1" variant="h1"
fontWeight="bold" fontWeight="bold"
sx={{ sx={{
fontSize: { xs: "2.5rem", md: "4rem" }, fontSize: { xs: "2.8rem", md: "4.5rem" },
mb: 3, mb: 3,
textShadow: "2px 2px 4px rgba(0,0,0,0.5)", textShadow: "2px 2px 8px rgba(0,0,0,0.7)",
lineHeight: 1.2,
letterSpacing: "0.03em",
}} }}
> >
Crafted for Comfort, Designed for Life Crafted for Comfort, Designed for Life
@ -104,12 +134,35 @@ const CategoryPage = () => {
variant="h5" variant="h5"
sx={{ sx={{
mb: 4, mb: 4,
color: "#FFA500", color: "#ed9506d6",
fontWeight: 500, fontWeight: 500,
fontStyle: "italic",
letterSpacing: "0.05em",
textShadow: "1px 1px 3px rgba(0,0,0,0.5)",
}} }}
> >
Discover furniture that transforms your space Discover furniture that transforms your space
</Typography> </Typography>
<Button
variant="contained"
size="large"
sx={{
background: "#ed9506d6",
px: 4,
py: 1.5,
borderRadius: "50px",
fontSize: "1.1rem",
fontWeight: 600,
boxShadow: "0 4px 15px rgba(255, 165, 0, 0.3)",
transition: "all 0.3s ease",
"&:hover": {
transform: "translateY(-3px)",
boxShadow: "0 6px 20px rgba(255, 165, 0, 0.4)",
},
}}
>
Explore Collections
</Button>
</Box> </Box>
</Box> </Box>
@ -118,16 +171,39 @@ const CategoryPage = () => {
elevation={0} elevation={0}
sx={{ sx={{
backgroundColor: "#fff", backgroundColor: "#fff",
py: 8, py: { xs: 6, md: 10 },
borderBottom: "1px solid rgba(0,0,0,0.1)", borderBottom: "1px solid rgba(0,0,0,0.05)",
position: "relative",
overflow: "hidden",
"&::before": {
content: '""',
position: "absolute",
top: 0,
left: 0,
right: 0,
height: "4px",
background: "linear-gradient(90deg, #FFA500, #FF8C00, #FFA500)",
},
}} }}
> >
<Container maxWidth="lg"> <Container maxWidth="lg">
<Typography <Typography
variant="h3" variant="h2"
fontWeight="bold" fontWeight="bold"
align="center" align="center"
sx={{ mb: 4 }} sx={{
mb: 6,
position: "relative",
"&::after": {
content: '""',
display: "block",
width: "80px",
height: "4px",
background: "orange",
margin: "20px auto 0",
borderRadius: "2px",
},
}}
> >
Our Craftsmanship Philosophy Our Craftsmanship Philosophy
</Typography> </Typography>
@ -135,7 +211,12 @@ const CategoryPage = () => {
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
<Typography <Typography
variant="body1" variant="body1"
sx={{ mb: 3, fontSize: "1.1rem", lineHeight: 1.8 }} sx={{
mb: 3,
fontSize: "1.15rem",
lineHeight: 1.8,
color: "#555",
}}
> >
At Panto, we believe furniture should be both beautiful and At Panto, we believe furniture should be both beautiful and
functional. Each piece in our collection is meticulously crafted functional. Each piece in our collection is meticulously crafted
@ -144,7 +225,11 @@ const CategoryPage = () => {
</Typography> </Typography>
<Typography <Typography
variant="body1" variant="body1"
sx={{ fontSize: "1.1rem", lineHeight: 1.8 }} sx={{
fontSize: "1.15rem",
lineHeight: 1.8,
color: "#555",
}}
> >
Our designers work closely with ergonomic specialists to create Our designers work closely with ergonomic specialists to create
pieces that don't just look good, but feel good to use every pieces that don't just look good, but feel good to use every
@ -155,7 +240,12 @@ const CategoryPage = () => {
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
<Typography <Typography
variant="body1" variant="body1"
sx={{ mb: 3, fontSize: "1.1rem", lineHeight: 1.8 }} sx={{
mb: 3,
fontSize: "1.15rem",
lineHeight: 1.8,
color: "#555",
}}
> >
We source our materials from responsible suppliers, ensuring We source our materials from responsible suppliers, ensuring
that our environmental impact is minimized. The hardwoods in our that our environmental impact is minimized. The hardwoods in our
@ -164,7 +254,11 @@ const CategoryPage = () => {
</Typography> </Typography>
<Typography <Typography
variant="body1" variant="body1"
sx={{ fontSize: "1.1rem", lineHeight: 1.8 }} sx={{
fontSize: "1.15rem",
lineHeight: 1.8,
color: "#555",
}}
> >
With over 15 years in the industry, we've perfected the balance With over 15 years in the industry, we've perfected the balance
between form and function, offering designs that stand the test between form and function, offering designs that stand the test
@ -176,38 +270,57 @@ const CategoryPage = () => {
</Paper> </Paper>
{/* Category Grid */} {/* Category Grid */}
<Container maxWidth="xl" sx={{ py: 10 }}> <Container maxWidth="xl" sx={{ py: { xs: 6, md: 10 } }}>
<Box sx={{ textAlign: "center", mb: { xs: 4, md: 8 } }}>
<Typography <Typography
variant="h2" variant="h2"
fontWeight="bold" fontWeight="bold"
align="center"
sx={{ sx={{
mb: 2, mb: 2,
color: "#333", color: "#333",
position: "relative",
display: "inline-block",
"&::after": {
content: '""',
position: "absolute",
bottom: "-10px",
left: "50%",
transform: "translateX(-50%)",
width: "100px",
height: "4px",
background: "orange",
borderRadius: "2px",
},
}} }}
> >
Explore Our Collections Explore Our Collections
</Typography> </Typography>
<Typography <Typography
variant="h5" variant="h5"
align="center"
sx={{ sx={{
mb: 6, mt: 3,
color: "#666", color: "#666",
fontStyle: "italic",
fontWeight: 400,
}} }}
> >
Each collection tells a unique design story Each collection tells a unique design story
</Typography> </Typography>
</Box>
<Grid container spacing={6}> <Grid container spacing={{ xs: 4, md: 6 }}>
{categories.map((category) => ( {categories.map((category) => (
<Grid item xs={12} sm={6} md={4} key={category.id}> <Grid item xs={12} sm={6} md={4} lg={3} key={category.id}>
<Card <Card
sx={{ sx={{
height: "100%", height: "100%",
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
transition: "all 0.3s ease", transition:
"all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275)",
borderRadius: "12px",
overflow: "hidden",
boxShadow: "0 5px 15px rgba(0,0,0,0.08)",
"&:hover": { "&:hover": {
transform: "translateY(-10px)", transform: "translateY(-10px)",
boxShadow: "0 15px 30px rgba(0,0,0,0.15)", boxShadow: "0 15px 30px rgba(0,0,0,0.15)",
@ -216,29 +329,63 @@ const CategoryPage = () => {
> >
<Box <Box
sx={{ sx={{
height: "300px", height: "280px",
backgroundImage: `url(${category.image})`, backgroundImage: `url(${category.image})`,
backgroundSize: "cover", backgroundSize: "contain",
backgroundRepeat: "no-repeat",
backgroundPosition: "center", backgroundPosition: "center",
position: "relative",
"&::before": {
content: '""',
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0,
background:
"linear-gradient(to bottom, rgba(0,0,0,0) 0%, rgba(0,0,0,0.03) 100%)",
},
}} }}
/> />
<Box sx={{ p: 4, flexGrow: 1 }}> <Box sx={{ p: 4, flexGrow: 1, backgroundColor: "#fff" }}>
<Typography variant="h4" fontWeight="bold" sx={{ mb: 2 }}> <Typography
variant="h5"
fontWeight="bold"
sx={{
mb: 2,
color: "#333",
minHeight: "64px",
}}
>
{category.name} {category.name}
</Typography> </Typography>
<Typography variant="body1" sx={{ mb: 3, color: "#666" }}> <Typography
variant="body1"
sx={{
mb: 3,
color: "#666",
minHeight: "60px",
}}
>
{category.description} {category.description}
</Typography> </Typography>
<Button <Button
fullWidth fullWidth
variant="contained" variant="contained"
color="secondary"
onClick={() => navigate(`/collections/${category.id}`)} onClick={() => navigate(`/collections/${category.id}`)}
sx={{ sx={{
backgroundColor: "#FFA500",
color: "#fff",
py: 1.5, py: 1.5,
background: "orange",
borderRadius: "8px",
fontWeight: 600,
fontSize: "1rem",
letterSpacing: "0.03em",
boxShadow: "none",
transition: "all 0.3s ease",
"&:hover": { "&:hover": {
backgroundColor: "#E59400", transform: "translateY(-2px)",
boxShadow: `0 4px 12px ${theme.palette.secondary.main}40`,
}, },
}} }}
> >
@ -254,35 +401,115 @@ const CategoryPage = () => {
{/* Testimonials */} {/* Testimonials */}
<Paper <Paper
elevation={0} elevation={0}
sx={{ backgroundColor: "#333", color: "#fff", py: 10 }} sx={{
backgroundColor: "#2c3e50",
color: "#fff",
py: { xs: 6, md: 10 },
position: "relative",
overflow: "hidden",
"&::before": {
content: '""',
position: "absolute",
top: 0,
left: 0,
right: 0,
height: "4px",
background: "linear-gradient(90deg, #FFA500, #FF8C00, #FFA500)",
},
}}
> >
<Container maxWidth="lg"> <Container maxWidth="lg">
<Typography <Typography
variant="h3" variant="h2"
fontWeight="bold" fontWeight="bold"
align="center" align="center"
sx={{ mb: 6 }} sx={{
mb: { xs: 4, md: 8 },
position: "relative",
"&::after": {
content: '""',
display: "block",
width: "80px",
height: "4px",
background: "orange",
margin: "20px auto 0",
borderRadius: "2px",
},
}}
> >
What Our Customers Say What Our Customers Say
</Typography> </Typography>
<Grid container spacing={4}> <Grid container spacing={4}>
{[ {[
{
quote:
"The most comfortable chair I've ever owned - worth every penny!", "The most comfortable chair I've ever owned - worth every penny!",
author: "Sarah J.",
},
{
quote:
"Transformed my living room completely. The quality is exceptional.", "Transformed my living room completely. The quality is exceptional.",
author: "Michael T.",
},
{
quote:
"Best furniture purchase I've made in years. Stunning and sturdy.", "Best furniture purchase I've made in years. Stunning and sturdy.",
].map((quote, i) => ( author: "Emily R.",
},
].map((testimonial, i) => (
<Grid item xs={12} md={4} key={i}> <Grid item xs={12} md={4} key={i}>
<Box <Box
sx={{ p: 4, backgroundColor: "#444", borderRadius: "8px" }} sx={{
p: 4,
height: "100%",
backgroundColor: "rgba(255,255,255,0.1)",
borderRadius: "12px",
border: "1px solid rgba(255,255,255,0.1)",
backdropFilter: "blur(8px)",
transition: "all 0.3s ease",
"&:hover": {
transform: "translateY(-5px)",
boxShadow: "0 10px 25px rgba(0,0,0,0.2)",
},
}}
> >
<Box sx={{ display: "flex", mb: 2 }}>
{[1, 2, 3, 4, 5].map((star) => (
<Box
key={star}
sx={{
color: "orange",
fontSize: "1.5rem",
lineHeight: 1,
mr: 0.5,
}}
>
</Box>
))}
</Box>
<Typography <Typography
variant="body1" variant="body1"
sx={{ fontStyle: "italic", mb: 2 }} sx={{
fontStyle: "italic",
mb: 2,
fontSize: "1.1rem",
lineHeight: 1.7,
}}
> >
"{quote}" "{testimonial.quote}"
</Typography> </Typography>
<Typography variant="body2" color="#FFA500"> <Typography
Happy Customer variant="body2"
// color="secondary"
sx={{
fontWeight: 600,
color: "orange",
fontSize: "1rem",
}}
>
{testimonial.author}
</Typography> </Typography>
</Box> </Box>
</Grid> </Grid>
@ -290,6 +517,9 @@ const CategoryPage = () => {
</Grid> </Grid>
</Container> </Container>
</Paper> </Paper>
<ContactForm />
<Footer />
</Box> </Box>
); );
}; };

View File

@ -8,12 +8,18 @@ import {
Button, Button,
Paper, Paper,
Divider, Divider,
useTheme,
useMediaQuery,
} from "@mui/material"; } from "@mui/material";
import { useParams, Link } from "react-router-dom"; import { useParams, Link } from "react-router-dom";
import { Product } from "./types"; import { Product } from "./types";
import chairone from "../images/chairone.png"; import chairone from "../images/chairone.png";
import chairtwo from "../images/chairtwo.png"; import chairtwo from "../images/chairtwo.png";
import chairthree from "../images/chairthree.png"; import chairthree from "../images/chairthree.png";
import carimg from "../images/caraone.png";
import Header from "../header";
import ContactForm from "../contactus/contactus";
import Footer from "../foorter";
const collectionItems: Record<string, Product[]> = { const collectionItems: Record<string, Product[]> = {
chairs: [ chairs: [
@ -92,74 +98,191 @@ const collectionItems: Record<string, Product[]> = {
], ],
}, },
], ],
// Add more collections as needed
}; };
const CollectionPage = () => { const CollectionPage = () => {
const { collectionId } = useParams<{ collectionId: string }>(); const { collectionId } = useParams<{ collectionId: string }>();
const collection = collectionId ? collectionItems[collectionId] || [] : []; const collection = collectionId ? collectionItems[collectionId] || [] : [];
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
return ( return (
<Box sx={{ backgroundColor: "#f5f5f5", minHeight: "100vh" }}> <Box sx={{ backgroundColor: "#f9f9f9", minHeight: "100vh" }}>
<Header />
{/* Collection Hero */} {/* Collection Hero */}
<Box <Box
sx={{ sx={{
height: "50vh", height: { xs: "60vh", md: "90vh" },
backgroundImage: backgroundImage: `linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)), url(${carimg})`,
"linear-gradient(rgba(0,0,0,0.2), rgba(0,0,0,0.2)), url(/images/collection-bg.jpg)",
backgroundSize: "cover", backgroundSize: "cover",
backgroundPosition: "center", backgroundPosition: "center",
backgroundAttachment: isMobile ? "scroll" : "fixed",
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
textAlign: "center", textAlign: "center",
color: "#fff", color: "#fff",
position: "relative", position: "relative",
overflow: "hidden",
animation: "fadeIn 1s ease-in-out",
"@keyframes fadeIn": {
"0%": { opacity: 0 },
"100%": { opacity: 1 },
},
}}
>
<Box
sx={{
position: "relative",
zIndex: 2,
px: 3,
transform: "translateY(0)",
transition: "transform 0.5s ease",
"&:hover": {
transform: "translateY(-10px)",
},
}} }}
> >
<Box sx={{ position: "relative", zIndex: 2 }}>
<Typography <Typography
variant="h1" variant="h1"
fontWeight="bold" fontWeight="bold"
sx={{ sx={{
fontSize: { xs: "2.5rem", md: "4rem" }, fontSize: { xs: "2.8rem", md: "4rem" },
mb: 2, mb: 2,
textTransform: "capitalize", textTransform: "capitalize",
textShadow: "2px 2px 8px rgba(0,0,0,0.7)",
lineHeight: 1.2,
letterSpacing: "0.03em",
}} }}
> >
{collectionId} Collection {collectionId} Collection
</Typography> </Typography>
<Typography variant="h5" sx={{ color: "#FFA500" }}> <Typography
variant="h5"
sx={{
color: "orange",
fontWeight: 500,
fontStyle: "italic",
letterSpacing: "0.05em",
textShadow: "1px 1px 3px rgba(0,0,0,0.5)",
}}
>
{collection.length} premium designs available {collection.length} premium designs available
</Typography> </Typography>
<Button
variant="contained"
size="large"
sx={{
background: "orange",
mt: 4,
px: 4,
py: 1.5,
borderRadius: "50px",
fontSize: "1.1rem",
fontWeight: 600,
boxShadow: "0 4px 15px rgba(255, 165, 0, 0.3)",
transition: "all 0.3s ease",
"&:hover": {
transform: "translateY(-3px)",
boxShadow: "0 6px 20px rgba(255, 165, 0, 0.4)",
},
}}
>
Shop Now
</Button>
</Box> </Box>
</Box> </Box>
{/* Collection Description */} {/* Collection Description */}
<Paper elevation={0} sx={{ backgroundColor: "#fff", py: 8 }}> <Paper
elevation={0}
sx={{
backgroundColor: "#fff",
py: { xs: 6, md: 10 },
borderBottom: "1px solid rgba(0,0,0,0.05)",
position: "relative",
overflow: "hidden",
"&::before": {
content: '""',
position: "absolute",
top: 0,
left: 0,
right: 0,
height: "4px",
background: "linear-gradient(90deg, #FFA500, #FF8C00, #FFA500)",
},
}}
>
<Container maxWidth="lg"> <Container maxWidth="lg">
<Typography variant="h3" fontWeight="bold" sx={{ mb: 4 }}> <Typography
variant="h2"
fontWeight="bold"
sx={{
mb: 6,
position: "relative",
"&::after": {
content: '""',
display: "block",
width: "80px",
height: "4px",
background: "orange",
margin: "20px 0 0",
borderRadius: "2px",
},
}}
>
About This Collection About This Collection
</Typography> </Typography>
<Grid container spacing={6}>
<Grid item xs={12} md={6}>
<Typography <Typography
variant="body1" variant="body1"
sx={{ mb: 3, fontSize: "1.1rem", lineHeight: 1.8 }} sx={{
mb: 3,
fontSize: "1.15rem",
lineHeight: 1.8,
color: "#555",
}}
> >
Our {collectionId} collection represents the pinnacle of design and Our {collectionId} collection represents the pinnacle of design
craftsmanship. Each piece is created with meticulous attention to and craftsmanship. Each piece is created with meticulous
detail, using only the finest materials sourced from sustainable attention to detail, using only the finest materials sourced
suppliers. from sustainable suppliers.
</Typography> </Typography>
</Grid>
<Grid item xs={12} md={6}>
<Typography <Typography
variant="body1" variant="body1"
sx={{ fontSize: "1.1rem", lineHeight: 1.8 }} sx={{
fontSize: "1.15rem",
lineHeight: 1.8,
color: "#555",
}}
> >
From the initial sketches to the final quality inspection, every From the initial sketches to the final quality inspection, every
step in our process is carefully monitored to ensure exceptional step in our process is carefully monitored to ensure exceptional
quality and durability that will last for generations. quality and durability that will last for generations.
</Typography> </Typography>
<Divider sx={{ my: 6 }} /> </Grid>
<Typography variant="h4" fontWeight="bold" sx={{ mb: 3 }}> </Grid>
<Divider sx={{ my: 6, borderColor: "rgba(0,0,0,0.1)" }} />
<Typography
variant="h3"
fontWeight="bold"
sx={{
mb: 4,
position: "relative",
"&::after": {
content: '""',
display: "block",
width: "60px",
height: "4px",
background: "orange",
margin: "15px 0 0",
borderRadius: "2px",
},
}}
>
Collection Highlights Collection Highlights
</Typography> </Typography>
<Grid container spacing={4} sx={{ mb: 6 }}> <Grid container spacing={4} sx={{ mb: 6 }}>
@ -173,13 +296,22 @@ const CollectionPage = () => {
<Box sx={{ display: "flex", alignItems: "center" }}> <Box sx={{ display: "flex", alignItems: "center" }}>
<Box <Box
sx={{ sx={{
width: "8px", width: "10px",
height: "8px", height: "10px",
backgroundColor: "#FFA500", backgroundColor: "orange",
mr: 2, mr: 2,
borderRadius: "50%",
}} }}
/> />
<Typography>{item}</Typography> <Typography
variant="body1"
sx={{
fontSize: "1.1rem",
color: "#555",
}}
>
{item}
</Typography>
</Box> </Box>
</Grid> </Grid>
))} ))}
@ -188,13 +320,26 @@ const CollectionPage = () => {
</Paper> </Paper>
{/* Products Grid */} {/* Products Grid */}
<Container maxWidth="xl" sx={{ py: 10 }}> <Container maxWidth="xl" sx={{ py: { xs: 6, md: 10 } }}>
<Box sx={{ textAlign: "left", mb: { xs: 4, md: 8 } }}>
<Typography <Typography
variant="h2" variant="h2"
fontWeight="bold" fontWeight="bold"
sx={{ sx={{
mb: 2, mb: 2,
color: "#333", color: "#333",
position: "relative",
display: "inline-block",
"&::after": {
content: '""',
position: "absolute",
bottom: "-10px",
left: 0,
width: "100px",
height: "4px",
background: "orange",
borderRadius: "2px",
},
}} }}
> >
Featured {collectionId} Featured {collectionId}
@ -202,14 +347,17 @@ const CollectionPage = () => {
<Typography <Typography
variant="h5" variant="h5"
sx={{ sx={{
mb: 6, mt: 3,
color: "#666", color: "#666",
fontStyle: "italic",
fontWeight: 400,
}} }}
> >
Browse our curated selection Browse our curated selection
</Typography> </Typography>
</Box>
<Grid container spacing={6}> <Grid container spacing={{ xs: 4, md: 6 }}>
{collection.map((product) => ( {collection.map((product) => (
<Grid item xs={12} sm={6} md={4} key={product.id}> <Grid item xs={12} sm={6} md={4} key={product.id}>
<Card <Card
@ -217,7 +365,12 @@ const CollectionPage = () => {
height: "100%", height: "100%",
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
transition: "all 0.3s ease", transition:
"all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275)",
borderRadius: "12px",
overflow: "hidden",
boxShadow: "0 5px 15px rgba(0,0,0,0.08)",
backgroundColor: "#fff",
"&:hover": { "&:hover": {
transform: "translateY(-10px)", transform: "translateY(-10px)",
boxShadow: "0 15px 30px rgba(0,0,0,0.15)", boxShadow: "0 15px 30px rgba(0,0,0,0.15)",
@ -228,15 +381,41 @@ const CollectionPage = () => {
sx={{ sx={{
height: "300px", height: "300px",
backgroundImage: `url(${product.image})`, backgroundImage: `url(${product.image})`,
backgroundSize: "cover", backgroundSize: "contain", // fits the whole image, may leave empty space
backgroundRepeat: "no-repeat",
backgroundPosition: "center", backgroundPosition: "center",
position: "relative",
"&::before": {
content: '""',
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0,
background:
"linear-gradient(to bottom, rgba(0,0,0,0) 0%, rgba(0,0,0,0.03) 100%)",
},
}} }}
/> />
<Box sx={{ p: 4, flexGrow: 1 }}> <Box sx={{ p: 4, flexGrow: 1 }}>
<Typography variant="h4" fontWeight="bold" sx={{ mb: 2 }}> <Typography
variant="h4"
fontWeight="bold"
sx={{
mb: 2,
color: "#333",
}}
>
{product.name} {product.name}
</Typography> </Typography>
<Typography variant="body1" sx={{ mb: 2, color: "#666" }}> <Typography
variant="body1"
sx={{
mb: 3,
color: "#666",
minHeight: "60px",
}}
>
{product.description} {product.description}
</Typography> </Typography>
<Box sx={{ mb: 3 }}> <Box sx={{ mb: 3 }}>
@ -247,17 +426,32 @@ const CollectionPage = () => {
sx={{ sx={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
mb: 1, mb: 1.5,
color: "#555",
}}
>
<Box
sx={{
color: "orange",
mr: 1.5,
fontSize: "1.5rem",
lineHeight: 0,
}} }}
> >
<span style={{ color: "#FFA500", marginRight: "8px" }}>
</span> </Box>
{detail} {detail}
</Typography> </Typography>
))} ))}
</Box> </Box>
<Typography variant="h5" color="#FFA500" sx={{ mb: 3 }}> <Typography
variant="h5"
color="secondary"
sx={{
mb: 3,
fontWeight: 600,
}}
>
{product.price} {product.price}
</Typography> </Typography>
<Button <Button
@ -266,11 +460,17 @@ const CollectionPage = () => {
fullWidth fullWidth
variant="contained" variant="contained"
sx={{ sx={{
backgroundColor: "#FFA500", background: "orange",
color: "#fff",
py: 1.5, py: 1.5,
borderRadius: "8px",
fontWeight: 600,
fontSize: "1rem",
letterSpacing: "0.03em",
boxShadow: "none",
transition: "all 0.3s ease",
"&:hover": { "&:hover": {
backgroundColor: "#E59400", transform: "translateY(-2px)",
boxShadow: `0 4px 12px ${theme.palette.secondary.main}40`,
}, },
}} }}
> >
@ -282,6 +482,8 @@ const CollectionPage = () => {
))} ))}
</Grid> </Grid>
</Container> </Container>
<ContactForm />
<Footer />
</Box> </Box>
); );
}; };

View File

@ -22,6 +22,9 @@ import StarIcon from "@mui/icons-material/Star";
import chairone from "../images/chairone.png"; import chairone from "../images/chairone.png";
import chairtwo from "../images/chairtwo.png"; import chairtwo from "../images/chairtwo.png";
import chairthree from "../images/chairthree.png"; import chairthree from "../images/chairthree.png";
import HeaderSection from "../header";
import ContactForm from "../contactus/contactus";
import Footer from "../foorter";
const products: Record<string, Record<string, Product>> = { const products: Record<string, Record<string, Product>> = {
chairs: { chairs: {
@ -109,14 +112,15 @@ const ProductPage = () => {
const productImages = [ const productImages = [
product.image, product.image,
"/images/chair-alt1.jpg", `${chairone}`,
"/images/chair-alt2.jpg", `${chairtwo}`,
"/images/chair-detail.jpg", `${chairthree}`,
]; ];
return ( return (
<Box sx={{ backgroundColor: "#f9f9f9", minHeight: "100vh", py: 8 }}> <Box sx={{ backgroundColor: "#f9f9f9", minHeight: "100vh" }}>
<Container maxWidth="lg"> <HeaderSection />
<Container maxWidth="lg" sx={{ mt: 8 }}>
<Grid container spacing={6}> <Grid container spacing={6}>
{/* Product Images */} {/* Product Images */}
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
@ -134,10 +138,15 @@ const ProductPage = () => {
> >
<CardMedia <CardMedia
component="img" component="img"
height="500"
image={productImages[activeImage]} image={productImages[activeImage]}
alt={product.name} alt={product.name}
sx={{ objectFit: "cover" }} sx={{
objectFit: "contain", // show full image
width: "100%", // or a fixed size like "80%" or "400px"
height: "400px", // decrease from 500 to a smaller value
mx: "auto", // center horizontally if width < 100%
display: "block", // ensure image behaves like a block element
}}
/> />
</Card> </Card>
@ -164,12 +173,16 @@ const ProductPage = () => {
> >
<CardMedia <CardMedia
component="img" component="img"
height="100"
image={img} image={img}
alt={`${product.name} view ${index + 1}`} alt={`${product.name} view ${index + 1}`}
sx={{ sx={{
objectFit: "cover", objectFit: "contain",
width: "80px",
height: "80px",
mx: "auto",
display: "block",
opacity: activeImage === index ? 1 : 0.8, opacity: activeImage === index ? 1 : 0.8,
transition: "opacity 0.3s ease",
}} }}
/> />
</Card> </Card>
@ -512,19 +525,19 @@ const ProductPage = () => {
id: "chair2", id: "chair2",
name: "Luxury Lounge Chair", name: "Luxury Lounge Chair",
price: "$399", price: "$399",
image: "/images/chair2.jpg", image: `${chairthree}`,
}, },
{ {
id: "chair3", id: "chair3",
name: "Modern Minimal Chair", name: "Modern Minimal Chair",
price: "$279", price: "$279",
image: "/images/chair3.jpg", image: `${chairtwo}`,
}, },
{ {
id: "chair4", id: "chair4",
name: "Executive Leather Chair", name: "Executive Leather Chair",
price: "$599", price: "$599",
image: "/images/chair4.jpg", image: `${chairthree}`,
}, },
].map((item) => ( ].map((item) => (
<Grid item xs={12} sm={6} md={4} key={item.id}> <Grid item xs={12} sm={6} md={4} key={item.id}>
@ -547,7 +560,8 @@ const ProductPage = () => {
sx={{ sx={{
height: "250px", height: "250px",
backgroundImage: `url(${item.image})`, backgroundImage: `url(${item.image})`,
backgroundSize: "cover", backgroundSize: "contain",
backgroundRepeat: "no-repeat",
backgroundPosition: "center", backgroundPosition: "center",
transition: "transform 0.5s ease", transition: "transform 0.5s ease",
"&:hover": { "&:hover": {
@ -555,6 +569,7 @@ const ProductPage = () => {
}, },
}} }}
/> />
<Box sx={{ p: 3, flexGrow: 1 }}> <Box sx={{ p: 3, flexGrow: 1 }}>
<Typography <Typography
variant="h5" variant="h5"
@ -600,6 +615,8 @@ const ProductPage = () => {
</Grid> </Grid>
</Box> </Box>
</Container> </Container>
<ContactForm />
<Footer />
</Box> </Box>
); );
}; };

View File

@ -1,15 +1,23 @@
import React from "react"; import React from "react";
import { Routes as ReactRouterRoutes, Route } from "react-router-dom"; import { Routes as ReactRouterRoutes, Route } from "react-router-dom";
import LandingPage from "./components/homepage/Landingpage"; import LandingPage from "./components/homepage/Landingpage";
import CategoryPage from "./components/category/CategoryPage";
import ProductPage from "./components/product/ProductPage";
import CollectionPage from "./components/category/collectionpage"; import CollectionPage from "./components/category/collectionpage";
import CartPage from "./components/cart/cart"; import CartPage from "./components/cart/cart";
import AboutPage from "./components/cart/aboutus"; import AboutPage from "./components/cart/aboutus";
import BrandPage from "./components/adminportal/brand";
import ProductPage from "./components/product/ProductPage";
import Layout from "./components/adminportal/adminlayout";
import ProductForm from "./components/adminportal/product";
import CategoryPage from "./components/category/CategoryPage";
import CategoryForm from "./components/adminportal/category";
const Routes: React.FC = () => { const Routes: React.FC = () => {
return ( return (
<ReactRouterRoutes> <ReactRouterRoutes>
{/* Public routes */}
<Route path="/" element={<LandingPage />} /> <Route path="/" element={<LandingPage />} />
<Route path="/cat" element={<CategoryPage />} /> <Route path="/cat" element={<CategoryPage />} />
<Route path="/collections/:collectionId" element={<CollectionPage />} /> <Route path="/collections/:collectionId" element={<CollectionPage />} />
@ -19,6 +27,17 @@ const Routes: React.FC = () => {
/> />
<Route path="/cart" element={<CartPage />} /> <Route path="/cart" element={<CartPage />} />
<Route path="/aboutus" element={<AboutPage />} /> <Route path="/aboutus" element={<AboutPage />} />
{/* Admin routes - using the layout we created */}
<Route path="/admin" element={<Layout />}>
<Route path="categoriesform" element={<CategoryForm />} />
<Route path="brands" element={<BrandPage />} />
<Route path="products" element={<ProductForm />} />
{/* Redirect /admin to /admin/products by default */}
<Route index element={<ProductPage />} />
</Route>
{/* <Route path="*" element={<NotFoundPage />} /> */} {/* <Route path="*" element={<NotFoundPage />} /> */}
</ReactRouterRoutes> </ReactRouterRoutes>
); );