Skip to content
Open
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
147 changes: 126 additions & 21 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,137 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Crochet Bags - Handmade with Love</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;600;700&family=Poppins:wght@300;400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Coffee!</h1>
<header class="hero">
<nav class="navbar">
<div class="container">
<h1 class="logo">Crochet Bags</h1>
<ul class="nav-links">
<li><a href="#home">Home</a></li>
<li><a href="#collection">Collection</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</div>
</nav>
<div class="hero-content">
<h2 class="hero-title">Handcrafted Crochet Bags</h2>
<p class="hero-subtitle">Unique, sustainable, and made with love</p>
<a href="#collection" class="cta-button">Explore Collection</a>
</div>
</header>

<form>
<label for="roast-selection"></label>
<select id="roast-selection">
<option>light</option>
<option>medium</option>
<option>dark</option>
</select>
<input id="submit" type="submit" />
</form>
<section class="features">
<div class="container">
<div class="feature-grid">
<div class="feature-card">
<div class="feature-icon">🧶</div>
<h3>Handmade</h3>
<p>Each bag is carefully crafted by hand with attention to every detail</p>
</div>
<div class="feature-card">
<div class="feature-icon">🌿</div>
<h3>Sustainable</h3>
<p>Made with eco-friendly materials and sustainable practices</p>
</div>
<div class="feature-card">
<div class="feature-icon">✨</div>
<h3>Unique</h3>
<p>No two bags are exactly alike - each piece is one of a kind</p>
</div>
</div>
</div>
</section>

<table>
<thead>
<tr>
<th>ID</th>
<th>NAME</th>
<th>ROAST</th>
</tr>
</thead>
<tbody id="coffees"></tbody>
</table>
<section id="collection" class="collection">
<div class="container">
<h2 class="section-title">Our Collection</h2>
<p class="section-subtitle">Browse our beautiful selection of crochet bags</p>

<div class="filter-section">
<label for="style-filter">Filter by Style:</label>
<select id="style-filter">
<option value="all">All Styles</option>
<option value="tote">Tote Bags</option>
<option value="crossbody">Crossbody</option>
<option value="clutch">Clutch</option>
<option value="bucket">Bucket Bags</option>
</select>
</div>

<div class="bags-grid" id="bags-container">
<!-- Bags will be rendered here by JavaScript -->
</div>
</div>
</section>

<section id="about" class="about">
<div class="container">
<div class="about-content">
<div class="about-text">
<h2 class="section-title">About Our Craft</h2>
<p>Crochet bags combine traditional craftsmanship with modern design. Each bag is meticulously handcrafted using premium yarns and time-honored crochet techniques passed down through generations.</p>
<p>Our bags are not just accessories - they're wearable art pieces that tell a story of patience, skill, and dedication. From casual totes perfect for everyday use to elegant clutches for special occasions, each piece is designed to be both beautiful and functional.</p>
<div class="about-stats">
<div class="stat">
<h3>500+</h3>
<p>Bags Created</p>
</div>
<div class="stat">
<h3>100%</h3>
<p>Handmade</p>
</div>
<div class="stat">
<h3>50+</h3>
<p>Unique Designs</p>
</div>
</div>
</div>
<div class="about-image">
<div class="image-placeholder">
<span>🧺</span>
</div>
</div>
</div>
</div>
</section>

<section id="contact" class="contact">
<div class="container">
<h2 class="section-title">Get in Touch</h2>
<p class="section-subtitle">Have questions or want a custom bag? We'd love to hear from you!</p>
<form class="contact-form">
<div class="form-group">
<input type="text" placeholder="Your Name" required>
</div>
<div class="form-group">
<input type="email" placeholder="Your Email" required>
</div>
<div class="form-group">
<textarea placeholder="Your Message" rows="5" required></textarea>
</div>
<button type="submit" class="submit-button">Send Message</button>
</form>
</div>
</section>

<footer class="footer">
<div class="container">
<p>&copy; 2025 Crochet Bags. Handmade with love.</p>
<div class="social-links">
<a href="#" aria-label="Instagram">Instagram</a>
<a href="#" aria-label="Pinterest">Pinterest</a>
<a href="#" aria-label="Etsy">Etsy</a>
</div>
</div>
</footer>

<script src="main.js"></script>
</body>
Expand Down
203 changes: 159 additions & 44 deletions main.js
Original file line number Diff line number Diff line change
@@ -1,57 +1,172 @@
"use strict"

