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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ module.exports = {
version: 'detect',
},
},
};
};
3 changes: 0 additions & 3 deletions .github/ISSUE_TEMPLATE/custom.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,4 @@ about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''

---


1 change: 0 additions & 1 deletion .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
Expand Down
2 changes: 1 addition & 1 deletion .markdownlint.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
"MD013": false,
"MD033": false,
"MD041": false
}
}
2 changes: 2 additions & 0 deletions docs/Adding_favicon.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
## Steps to Add a New Favicon

1. **Prepare the Favicon File:**

- Create an SVG (preferred) or PNG file for the favicon.
- Ensure the favicon design aligns with the existing ones.

2. **Place the Favicon in the Correct Directory:**

- Move the favicon file to the `public/favicons/` folder.

3. **Update the Favicon List:**
Expand Down
60 changes: 30 additions & 30 deletions docs/dev_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@

2. Clone your forked copy of the project;

```bash
git clone https://github.com/<your_user_name>/www-v2.git
```
```bash
git clone https://github.com/<your_user_name>/www-v2.git
```

3. Change to the project directory;

```bash
cd www-v2
```
```bash
cd www-v2
```

## Setup Development Environment

This is a _**TypeScript**_ project that uses _**React**_. You'll just need _[**Node.js**](https://nodejs.org/en) and _**npm**_ installed on your development machine.
This is a _**TypeScript**_ project that uses _**React**_. You'll just need _[**Node.js**](https://nodejs.org/en) and _**npm**\_ installed on your development machine.
Although, this is sufficient to run, build, and test the project as a whole, you might need some
extra tools for other development tasks.

Expand Down Expand Up @@ -55,41 +55,41 @@ After you are set-up, the steps you take depend on what you want to do:

- **Run a development server**

1. To install all the dependencies (in `package.json`), run
1. To install all the dependencies (in `package.json`), run

```bash
npm install
```
```bash
npm install
```

2. Run _React scripts_.
2. Run _React scripts_.

- For unoptimized development serving, run
- For unoptimized development serving, run

```bash
npm run dev
```
```bash
npm run dev
```

Visit `localhost:5173` in a browser to view the web page served.
Visit `localhost:5173` in a browser to view the web page served.

- For generating a generic production build, run
- For generating a generic production build, run

```bash
npm run build
```
```bash
npm run build
```

- For generating a production build under the subdirectory `/www-v2`, run
- For generating a production build under the subdirectory `/www-v2`, run

```bash
npm run build:gh
```
```bash
npm run build:gh
```

- For serving the last production build (`dist` folder), run
- For serving the last production build (`dist` folder), run

```bash
npm run preview
```
```bash
npm run preview
```

Visit `localhost:4173` in a browser to view the web page served.
Visit `localhost:4173` in a browser to view the web page served.

## Editor

Expand Down
12 changes: 6 additions & 6 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';

export default tseslint.config(
{ ignores: ['dist'] },
Expand All @@ -25,4 +25,4 @@ export default tseslint.config(
],
},
},
)
);
Binary file added public/assets/Images/sugarTshirtBlue.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/Images/sugarTshirtGreen.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/Images/sugarTshirtPurple.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/Images/sugarTshirtWhite.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/Images/sugarlabsUsb.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/fonts/Oswald-VariableFont_wght.ttf
Binary file not shown.
122 changes: 122 additions & 0 deletions src/components/Products/ProductDisplay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
'use client';

import { useState } from 'react';
import { ChevronLeft, ChevronRight } from 'lucide-react';

interface ProductDisplayProps {
name: string;
description: string;
images: string[];
buyNowLink: string;
}

const parseMarkdown = (text: string) => {
return text
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?)\*/g, '<em>$1</em>')
.replace(/\n/g, '<br />');
};

