added product categories pages to the application
This commit is contained in:
parent
b10f323455
commit
04b3c4e07b
14
.env
14
.env
@ -1,2 +1,12 @@
|
||||
VITE_ENVIRONMENT=dev
|
||||
VITE_API_URL=https://api.yourproductionurl.com
|
||||
|
||||
const environment = import.meta.env.VITE_ENVIRONMENT;
|
||||
const apiUrl = import.meta.env.VITE_API_URL;
|
||||
|
||||
console.log('Environment:', environment);
|
||||
console.log('API URL:', apiUrl);
|
||||
|
||||
// Example of using the API URL
|
||||
fetch(`${apiUrl}/endpoint`)
|
||||
.then(response => response.json())
|
||||
.then(data => console.log(data))
|
||||
.catch(error => console.error('Error:', error));
|
||||
|
12
src/App.jsx
12
src/App.jsx
@ -14,6 +14,13 @@ import EmployeeList from "./components/admin/EmployeeList";
|
||||
import AddEmployee from "./components/admin/AddEmployee";
|
||||
import EmployeeProfile from "./components/admin/EmployeeProfile";
|
||||
import CategoryList from "./components/categories/CategoryList";
|
||||
import ShirtsProductList from "./components/categories/ShirtsProductList";
|
||||
import SuitsProductList from "./components/categories/SuitsProductList";
|
||||
import TuxedosProductList from "./components/categories/TuxedosProductList";
|
||||
import JacketsProductList from "./components/categories/JacketsProductList";
|
||||
import Customize from "./components/customize/Customize";
|
||||
|
||||
|
||||
import { Refine } from "@refinedev/core";
|
||||
import { RefineKbarProvider } from "@refinedev/kbar";
|
||||
import { ToastContainer, toast } from "react-toastify";
|
||||
@ -46,6 +53,11 @@ const App = () => {
|
||||
<Route path="/add-employee" element={<PrivateRoute><AddEmployee /></PrivateRoute>} />
|
||||
<Route path="/employee-profile" element={<PrivateRoute><EmployeeProfile /></PrivateRoute>} />
|
||||
<Route path="/CategoryList" element={<PrivateRoute><CategoryList /></PrivateRoute>} />
|
||||
<Route path="/products/shirts" element={<ShirtsProductList />} />
|
||||
<Route path="/products/suits" element={<SuitsProductList />} />
|
||||
<Route path="/products/tuxedos" element={<TuxedosProductList />} />
|
||||
<Route path="/products/jackets" element={<JacketsProductList />} />
|
||||
<Route path="/customize/:id" element={<Customize />} />
|
||||
</Routes>
|
||||
</Content>
|
||||
</div>
|
||||
|
@ -2,10 +2,12 @@ import axios from 'axios';
|
||||
|
||||
// Determine environment and set baseURL accordingly
|
||||
const environment = import.meta.env.VITE_ENVIRONMENT;
|
||||
const baseURL = environment === 'dev'
|
||||
const baseURL = environment === 'production'
|
||||
? import.meta.env.VITE_API_URL
|
||||
: 'http://localhost:5000'; // Default for development
|
||||
|
||||
console.log(`Axios baseURL set to: ${baseURL}`); // Log the base URL for debugging
|
||||
|
||||
const axiosInstance = axios.create({
|
||||
baseURL,
|
||||
headers: {
|
||||
@ -13,18 +15,23 @@ const axiosInstance = axios.create({
|
||||
},
|
||||
});
|
||||
|
||||
// Request interceptor to add JWT token
|
||||
axiosInstance.interceptors.request.use((config) => {
|
||||
const token = localStorage.getItem('token');
|
||||
if (token) {
|
||||
config.headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
return config;
|
||||
}, error => {
|
||||
// Handle request error
|
||||
console.error('Request error:', error);
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
// Response interceptor to handle responses globally
|
||||
axiosInstance.interceptors.response.use(
|
||||
response => response,
|
||||
error => {
|
||||
// Handle errors globally
|
||||
if (error.response) {
|
||||
// Server responded with a status other than 2xx
|
||||
console.error('Error response:', error.response.data);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import axiosInstance from './axiosConfig';
|
||||
import axiosInstance from '../axiosConfig';
|
||||
|
||||
|
||||
export const getEmployees = async () => {
|
||||
|
@ -1,15 +1,17 @@
|
||||
import React from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import Sidebar from '../sidebar/Sidebar'; // Ensure the correct path to Sidebar
|
||||
import Sidebar from '../sidebar/Sidebar';
|
||||
import '../../styles/ProductList.css';
|
||||
|
||||
const CategoryList = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Updated categories array with names and specifications
|
||||
const categories = [
|
||||
{ name: 'shirts', image: 'https://www2.hm.com/en_in/productpage.1032522123.html' },
|
||||
{ name: 'suits', image: 'https://www2.hm.com/en_in/productpage.1032522123.html' },
|
||||
{ name: 'tuxedos', image: 'https://www2.hm.com/en_in/productpage.1032522123.html' },
|
||||
{ name: 'jackets', image: 'https://image.coolblue.nl/422x390/products/1101120' },
|
||||
{ name: 'Shirts', image: 'https://www2.hm.com/en_in/productpage.1032522123.html', description: 'shirts' },
|
||||
{ name: 'Suits', image: 'https://www2.hm.com/en_in/productpage.1032522123.html', description: 'suits' },
|
||||
{ name: 'Tuxedos', image: 'https://www2.hm.com/en_in/productpage.1032522123.html', description: 'tuxedos' },
|
||||
{ name: 'Jackets', image: 'https://image.coolblue.nl/422x390/products/1101120', description: 'jackets' },
|
||||
];
|
||||
|
||||
const handleClick = (category) => {
|
||||
@ -22,20 +24,25 @@ const CategoryList = () => {
|
||||
<Sidebar />
|
||||
|
||||
{/* Main content */}
|
||||
<div className="flex-grow p-8">
|
||||
<h1 className="text-3xl font-bold mb-8 text-left pl-4">categories</h1>
|
||||
<div className="grid grid-cols-2 gap-8">
|
||||
{categories.map((category, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="border border-gray-300 p-4 rounded-lg cursor-pointer hover:shadow-lg transition-shadow duration-300 ease-in-out flex flex-col items-center"
|
||||
onClick={() => handleClick(category.name)}
|
||||
>
|
||||
<img src={category.image} alt={category.name} className="w-48 h-48 object-cover" />
|
||||
<h2 className="text-xl font-bold text-center mt-2 capitalize">{category.name}</h2>
|
||||
<p className="text-center text-sm text-gray-600">click to view products</p>
|
||||
</div>
|
||||
))}
|
||||
<div className="flex-grow flex flex-col">
|
||||
<div className="bg-white p-4 flex items-center">
|
||||
<h1 className="ml-4 text-2xl font-medium text-gray-700">Categories</h1>
|
||||
</div>
|
||||
<div className="flex-grow p-8">
|
||||
<div className="grid grid-cols-2 gap-8">
|
||||
{categories.map((category, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="border border-gray-300 p-4 rounded-lg cursor-pointer hover:shadow-lg transition-shadow duration-300 ease-in-out flex flex-col items-center"
|
||||
onClick={() => handleClick(category.name.toLowerCase())} // Updated to handle lowercase category names
|
||||
>
|
||||
<img src={category.image} alt={category.name} className="w-48 h-48 object-cover" />
|
||||
<h2 className="text-xl font-bold text-center mt-2 capitalize">{category.name}</h2>
|
||||
<p className="ml-4 text-2xl font-medium text-gray-700">{category.description}</p>
|
||||
<p className="text-center text-sm text-gray-600 mt-1">Click to view products</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
66
src/components/categories/JacketsProductList.jsx
Normal file
66
src/components/categories/JacketsProductList.jsx
Normal file
@ -0,0 +1,66 @@
|
||||
import React from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import Sidebar from '../sidebar/Sidebar';
|
||||
import ProductRow from './ProductRow';
|
||||
import '../../styles/ProductList.css';
|
||||
|
||||
const products = [
|
||||
{ id: 1, name: 'red bomber jacket', price: 129, image: 'path/to/red-bomber-jacket-image.png' },
|
||||
{ id: 2, name: 'green utility jacket', price: 149, image: 'path/to/green-utility-jacket-image.png' },
|
||||
{ id: 3, name: 'black leather jacket', price: 199, image: 'path/to/black-leather-jacket-image.png' },
|
||||
{ id: 4, name: 'blue aces', price: 99, image: 'path/to/blue-aces-image.png' },
|
||||
{ id: 5, name: 'blue birdseye', price: 99, image: 'path/to/blue-birdseye-image.png' },
|
||||
{ id: 6, name: 'blue hydrangea', price: 99, image: 'path/to/blue-hydrangea-image.png' },
|
||||
];
|
||||
|
||||
const JacketsProductList = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleCustomize = (id) => {
|
||||
navigate(`/customize/${id}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-screen">
|
||||
{/* Sidebar */}
|
||||
<Sidebar />
|
||||
|
||||
{/* Main content */}
|
||||
<div className="flex-grow p-8 product-list">
|
||||
<h1 className="ml-4 text-2xl font-medium text-gray-700 ">Products (Jackets)</h1>
|
||||
<div className="product-actions">
|
||||
<p className="text-sm text-gray-600 ">Total jackets: ({products.length})</p>
|
||||
<div className="flex items-center ">
|
||||
<svg
|
||||
className="w-5 h-5 text-gray-500"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
|
||||
/>
|
||||
</svg>
|
||||
<span className="text-sm text-gray-600">filter</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="product-grid">
|
||||
{products.map((product) => (
|
||||
<ProductRow
|
||||
key={product.id}
|
||||
image17={product.image} // Ensure this matches the prop expected in ProductRow
|
||||
shirts={product.name} // Ensure this matches the prop expected in ProductRow
|
||||
onClick={() => handleCustomize(product.id)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default JacketsProductList;
|
@ -1,7 +1,8 @@
|
||||
import { useMemo } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import React, { useMemo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import '../../styles/ProductList.css';
|
||||
|
||||
const ProductRow = ({ className = "", image17, shirts, propLeft, propTop }) => {
|
||||
const ProductRow = ({ className = "", image17, shirts, onClick, propLeft, propTop }) => {
|
||||
const productRowStyle = useMemo(() => {
|
||||
return {
|
||||
left: propLeft,
|
||||
@ -11,37 +12,43 @@ const ProductRow = ({ className = "", image17, shirts, propLeft, propTop }) => {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`h-[350px] w-[350px] !m-[0] absolute top-[20px] left-[20px] rounded-3xs box-border flex flex-col items-start justify-start py-5 px-0 gap-[15px] text-center text-29xl text-tertiary font-button border-[0.7px] border-solid border-tertiary ${className}`}
|
||||
className={`h-88 w-88 m-0 rounded-lg flex flex-col items-start justify-start py-5 px-0 gap-4 text-center text-3xl font-semibold border border-gray-300 ${className}`}
|
||||
style={productRowStyle}
|
||||
>
|
||||
<img
|
||||
className="self-stretch flex-1 relative max-w-full overflow-hidden max-h-full object-cover"
|
||||
className="w-full h-full object-cover"
|
||||
loading="lazy"
|
||||
alt=""
|
||||
alt={shirts}
|
||||
src={image17}
|
||||
/>
|
||||
<div className="self-stretch flex flex-row items-start justify-center py-0 pr-[21px] pl-5">
|
||||
<div className="relative leading-[53px] lowercase font-semibold inline-block min-w-[124px] mq450:text-10xl mq450:leading-[32px] mq1025:text-19xl mq1025:leading-[42px]">
|
||||
<div className="w-full flex flex-row items-center justify-center py-0 pr-5 pl-5">
|
||||
<div className="leading-9 font-semibold">
|
||||
{shirts}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row items-start justify-start py-0 px-[66px] text-3xl">
|
||||
<div className="relative leading-[110%] lowercase font-semibold mq450:text-lg mq450:leading-[19px]">
|
||||
Click to view products
|
||||
<div className="w-full flex flex-row items-start justify-start py-0 px-16 text-lg">
|
||||
<div className="leading-tight font-semibold">
|
||||
Click to view product details
|
||||
</div>
|
||||
</div>
|
||||
{/* Customize Button */}
|
||||
<button
|
||||
className="customize-button w-full "
|
||||
onClick={onClick}
|
||||
>
|
||||
Customize
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ProductRow.propTypes = {
|
||||
className: PropTypes.string,
|
||||
image17: PropTypes.string,
|
||||
shirts: PropTypes.string,
|
||||
|
||||
/** Style props */
|
||||
image17: PropTypes.string.isRequired,
|
||||
shirts: PropTypes.string.isRequired,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
propLeft: PropTypes.any,
|
||||
propTop: PropTypes.any,
|
||||
};
|
||||
|
||||
export default ProductRow;
|
||||
export default ProductRow;
|
||||
|
66
src/components/categories/ShirtsProductList.jsx
Normal file
66
src/components/categories/ShirtsProductList.jsx
Normal file
@ -0,0 +1,66 @@
|
||||
import React from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import Sidebar from '../sidebar/Sidebar';
|
||||
import ProductRow from './ProductRow';
|
||||
import '../../styles/ProductList.css';
|
||||
|
||||
const products = [
|
||||
{ id: 1, name: 'blue aces', price: 99, image: 'path/to/blue-aces-image.png' },
|
||||
{ id: 2, name: 'blue birdseye', price: 99, image: 'path/to/blue-birdseye-image.png' },
|
||||
{ id: 3, name: 'blue hydrangea', price: 99, image: 'path/to/blue-hydrangea-image.png' },
|
||||
{ id: 4, name: 'blue aces', price: 99, image: 'path/to/blue-aces-image.png' },
|
||||
{ id: 5, name: 'blue birdseye', price: 99, image: 'path/to/blue-birdseye-image.png' },
|
||||
{ id: 6, name: 'blue hydrangea', price: 99, image: 'path/to/blue-hydrangea-image.png' },
|
||||
];
|
||||
|
||||
const ShirtsProductList = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleCustomize = (id) => {
|
||||
navigate(`/customize/${id}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-screen">
|
||||
{/* Sidebar */}
|
||||
<Sidebar />
|
||||
|
||||
{/* Main content */}
|
||||
<div className="flex-grow p-8 product-list">
|
||||
<h1 className="ml-4 text-2xl font-medium text-gray-700 " >Products (Shirts)</h1>
|
||||
<div className="product-actions">
|
||||
<p className="text-sm text-gray-600 ">Total shirts: ({products.length})</p>
|
||||
<div className="flex items-center ">
|
||||
<svg
|
||||
className="w-5 h-5 text-gray-500"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
|
||||
/>
|
||||
</svg>
|
||||
<span className="text-sm text-gray-600">filter</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="product-grid">
|
||||
{products.map((product) => (
|
||||
<ProductRow
|
||||
key={product.id}
|
||||
image17={product.image} // Updated to match prop name
|
||||
shirts={product.name} // Updated to match prop name
|
||||
onClick={() => handleCustomize(product.id)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ShirtsProductList;
|
66
src/components/categories/SuitsProductList.jsx
Normal file
66
src/components/categories/SuitsProductList.jsx
Normal file
@ -0,0 +1,66 @@
|
||||
import React from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import Sidebar from '../sidebar/Sidebar';
|
||||
import ProductRow from './ProductRow';
|
||||
import '../../styles/ProductList.css';
|
||||
|
||||
const products = [
|
||||
{ id: 1, name: 'blue aces', price: 99, image: 'path/to/blue-aces-image.png' },
|
||||
{ id: 2, name: 'blue birdseye', price: 99, image: 'path/to/blue-birdseye-image.png' },
|
||||
{ id: 3, name: 'blue hydrangea', price: 99, image: 'path/to/blue-hydrangea-image.png' },
|
||||
{ id: 4, name: 'blue aces', price: 99, image: 'path/to/blue-aces-image.png' },
|
||||
{ id: 5, name: 'blue birdseye', price: 99, image: 'path/to/blue-birdseye-image.png' },
|
||||
{ id: 6, name: 'blue hydrangea', price: 99, image: 'path/to/blue-hydrangea-image.png' },
|
||||
];
|
||||
|
||||
const SuitsProductList = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleCustomize = (id) => {
|
||||
navigate(`/customize/${id}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-screen">
|
||||
{/* Sidebar */}
|
||||
<Sidebar />
|
||||
|
||||
{/* Main content */}
|
||||
<div className="flex-grow p-8 product-list">
|
||||
<h1 className="ml-4 text-2xl font-medium text-gray-700 ">Products (Suits)</h1>
|
||||
<div className="product-actions">
|
||||
<p className="text-sm text-gray-600 ">Total suits: ({products.length})</p>
|
||||
<div className="flex items-center ">
|
||||
<svg
|
||||
className="w-5 h-5 text-gray-500"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
|
||||
/>
|
||||
</svg>
|
||||
<span className="text-sm text-gray-600">filter</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="product-grid">
|
||||
{products.map((product) => (
|
||||
<ProductRow
|
||||
key={product.id}
|
||||
image17={product.image} // Ensure this matches the prop expected in ProductRow
|
||||
shirts={product.name} // Ensure this matches the prop expected in ProductRow
|
||||
onClick={() => handleCustomize(product.id)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SuitsProductList;
|
66
src/components/categories/TuxedosProductList.jsx
Normal file
66
src/components/categories/TuxedosProductList.jsx
Normal file
@ -0,0 +1,66 @@
|
||||
import React from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import Sidebar from '../sidebar/Sidebar';
|
||||
import ProductRow from './ProductRow';
|
||||
import '../../styles/ProductList.css';
|
||||
|
||||
const products = [
|
||||
{ id: 1, name: 'black tuxedo', price: 199, image: 'path/to/black-tuxedo-image.png' },
|
||||
{ id: 2, name: 'navy tuxedo', price: 199, image: 'path/to/navy-tuxedo-image.png' },
|
||||
{ id: 3, name: 'grey tuxedo', price: 199, image: 'path/to/grey-tuxedo-image.png' },
|
||||
{ id: 4, name: 'blue aces', price: 99, image: 'path/to/blue-aces-image.png' },
|
||||
{ id: 5, name: 'blue birdseye', price: 99, image: 'path/to/blue-birdseye-image.png' },
|
||||
{ id: 6, name: 'blue hydrangea', price: 99, image: 'path/to/blue-hydrangea-image.png' },
|
||||
];
|
||||
|
||||
const TuxedosProductList = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleCustomize = (id) => {
|
||||
navigate(`/customize/${id}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-screen">
|
||||
{/* Sidebar */}
|
||||
<Sidebar />
|
||||
|
||||
{/* Main content */}
|
||||
<div className="flex-grow p-8 product-list">
|
||||
<h1 className="ml-4 text-2xl font-medium text-gray-700 ">Products (Tuxedos)</h1>
|
||||
<div className="product-actions">
|
||||
<p className="text-sm text-gray-600 ">Total tuxedos: ({products.length})</p>
|
||||
<div className="flex items-center ">
|
||||
<svg
|
||||
className="w-5 h-5 text-gray-500"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
|
||||
/>
|
||||
</svg>
|
||||
<span className="text-sm text-gray-600">filter</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="product-grid">
|
||||
{products.map((product) => (
|
||||
<ProductRow
|
||||
key={product.id}
|
||||
image17={product.image} // Ensure this matches the prop expected in ProductRow
|
||||
shirts={product.name} // Ensure this matches the prop expected in ProductRow
|
||||
onClick={() => handleCustomize(product.id)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TuxedosProductList;
|
106
src/components/customize/Customize.jsx
Normal file
106
src/components/customize/Customize.jsx
Normal file
@ -0,0 +1,106 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useParams, useNavigate, Link } from 'react-router-dom';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faChevronLeft } from '@fortawesome/free-solid-svg-icons';
|
||||
import Sidebar from '../sidebar/Sidebar';
|
||||
import '../../styles/Customize.css';
|
||||
|
||||
|
||||
|
||||
const Customize = () => {
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [style, setStyle] = useState('');
|
||||
const [material, setMaterial] = useState('');
|
||||
|
||||
const handleStyleChange = (event) => {
|
||||
setStyle(event.target.value);
|
||||
};
|
||||
|
||||
const handleMaterialChange = (event) => {
|
||||
setMaterial(event.target.value);
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
const customization = {
|
||||
productId: id,
|
||||
style,
|
||||
material,
|
||||
};
|
||||
|
||||
fetch('/api/saveCustomization', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(customization),
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log('Success:', data);
|
||||
navigate('/');
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-screen ">
|
||||
{/* Sidebar */}
|
||||
<Sidebar />
|
||||
|
||||
{/* Main content */}
|
||||
<div className="flex-grow flex flex-col">
|
||||
<div className="bg-white p-4 flex items-center">
|
||||
<Link to="/CategoryList" className="">
|
||||
<FontAwesomeIcon icon={faChevronLeft} />
|
||||
</Link>
|
||||
<h1 className="ml-4 text-2xl font-medium text-gray-700 ">Customize Product</h1>
|
||||
</div>
|
||||
<div className="flex-grow flex items-center justify-center p-8">
|
||||
<div className="bg-white p-6 rounded-lg shadow-lg w-full max-w-md">
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-medium text-gray-700">
|
||||
Style:
|
||||
<select
|
||||
value={style}
|
||||
onChange={handleStyleChange}
|
||||
className="mt-1 block w-full py-2 px-3 "
|
||||
>
|
||||
<option value="">Select style</option>
|
||||
<option value="collar">Collar</option>
|
||||
<option value="cuff">Cuff</option>
|
||||
<option value="placket">Placket</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-medium text-gray-700">
|
||||
Material:
|
||||
<select
|
||||
value={material}
|
||||
onChange={handleMaterialChange}
|
||||
className="mt-1 block w-full "
|
||||
>
|
||||
<option value="">Select material</option>
|
||||
<option value="cotton">Cotton</option>
|
||||
<option value="polyester">Polyester</option>
|
||||
<option value="linen">Linen</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleSave}
|
||||
className="w-full py-2 px-4"
|
||||
>
|
||||
Save Style and Material
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Customize;
|
@ -1,4 +1,4 @@
|
||||
import axiosInstance from "../api/axiosConfig"; // Import the global axios instance
|
||||
import axiosInstance from "../api/axiosConfig";
|
||||
|
||||
// Get all users with their metadata
|
||||
export const getAllUsers = async () => {
|
||||
|
82
src/styles/Customize.css
Normal file
82
src/styles/Customize.css
Normal file
@ -0,0 +1,82 @@
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.main-content {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: #ffffff;
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1.5rem; /* text-2xl */
|
||||
font-weight: 600; /* font-semibold */
|
||||
color: #0e355b; /* Dark blue */
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
color: #0e355b;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.inner-content {
|
||||
flex-grow: 1;
|
||||
padding: 1.5rem;
|
||||
background-color: #f9fafb;
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.form-input,
|
||||
.form-select {
|
||||
width: 100%;
|
||||
padding: 0.75rem; /* p-3 */
|
||||
border: 1px solid #cbd5e0; /* border-gray-400 */
|
||||
border-radius: 0.375rem; /* rounded-md */
|
||||
}
|
||||
|
||||
.form-input:focus,
|
||||
.form-select:focus {
|
||||
border-color: #2d3748; /* Darker gray border on focus */
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
background-color: #0e355b; /* Dark blue */
|
||||
color: white;
|
||||
padding: 0.75rem 1.5rem; /* p-3 */
|
||||
border-radius: 0.375rem; /* rounded-md */
|
||||
font-weight: 600; /* font-semibold */
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.submit-button:hover {
|
||||
background-color: #1e3a8a; /* Darker blue on hover */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
107
src/styles/ProductList.css
Normal file
107
src/styles/ProductList.css
Normal file
@ -0,0 +1,107 @@
|
||||
.product-list {
|
||||
padding: 20px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.product-list h1 {
|
||||
color: #0e355b;
|
||||
text-align: left;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.product-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-button {
|
||||
padding: 10px 20px;
|
||||
background-color: #0e355b;
|
||||
color: #ffffff;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.filter-button:hover {
|
||||
background-color: #154676;
|
||||
}
|
||||
|
||||
.product-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.product-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.product-grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.product-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
transition: box-shadow 0.3s;
|
||||
}
|
||||
|
||||
.product-row:hover {
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.product-row img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.product-row .product-name {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
color: #0e355b;
|
||||
padding: 10px 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.product-row .view-products {
|
||||
font-size: 1rem;
|
||||
color: #ffffff;
|
||||
background-color: #0e355b;
|
||||
padding: 10px 20px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.product-row .view-products:hover {
|
||||
background-color: #154676;
|
||||
}
|
||||
|
||||
.customize-button {
|
||||
background-color: #0e355b;
|
||||
color: #d1d5db;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 8px 16px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.customize-button:hover {
|
||||
background-color: #154676;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user