function renderCoffee(coffee) {
let html = '<tr class="coffee">';
html += `<td>${coffee.id}</td>`;
html += `<td>${coffee.name}</td>`;
html += `<td>${coffee.roast}</td>`;
html += '</tr>';

return html;
const crochetBags = [
{
id: 1,
name: 'Summer Breeze Tote',
style: 'tote',
description: 'Perfect for beach days and farmers markets. Spacious and durable with comfortable handles.',
icon: '👜'
},
{
id: 2,
name: 'Bohemian Crossbody',
style: 'crossbody',
description: 'Hands-free convenience with a boho-chic style. Features adjustable strap and secure closure.',
icon: '👝'
},
{
id: 3,
name: 'Evening Elegance Clutch',
style: 'clutch',
description: 'Sophisticated design for special occasions. Compact yet spacious enough for essentials.',
icon: '💼'
},
{
id: 4,
name: 'Rustic Bucket Bag',
style: 'bucket',
description: 'Trendy bucket shape with drawstring closure. Perfect for everyday adventures.',
icon: '🧺'
},
{
id: 5,
name: 'Market Day Tote',
style: 'tote',
description: 'Extra large capacity for all your shopping needs. Reinforced bottom and sturdy construction.',
icon: '🛍️'
},
{
id: 6,
name: 'Vintage Crossbody',
style: 'crossbody',
description: 'Classic design with modern functionality. Features multiple pockets for organization.',
icon: '👜'
},
{
id: 7,
name: 'Pearl Clutch',
style: 'clutch',
description: 'Adorned with delicate pearl accents. Perfect for weddings and formal events.',
icon: '💎'
},
{
id: 8,
name: 'Festival Bucket',
style: 'bucket',
description: 'Colorful and fun design ideal for music festivals. Lightweight and easy to carry.',
icon: '🎨'
},
{
id: 9,
name: 'Coastal Tote',
style: 'tote',
description: 'Inspired by ocean waves with blue and white patterns. Water-resistant lining available.',
icon: '🌊'
},
{
id: 10,
name: 'Mini Crossbody',
style: 'crossbody',
description: 'Compact and cute for carrying just the essentials. Perfect for concerts and nights out.',
icon: '✨'
},
{
id: 11,
name: 'Metallic Clutch',
style: 'clutch',
description: 'Shimmering metallic yarn creates a stunning effect. Statement piece for any outfit.',
icon: '⭐'
},
{
id: 12,
name: 'Garden Bucket',
style: 'bucket',
description: 'Floral-inspired design with nature motifs. Eco-friendly and sustainable materials.',
icon: '🌸'
}
];

function renderBag(bag) {
return `
<div class="bag-card" data-style="${bag.style}">
<div class="bag-image">
<span>${bag.icon}</span>
</div>
<div class="bag-info">
<h3 class="bag-name">${bag.name}</h3>
<span class="bag-style">${bag.style.charAt(0).toUpperCase() + bag.style.slice(1)}</span>
<p class="bag-description">${bag.description}</p>
</div>
</div>
`;
}

function renderCoffees(coffees) {
let html = '';
for(let i = coffees.length - 1; i >= 0; i--) {
html += renderCoffee(coffees[i]);
function renderBags(bags) {
return bags.map(bag => renderBag(bag)).join('');
}

function filterBags() {
const selectedStyle = styleFilter.value;
const bagsContainer = document.getElementById('bags-container');

if (selectedStyle === 'all') {
bagsContainer.innerHTML = renderBags(crochetBags);
} else {
const filteredBags = crochetBags.filter(bag => bag.style === selectedStyle);
bagsContainer.innerHTML = renderBags(filteredBags);
}
return html;

const bagCards = document.querySelectorAll('.bag-card');
bagCards.forEach((card, index) => {
card.style.animation = `fadeIn 0.5s ease ${index * 0.1}s backwards`;
});
}

function updateCoffees(e) {
e.preventDefault(); // don't submit the form, we just want to update the data
const selectedRoast = roastSelection.value;
const filteredCoffees = [];
coffees.forEach( coffee => {
if (coffee.roast === selectedRoast) {
filteredCoffees.push(coffee);
const styleFilter = document.getElementById('style-filter');
const bagsContainer = document.getElementById('bags-container');

bagsContainer.innerHTML = renderBags(crochetBags);

styleFilter.addEventListener('change', filterBags);

document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
tbody.innerHTML = renderCoffees(filteredCoffees);
}
});

// from http://www.ncausa.org/About-Coffee/Coffee-Roasts-Guide
const coffees = [
{id: 1, name: 'Light City', roast: 'light'},
{id: 2, name: 'Half City', roast: 'light'},
{id: 3, name: 'Cinnamon', roast: 'light'},
{id: 4, name: 'City', roast: 'medium'},
{id: 5, name: 'American', roast: 'medium'},
{id: 6, name: 'Breakfast', roast: 'medium'},
{id: 7, name: 'High', roast: 'dark'},
{id: 8, name: 'Continental', roast: 'dark'},
{id: 9, name: 'New Orleans', roast: 'dark'},
{id: 10, name: 'European', roast: 'dark'},
{id: 11, name: 'Espresso', roast: 'dark'},
{id: 12, name: 'Viennese', roast: 'dark'},
{id: 13, name: 'Italian', roast: 'dark'},
{id: 14, name: 'French', roast: 'dark'},
];
const contactForm = document.querySelector('.contact-form');
contactForm.addEventListener('submit', function(e) {
e.preventDefault();
alert('Thank you for your message! We\'ll get back to you soon.');
contactForm.reset();
});

const tbody = document.querySelector('#coffees');
const submitButton = document.querySelector('#submit');
const roastSelection = document.querySelector('#roast-selection');
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};

tbody.innerHTML = renderCoffees(coffees);
const observer = new IntersectionObserver(function(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);

submitButton.addEventListener('click', updateCoffees);
document.querySelectorAll('.feature-card, .bag-card').forEach(el => {
el.style.opacity = '0';
el.style.transform = 'translateY(20px)';
el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
observer.observe(el);
});
Loading