export const ProductDisplay = ({
name,
description,
images = [],
buyNowLink,
}: ProductDisplayProps) => {
const [currentIndex, setCurrentIndex] = useState(0);

const nextImage = () => {
if (!images || images.length <= 1) return;
setCurrentIndex((prevIndex) =>
prevIndex === images.length - 1 ? 0 : prevIndex + 1,
);
};

const prevImage = () => {
if (!images || images.length <= 1) return;
setCurrentIndex((prevIndex) =>
prevIndex === 0 ? images.length - 1 : prevIndex - 1,
);
};

return (
<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">
{/* Product Image */}
<div className="w-full md:w-1/2">
<div className="overflow-hidden rounded-2xl border relative">
<img
src={
images && images.length > 0
? images[currentIndex]
: '/placeholder.svg'
}
alt={`${name} - View ${currentIndex + 1}`}
className="object-cover transition-all duration-300"
/>
{images.length > 1 && (
<>
<button
onClick={prevImage}
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"
aria-label="Previous image"
>
<ChevronLeft className="size-4 text-gray-700" />
</button>
<button
onClick={nextImage}
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"
aria-label="Next image"
>
<ChevronRight className="size-4 text-gray-700" />
</button>
</>
)}
{images.length > 1 && (
<div className="absolute bottom-3 left-0 right-0 flex justify-center gap-2 py-2">
{images.map((_, index) => (
<button
key={index}
onClick={() => setCurrentIndex(index)}
className={`w-3 h-3 rounded-full transition-colors border ${
currentIndex === index
? 'bg-black border-black'
: 'bg-white border-gray-700 hover:bg-gray-200'
}`}
aria-label={`View image ${index + 1}`}
/>
))}
</div>
)}
</div>
</div>

{/* Product Details */}
<div className="flex-1 flex flex-col">
<div>
<h1 className="text-2xl sm:text-3xl md:text-4xl font-bold text-gray-900">
{name}
</h1>
<div className="mt-4">
<h2 className="text-md font-medium text-gray-900 text-wrap">
Description
</h2>
<div
className="mt-2 text-gray-600 text-sm sm:text-md overflow-auto prose prose-sm max-w-none"
dangerouslySetInnerHTML={{ __html: parseMarkdown(description) }}
/>
<div className="mt-6">
<a
href={buyNowLink}
target="_blank"
rel="noopener noreferrer"
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"
>
Buy Now
</a>
</div>
</div>
</div>
</div>
</div>
);
};
28 changes: 28 additions & 0 deletions src/constants/Info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import discussImage from '/assets/Images/discuss.jpeg';
import teach2Image from '/assets/Images/teach2.jpeg';
import learnImage from '/assets/Images/learn.jpg';

import merch1 from '/assets/Images/sugarTshirtBlue.jpeg';
import merch2 from '/assets/Images/sugarTshirtWhite.jpeg';
import merch3 from '/assets/Images/sugarTshirtPurple.jpeg';
import flash from '/assets/Images/sugarlabsUsb.jpeg';

export interface ImageConfig {
src: string;
alt: string;
Expand All @@ -15,6 +20,13 @@ interface HeroContent {
description: string;
}

interface ProductContent {
name: string;
description: string;
images: string[];
buyNowLink: string;
}

export const heroContent: HeroContent = {
title: 'SUGAR LABS',
description: `Whether you're a young learner, teacher, or a budding developer,
Expand Down Expand Up @@ -48,3 +60,19 @@ export const images: Record<string, ImageConfig> = {
export const mission = {
learnImage,
};

export const ProductConstants: ProductContent[] = [
{
name: 'Sugarlabs Merch',
description: 'Sweet merch that supports our unique cause.',
images: [merch1, merch2, merch3],
buyNowLink: 'https://www.bonfire.com/sugar-labs-education/',
},
{
name: 'Sugarlabs USB Flash Drive',
description:
'Easily install Fedora Sugar On A Stick (SOAS) to your device directly from this USB flash drive.',
images: [flash],
buyNowLink: 'https://www.usbmemorydirect.com/store/novelty/sugarlabs/',
},
];
Loading
Loading