Skip to content

Commit 1022e27

Browse files
committed
product-page
1 parent 30bc500 commit 1022e27

File tree

4 files changed

+101
-95
lines changed

4 files changed

+101
-95
lines changed
252 KB
Loading

src/components/Products/ProductDisplay.tsx

Lines changed: 71 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -41,85 +41,82 @@ export const ProductDisplay = ({
4141
};
4242

4343
return (
44-
<div className="w-full mx-auto p-4 sm:p-6 max-h-[800px]">
45-
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 md:gap-8 lg:gap-12">
46-
{/* Product Image */}
47-
<div className="relative w-full">
48-
<div className="relative aspect-square overflow-hidden rounded-2xl border">
49-
<img
50-
src={
51-
images && images.length > 0
52-
? images[currentIndex]
53-
: '/placeholder.svg'
54-
}
55-
alt={`${name} - View ${currentIndex + 1}`}
56-
className={`object-cover transition-all duration-300 p-4`}
57-
/>
58-
{images.length > 1 && (
59-
<>
60-
<button
61-
onClick={prevImage}
62-
className="absolute left-3 top-1/2 -translate-y-1/2 bg-white/80 hover:bg-white rounded-full p-1 shadow-md transition-all duration-200"
63-
aria-label="Previous image"
64-
>
65-
<ChevronLeft className="size-4 text-gray-700" />
66-
</button>
44+
<div className="w-full mx-auto p-4 sm:p-6 flex flex-col md:flex-row gap-6 md:gap-8 lg:gap-12">
45+
{/* Product Image */}
46+
<div className="w-full md:w-1/2">
47+
<div className="overflow-hidden rounded-2xl border relative">
48+
<img
49+
src={
50+
images && images.length > 0
51+
? images[currentIndex]
52+
: '/placeholder.svg'
53+
}
54+
alt={`${name} - View ${currentIndex + 1}`}
55+
className="object-cover transition-all duration-300"
56+
/>
57+
{images.length > 1 && (
58+
<>
59+
<button
60+
onClick={prevImage}
61+
className="absolute left-3 top-1/2 -translate-y-1/2 bg-white/80 hover:bg-white rounded-full p-1 shadow-md transition-all duration-200"
62+
aria-label="Previous image"
63+
>
64+
<ChevronLeft className="size-4 text-gray-700" />
65+
</button>
66+
<button
67+
onClick={nextImage}
68+
className="absolute right-3 top-1/2 -translate-y-1/2 bg-white/80 hover:bg-white rounded-full p-1 shadow-md transition-all duration-200"
69+
aria-label="Next image"
70+
>
71+
<ChevronRight className="size-4 text-gray-700" />
72+
</button>
73+
</>
74+
)}
75+
{images.length > 1 && (
76+
<div className="absolute bottom-3 left-0 right-0 flex justify-center gap-2 py-2">
77+
{images.map((_, index) => (
6778
<button
68-
onClick={nextImage}
69-
className="absolute right-3 top-1/2 -translate-y-1/2 bg-white/80 hover:bg-white rounded-full p-1 shadow-md transition-all duration-200"
70-
aria-label="Next image"
71-
>
72-
<ChevronRight className="size-4 text-gray-700" />
73-
</button>
74-
</>
75-
)}
76-
{images.length > 1 && (
77-
<div className="absolute bottom-3 left-0 right-0 flex justify-center gap-2 py-2">
78-
{images.map((_, index) => (
79-
<button
80-
key={index}
81-
onClick={() => setCurrentIndex(index)}
82-
className={`w-3 h-3 rounded-full transition-colors border ${
83-
currentIndex === index
84-
? 'bg-black border-black'
85-
: 'bg-white border-gray-700 hover:bg-gray-200'
86-
}`}
87-
aria-label={`View image ${index + 1}`}
88-
/>
89-
))}
90-
</div>
91-
)}
92-
</div>
79+
key={index}
80+
onClick={() => setCurrentIndex(index)}
81+
className={`w-3 h-3 rounded-full transition-colors border ${
82+
currentIndex === index
83+
? 'bg-black border-black'
84+
: 'bg-white border-gray-700 hover:bg-gray-200'
85+
}`}
86+
aria-label={`View image ${index + 1}`}
87+
/>
88+
))}
89+
</div>
90+
)}
9391
</div>
92+
</div>
9493

95-
{/* Product Details */}
96-
<div className="flex flex-col justify-between h-full">
97-
<div>
98-
<h1 className="text-2xl sm:text-3xl md:text-4xl font-bold text-gray-900">
99-
{name}
100-
</h1>
101-
{/* Description */}
102-
<div className="mt-4">
103-
<h2 className="text-md font-medium text-gray-900 text-wrap">
104-
Description
105-
</h2>
106-
<div
107-
className="mt-2 text-gray-600 text-sm sm:text-md overflow-auto prose prose-sm max-w-none"
108-
dangerouslySetInnerHTML={{ __html: parseMarkdown(description) }}
109-
/>
94+
{/* Product Details */}
95+
{/* Product Details */}
96+
<div className="flex-1 flex flex-col">
97+
<div>
98+
<h1 className="text-2xl sm:text-3xl md:text-4xl font-bold text-gray-900">
99+
{name}
100+
</h1>
101+
<div className="mt-4">
102+
<h2 className="text-md font-medium text-gray-900 text-wrap">
103+
Description
104+
</h2>
105+
<div
106+
className="mt-2 text-gray-600 text-sm sm:text-md overflow-auto prose prose-sm max-w-none"
107+
dangerouslySetInnerHTML={{ __html: parseMarkdown(description) }}
108+
/>
109+
<div className="mt-6">
110+
<a
111+
href={buyNowLink}
112+
target="_blank"
113+
rel="noopener noreferrer"
114+
className="inline-block w-full md:w-[150px] px-6 py-3 text-center text-base font-medium bg-blue-700 text-white rounded-full hover:bg-blue-800 transition-colors shadow-sm hover:shadow-md"
115+
>
116+
Buy Now
117+
</a>
110118
</div>
111119
</div>
112-
{/* Buy Now Button */}
113-
<div className="mt-6 md:mt-8">
114-
<a
115-
href={buyNowLink}
116-
target="_blank"
117-
rel="noopener noreferrer"
118-
className="inline-block w-full md:w-[150px] px-6 py-3 text-center text-base font-medium bg-blue-700 text-white rounded-full hover:bg-blue-800 transition-colors shadow-sm hover:shadow-md"
119-
>
120-
Buy Now
121-
</a>
122-
</div>
123120
</div>
124121
</div>
125122
</div>

src/constants/Info.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import discussImage from '/assets/Images/discuss.jpeg';
44
import teach2Image from '/assets/Images/teach2.jpeg';
55
import learnImage from '/assets/Images/learn.jpg';
66

7+
import merch1 from '/assets/Images/sugarTshirtBlue.jpeg';
8+
import merch2 from '/assets/Images/sugarTshirtWhite.jpeg';
9+
import merch3 from '/assets/Images/sugarTshirtPurple.jpeg';
10+
import flash from '/assets/Images/sugarlabsUsb.jpeg';
11+
712
export interface ImageConfig {
813
src: string;
914
alt: string;
@@ -15,6 +20,13 @@ interface HeroContent {
1520
description: string;
1621
}
1722

23+
interface ProductContent {
24+
name: string;
25+
description: string;
26+
images: string[];
27+
buyNowLink: string;
28+
}
29+
1830
export const heroContent: HeroContent = {
1931
title: 'SUGAR LABS',
2032
description: `Whether you're a young learner, teacher, or a budding developer,
@@ -48,3 +60,19 @@ export const images: Record<string, ImageConfig> = {
4860
export const mission = {
4961
learnImage,
5062
};
63+
64+
export const ProductConstants: ProductContent[] = [
65+
{
66+
name: 'Sugarlabs Merch',
67+
description: 'Sweet merch that supports our unique cause.',
68+
images: [merch1, merch2, merch3],
69+
buyNowLink: 'https://www.bonfire.com/sugar-labs-education/',
70+
},
71+
{
72+
name: 'Sugarlabs USB Flash Drive',
73+
description:
74+
'Easily install Fedora Sugar On A Stick (SOAS) to your device directly from this USB flash drive.',
75+
images: [flash],
76+
buyNowLink: 'https://www.usbmemorydirect.com/store/novelty/sugarlabs/',
77+
},
78+
];

src/pages/Products.tsx

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,7 @@ import { ProductDisplay } from '@/components/Products/ProductDisplay';
22
import Header from '@/sections/Header';
33
import { subtleRise } from '@/styles/Animations';
44
import { motion } from 'framer-motion';
5-
6-
const products = [
7-
{
8-
name: 'Product Name',
9-
description:
10-
'*This is a mock description* Our premium cotton t-shirt offers exceptional comfort and durability. Made from 100% organic cotton, this versatile piece features a classic fit, reinforced seams, and a tagless collar for maximum comfort. Perfect for everyday wear, this t-shirt maintains its shape and softness even after multiple washes.',
11-
images: ['/assets/Images/sugarTshirtBlue.jpeg'],
12-
buyNowLink: 'https://www.bonfire.com/sugar-labs-education/',
13-
},
14-
{
15-
name: 'Product Name',
16-
description:
17-
'*This is a mock description* Our classic hoodie is made from ultra-soft fleece, providing warmth and comfort. Featuring a relaxed fit, a spacious front pocket, and an adjustable drawstring hood, it is perfect for casual outings or lounging at home.',
18-
images: [
19-
'/assets/Images/sugarTshirtWhite.jpeg',
20-
'/assets/Images/sugarTshirtWhite.jpeg',
21-
],
22-
buyNowLink: 'https://www.example.com/classic-hoodie',
23-
},
24-
];
5+
import { ProductConstants } from '@/constants/Info';
256

267
const Products = () => {
278
return (
@@ -39,7 +20,7 @@ const Products = () => {
3920
</h1>
4021
</motion.div>
4122
<div className="flex flex-col items-center w-full">
42-
{products.map((product, index) => (
23+
{ProductConstants.map((product, index) => (
4324
<div key={index} className="w-full max-w-5xl">
4425
<ProductDisplay
4526
name={product.name}

0 commit comments

Comments
 (0)