From 6548c90566a42b385ee07ea500200dc13335eae9 Mon Sep 17 00:00:00 2001 From: FaizyQadri Date: Mon, 14 Apr 2025 20:37:22 +0530 Subject: [PATCH 1/2] feat(cart): style adding --- fetch-summit-settings.sh | 0 pages/product-information/CartTable.tsx | 58 ++++ pages/product-information/CustomTable.tsx | 53 +++ pages/product-information/index.tsx | 401 ++++++++++++++++++++++ services/constants/Colors.tsx | 19 + 5 files changed, 531 insertions(+) mode change 100644 => 100755 fetch-summit-settings.sh create mode 100644 pages/product-information/CartTable.tsx create mode 100644 pages/product-information/CustomTable.tsx create mode 100644 pages/product-information/index.tsx create mode 100644 services/constants/Colors.tsx diff --git a/fetch-summit-settings.sh b/fetch-summit-settings.sh old mode 100644 new mode 100755 diff --git a/pages/product-information/CartTable.tsx b/pages/product-information/CartTable.tsx new file mode 100644 index 00000000..0776f175 --- /dev/null +++ b/pages/product-information/CartTable.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { IoAddOutline, IoRemoveOutline } from 'react-icons/io5'; +import CustomTable from './CustomTable'; // adjust path as needed + +type CartItem = { + metal: string; + purity: string; + tone: string; + diamond: string; + size: string; + quantity: number; + total: number; +}; + +type CartTableProps = { + cart: CartItem[]; + handleCartQuantityChange: (index: number, change: number) => void; +}; + +const CartTable: React.FC = ({ cart, handleCartQuantityChange }) => { + const headers = ['Metal', 'Purity', 'Tone', 'Diamond', 'Size', 'Quantity', 'Total']; + + const rows = cart.map((item, index) => [ + item.metal, + item.purity, + item.tone, + item.diamond, + item.size, + // Quantity Control (JSX Element) +
+ +
{item.quantity}
+ +
, + item.total.toFixed(2), + ]); + if (cart.length === 0) { + rows.push([ + + No items in cart + , + ]); + } + + return ; +}; + +export default CartTable; diff --git a/pages/product-information/CustomTable.tsx b/pages/product-information/CustomTable.tsx new file mode 100644 index 00000000..74884d39 --- /dev/null +++ b/pages/product-information/CustomTable.tsx @@ -0,0 +1,53 @@ +import React from 'react'; + +type CellContent = + | string + | number + | JSX.Element + | { content: string | number | JSX.Element; props?: React.TdHTMLAttributes }; + +type CustomTableProps = { + headers?: string[]; + rows: CellContent[][]; +}; + +const CustomTable: React.FC = ({ headers = [], rows }) => { + const columnCount = Math.max(...rows.map((row) => row.length), headers.length); + + return ( +
+ + {headers.length > 0 && ( + + + {headers.length === 1 && columnCount > 1 ? ( + + ) : ( + headers.map((header, i) => ) + )} + + + )} + + {rows.map((row, i) => ( + + {row.map((cell, j) => { + if (typeof cell === 'object' && 'content' in cell) { + return ( + + ); + } else { + return ; + } + })} + + ))} + +
{headers[0]}{header}
+ {cell.content} + {cell}
+
+ ); +}; + +export default CustomTable; diff --git a/pages/product-information/index.tsx b/pages/product-information/index.tsx new file mode 100644 index 00000000..2a7079ca --- /dev/null +++ b/pages/product-information/index.tsx @@ -0,0 +1,401 @@ +import React, { useState } from 'react'; +import { IoIosArrowBack } from 'react-icons/io'; +import { IoAddOutline, IoRemoveOutline } from 'react-icons/io5'; +import ProductInfoTable from './CustomTable'; +import CartTable from './CartTable'; + +import productInformationStyle from '../../styles/components/productInformation.module.scss'; + +export default function ProductDetails() { + const [selectedMetal, setSelectedMetal] = useState('Gold'); + const [selectedPurity, setSelectedPurity] = useState(''); + const [selectedTone, setSelectedTone] = useState(''); + const [selectedDiamond, setSelectedDiamond] = useState(''); + const [selectedSize, setSelectedSize] = useState(''); + const [quantity, setQuantity] = useState(1); + const [cart, setCart] = useState([]); + const [error, setError] = useState(''); + + const handleMainQuantityChange = (delta: any) => { + setQuantity((prev) => Math.max(1, prev + delta)); + }; + + const handleCartQuantityChange = (itemIndex: any, delta: any) => { + setCart((prevCart) => + prevCart.map((item, idx) => + idx === itemIndex + ? { + ...item, + quantity: Math.max(1, item.quantity + delta), + total: item.unitPrice * Math.max(1, item.quantity + delta), + } + : item + ) + ); + }; + + const handleAddToCart = () => { + if (selectedMetal !== 'Platinum') { + if (!selectedPurity || !selectedTone) { + setError('Please select purity and tone for Gold.'); + return; + } + } + + if (!selectedDiamond || !selectedSize) { + setError('Please select diamond type and size.'); + return; + } + + // Clear error + setError(''); + + alert('Product has been added'); + + // Add item to cart + const unitPrice = selectedMetal === 'Gold' ? 211.22 : 311.22; + const newItem = { + metal: selectedMetal, + purity: selectedMetal !== 'Platinum' ? selectedPurity : '-', + tone: selectedMetal !== 'Platinum' ? selectedTone : '-', + diamond: selectedDiamond, + size: selectedSize, + quantity, + unitPrice, + total: unitPrice * quantity, // This is a number + }; + + setCart([...cart, newItem]); + + setSelectedPurity(''); + setSelectedTone(''); + setSelectedDiamond(''); + setSelectedSize(''); + setQuantity(1); + }; + + const metalHeader = ['Kt', 'Colour', 'Wght', 'Rate', 'Value']; + const metalRows = [ + [22, 'Yellow', 10.5, 5800, (10.5 * 5800).toFixed(2)], + [18, 'White', 7.3, 4500, (7.3 * 4500).toFixed(2)], + ]; + + const diamondHeader = ['Shape', 'Quality', 'Size 1', 'Size 2', 'Pointer', 'Qty', 'Carats', 'Rate', 'Value', 'Setting', 'Rate', 'Value']; + const diamondRows = [ + ['Round', 'VVS', '1.2', '1.4', '0.03', 10, 0.3, 5000, (0.3 * 5000).toFixed(2), 'Prong', 200, (10 * 200).toFixed(2)], + ['Princess', 'VS', '1.5', '1.7', '0.05', 8, 0.4, 5200, (0.4 * 5200).toFixed(2), 'Bezel', 220, (8 * 220).toFixed(2)], + ]; + + const colorStoneHeader = [ + 'Shape', + 'Quality', + 'Size 1', + 'Size 2', + 'Pointer', + 'Qty', + 'Carats', + 'Rate', + 'Value', + 'Setting', + 'Rate', + 'Value', + ]; + + const colorStoneRows = [ + ['Round', 'VVS', '1.2', '1.4', '0.03', 10, 0.3, 5000, (0.3 * 5000).toFixed(2), 'Prong', 200, (10 * 200).toFixed(2)], + ['Princess', 'VS', '1.5', '1.7', '0.05', 8, 0.4, 5200, (0.4 * 5200).toFixed(2), 'Bezel', 220, (8 * 220).toFixed(2)], + ]; + + const accessoriesHeader = [ + 'Shape', + 'Quality', + 'Size 1', + 'Size 2', + 'Per pc wt', + 'Qty', + 'Weight', + 'Rate', + 'Value', + 'Setting', + 'Rate', + 'Value', + ]; + + const accessoriesRows = [ + ['Round', 'VVS', '1.2', '1.4', '0.05', 12, 0.6, 4000, (0.6 * 4000).toFixed(2), 'Prong', 150, (12 * 150).toFixed(2)], + ['Oval', 'VS', '1.3', '1.5', '0.07', 10, 0.7, 4200, (0.7 * 4200).toFixed(2), 'Bezel', 180, (10 * 180).toFixed(2)], + ]; + + const labourHeader = ['Main Kt', 'Lab Cd', 'Qt/Wt', 'Rate', 'Value']; + + const labourRows = [ + ['10.5', 'L123', '0.5', 1000, (0.5 * 1000).toFixed(2)], + ['12.0', 'L456', '0.8', 1200, (0.8 * 1200).toFixed(2)], + ]; + + const summaryHeaders = ['Summary']; + const summaryRows = [ + ['Metal Weight', 'qty', 'value'], + ['Purity', 'qty', 'value'], + ['Tone', 'qty', 'value'], + ['Diamond', 'qty', 'value'], + ['Size', 'qty', 'value'], + ]; + + const customerInfoRows = [['Test text display'], ['Another sample line'], ['Customer liked it'], ['Fast delivery'], ['Will buy again']]; + + return ( +
+
+ +
Product Details
+
+ +
+ {/* Left Column */} +
+
+
+ Main Product +
+
+ Side 1 + Side 2 +
+
+
+ + {/* Right Column */} +
+
+
+

JY-2025-001

+
€{selectedMetal === 'Gold' ? '211.22' : '311.22'}
+
+ + {error &&
{error}
} + + +
+ + + + + + {selectedMetal !== 'Platinum' && ( + <> +
+ +
+ {['9Kt', '10Kt', '14Kt', '18Kt'].map((k, i) => ( + + ))} +
+ +
+ +
+ {['Yellow', 'White', 'Rose'].map((tone, i) => ( + + ))} +
+ + )} + +
+ +
+ {['I1', 'SI', 'VS', 'LGD'].map((type, i) => ( + + ))} +
+ +
+ +
+ {['4', '4.5', '5', '5.5', '6', '6.5', '7', '7.5', '8', '8.5'].map((size, i) => ( + + ))} +
+ +
+ {/* Quantity Selector */} +
+ +
+ +
{quantity}
+ +
+
+ + {/* Add to Cart Button */} +
+ +
+
+
+
+
+ + {/* Cart Summary */} +
+
+
+ Side 1 +
Your Cart for Jy-2025-001
+
+ +
Subtotal: €{cart.reduce((acc, item) => acc + (Number(item.total) || 0), 0).toFixed(2)}
+
+ + +
+ + {/* Metal Details */} + + {/* --- Desktop Version: Positioned Summary and Customer Info --- */} +
+ {/* Left: Metal Details */} +
+
Metal Details
+ +
+ + {/* Right: Absolute positioned Summary and Customer Info */} +
+
+ +
+
+ +
+
+ + +
+
+
+ + {/* Diamond Details */} + +
+
Diamond Details
+ +
+ + {/* Color Stone Details */} + +
+
Color Stone Details
+ +
+ + {/* Accessories Details */} + +
+
Accessories Details
+ +
+ + {/* Labour Details */} + +
+
Labour Details
+ +
+ + {/* --- Mobile Version: Summary and Customer Info at Bottom --- */} +
+
+ +
+
+ +
+
+ + +
+
+
+ ); +} diff --git a/services/constants/Colors.tsx b/services/constants/Colors.tsx new file mode 100644 index 00000000..3de994b2 --- /dev/null +++ b/services/constants/Colors.tsx @@ -0,0 +1,19 @@ +export const colors = { + primary: '#fff', + softWhite: '#f8f9fa', + red: '#ff3400', + black: '#000', + lightgray: '#F5F5F5', + mediumGray: '#ddd', + darkGray: '#333', + white: '#fff', + transparent: 'transparent', + lightPink: '#F1E9E9', + darkPink: '#792E2C', + darkBlue: '#082468', + lightBlue: '#E5ECFF', + grey: '#EDECEC', + lightPurple: '#F2EEFC', + cardTextGrey: '#9F9F9F', + softGray: '#F6F6F6', +}; From 132a9da9993fffac3bd6b6e15742ce762cc04be4 Mon Sep 17 00:00:00 2001 From: FaizyQadri Date: Tue, 15 Apr 2025 19:01:49 +0530 Subject: [PATCH 2/2] feat: complete product info page UI --- pages/product-information/CartTable.tsx | 12 +- pages/product-information/CustomTable.tsx | 8 +- pages/product-information/index.tsx | 138 +++++++++++++++++++--- 3 files changed, 137 insertions(+), 21 deletions(-) diff --git a/pages/product-information/CartTable.tsx b/pages/product-information/CartTable.tsx index 0776f175..b8104d8a 100644 --- a/pages/product-information/CartTable.tsx +++ b/pages/product-information/CartTable.tsx @@ -20,7 +20,7 @@ type CartTableProps = { const CartTable: React.FC = ({ cart, handleCartQuantityChange }) => { const headers = ['Metal', 'Purity', 'Tone', 'Diamond', 'Size', 'Quantity', 'Total']; - const rows = cart.map((item, index) => [ + const rows: any[][] = cart.map((item, index) => [ item.metal, item.purity, item.tone, @@ -46,9 +46,13 @@ const CartTable: React.FC = ({ cart, handleCartQuantityChange }) ]); if (cart.length === 0) { rows.push([ - - No items in cart - , + { + content: 'No items in cart', + props: { + colSpan: 7, + className: 'text-center fw-bold px-4', + }, + }, ]); } diff --git a/pages/product-information/CustomTable.tsx b/pages/product-information/CustomTable.tsx index 74884d39..c631812b 100644 --- a/pages/product-information/CustomTable.tsx +++ b/pages/product-information/CustomTable.tsx @@ -34,12 +34,16 @@ const CustomTable: React.FC = ({ headers = [], rows }) => { {row.map((cell, j) => { if (typeof cell === 'object' && 'content' in cell) { return ( - + {cell.content} ); } else { - return {cell}; + return ( + + {cell} + + ); } })} diff --git a/pages/product-information/index.tsx b/pages/product-information/index.tsx index 2a7079ca..3886c89b 100644 --- a/pages/product-information/index.tsx +++ b/pages/product-information/index.tsx @@ -142,7 +142,16 @@ export default function ProductDetails() { ['Size', 'qty', 'value'], ]; - const customerInfoRows = [['Test text display'], ['Another sample line'], ['Customer liked it'], ['Fast delivery'], ['Will buy again']]; + const customerInfoRows = [ + ['Customer Instructions'], + ['Product Instruction'], + ['Stamping'], + ['Size'], + ['Special Remark'], + ['Sub Remark'], + ['Delivery Date'], + ['Payment Terms'], + ]; return (
@@ -194,19 +203,33 @@ export default function ProductDetails() {
@@ -221,6 +244,13 @@ export default function ProductDetails() { key={i} className={`btn btn-sm me-2 ${productInformationStyle['metal-btn']} ${selectedPurity === k ? 'btn-secondary' : 'btn-outline-secondary'}`} onClick={() => setSelectedPurity(k)} + style={{ + backgroundColor: selectedPurity === k ? '#f5f5f5' : 'transparent', + color: selectedPurity === k ? '#000' : '#6c757d', + fontWeight: selectedPurity === k ? 'bold' : 'normal', + border: '1px solid #ccc', + borderRadius: '6px', + }} > {k} @@ -234,6 +264,13 @@ export default function ProductDetails() { @@ -265,6 +309,13 @@ export default function ProductDetails() { key={i} className={`btn btn-sm me-2 ${productInformationStyle['metal-btn']} ${selectedSize === size ? 'btn-secondary' : 'btn-outline-secondary'}`} onClick={() => setSelectedSize(size)} + style={{ + backgroundColor: selectedSize === size ? '#f5f5f5' : 'transparent', + color: selectedSize === size ? '#000' : '#6c757d', + fontWeight: selectedSize === size ? 'bold' : 'normal', + border: '1px solid #ccc', + borderRadius: '6px', + }} > {size} @@ -304,7 +355,7 @@ export default function ProductDetails() {
{/* Cart Summary */} -
+
- {/* Metal Details */} - {/* --- Desktop Version: Positioned Summary and Customer Info --- */}
{/* Left: Metal Details */}
-
Metal Details
+
+ Side 1 + +
Metal Details
+
@@ -342,14 +400,24 @@ export default function ProductDetails() { maxWidth: '350px', }} > -
+
- + {customerInfoRows.map((item, index) => ( +
+ {item} +
+ ))}
- +
@@ -358,28 +426,60 @@ export default function ProductDetails() { {/* Diamond Details */}
-
Diamond Details
+
+ Side 1 +
Diamond Details
+
{/* Color Stone Details */}
-
Color Stone Details
+
+ Side 1 +
Color Stone Details
+
{/* Accessories Details */}
-
Accessories Details
+
+ Side 1 +
Accessories Details
+
{/* Labour Details */}
-
Labour Details
+
+ Side 1 +
Labour Details
+
@@ -389,7 +489,15 @@ export default function ProductDetails() {
- + {customerInfoRows.map((item, index) => ( +
+ {item} +
+ ))}