baby / index.html
davidkkkk's picture
Add 2 files
ba7240b verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Newborn Baby Shopping List</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&family=Playfair+Display:wght@400;500;600;700&display=swap');
body {
font-family: 'Poppins', sans-serif;
background-color: #fafafa;
}
.title-font {
font-family: 'Playfair Display', serif;
}
.category-card {
transition: all 0.3s ease;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
}
.category-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 25px rgba(0, 0, 0, 0.1);
}
.checkmark {
display: inline-block;
width: 22px;
height: 22px;
border: 2px solid #e2e8f0;
border-radius: 6px;
position: relative;
cursor: pointer;
transition: all 0.2s ease;
}
.checkmark.checked {
background-color: #10b981;
border-color: #10b981;
}
.checkmark.checked:after {
content: "";
position: absolute;
left: 6px;
top: 2px;
width: 5px;
height: 10px;
border: solid white;
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
.progress-bar {
height: 10px;
border-radius: 10px;
background-color: #e2e8f0;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
}
.progress-fill {
height: 100%;
border-radius: 10px;
background: linear-gradient(90deg, #3b82f6, #8b5cf6);
transition: width 0.5s ease;
box-shadow: 0 2px 4px rgba(59, 130, 246, 0.3);
}
.print-area {
background-color: white;
padding: 24px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}
.timeline-item {
position: relative;
padding-left: 32px;
margin-bottom: 24px;
}
.timeline-item:before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 18px;
height: 18px;
border-radius: 50%;
background: linear-gradient(135deg, #8b5cf6, #3b82f6);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.timeline-item:after {
content: '';
position: absolute;
left: 8px;
top: 18px;
width: 2px;
height: 100%;
background-color: #e2e8f0;
}
.timeline-item:last-child:after {
display: none;
}
.category-icon {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
margin-right: 12px;
color: white;
}
.input-focus {
transition: all 0.3s ease;
}
.input-focus:focus {
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.2);
}
.floating-btn {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
}
.floating-btn:hover {
transform: translateY(-2px);
box-shadow: 0 15px 20px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.suggestion-card {
transition: all 0.3s ease;
border: 1px solid #e2e8f0;
}
.suggestion-card:hover {
transform: translateY(-3px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
border-color: #8b5cf6;
}
.gradient-text {
background: linear-gradient(90deg, #3b82f6, #8b5cf6);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.custom-number-input::-webkit-inner-spin-button,
.custom-number-input::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
.custom-number-input {
-moz-appearance: textfield;
}
.animate-pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% {
opacity: 0.6;
}
50% {
opacity: 1;
}
100% {
opacity: 0.6;
}
}
.tooltip {
position: relative;
}
.tooltip .tooltip-text {
visibility: hidden;
width: 120px;
background-color: #333;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -60px;
opacity: 0;
transition: opacity 0.3s;
}
.tooltip .tooltip-text::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #333 transparent transparent transparent;
}
.tooltip:hover .tooltip-text {
visibility: visible;
opacity: 1;
}
</style>
</head>
<body class="min-h-screen bg-gray-50">
<!-- Header with decorative elements -->
<div class="relative overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-r from-blue-100 to-purple-100 opacity-20"></div>
<div class="container mx-auto px-4 py-12 relative">
<div class="text-center mb-8">
<h1 class="title-font text-5xl font-bold text-gray-900 mb-4">Newborn Baby Shopping List</h1>
<p class="text-lg text-gray-600 max-w-3xl mx-auto">
Prepare everything you need for your little one's arrival with our comprehensive checklist
</p>
</div>
<!-- Progress Section with animated elements -->
<div class="bg-white rounded-xl shadow-lg p-8 mb-8 relative overflow-hidden">
<div class="absolute top-0 right-0 w-32 h-32 bg-blue-50 rounded-full -mr-10 -mt-10"></div>
<div class="absolute bottom-0 left-0 w-24 h-24 bg-purple-50 rounded-full -ml-8 -mb-8"></div>
<div class="relative z-10">
<div class="flex justify-between items-center mb-4">
<h2 class="text-2xl font-semibold text-gray-800">Your Preparation Progress</h2>
<span class="text-2xl font-bold gradient-text" id="progress-percentage">0%</span>
</div>
<div class="progress-bar mb-6">
<div class="progress-fill" id="progress-fill" style="width: 0%"></div>
</div>
<div class="flex justify-between text-sm text-gray-600">
<span id="items-completed">0 items completed</span>
<span id="items-total">0 total items</span>
</div>
</div>
</div>
</div>
</div>
<!-- Main Content -->
<div class="container mx-auto px-4 pb-16">
<div class="flex flex-col lg:flex-row gap-8">
<!-- Categories Navigation -->
<div class="lg:w-1/4">
<div class="bg-white rounded-xl shadow-lg p-6 sticky top-4">
<h2 class="text-xl font-semibold text-gray-800 mb-6 flex items-center">
<i class="fas fa-list-check mr-3 text-purple-500"></i>
Categories
</h2>
<ul class="space-y-2">
<li>
<button onclick="showCategory('nursery')" class="category-btn w-full text-left px-4 py-3 rounded-lg hover:bg-blue-50 hover:text-blue-600 transition flex items-center active-category" data-category="nursery">
<div class="category-icon bg-blue-500">
<i class="fas fa-baby-carriage"></i>
</div>
Nursery
</button>
</li>
<li>
<button onclick="showCategory('clothing')" class="category-btn w-full text-left px-4 py-3 rounded-lg hover:bg-pink-50 hover:text-pink-600 transition flex items-center" data-category="clothing">
<div class="category-icon bg-pink-500">
<i class="fas fa-tshirt"></i>
</div>
Clothing
</button>
</li>
<li>
<button onclick="showCategory('feeding')" class="category-btn w-full text-left px-4 py-3 rounded-lg hover:bg-yellow-50 hover:text-yellow-600 transition flex items-center" data-category="feeding">
<div class="category-icon bg-yellow-500">
<i class="fas fa-bottle-water"></i>
</div>
Feeding
</button>
</li>
<li>
<button onclick="showCategory('diapering')" class="category-btn w-full text-left px-4 py-3 rounded-lg hover:bg-green-50 hover:text-green-600 transition flex items-center" data-category="diapering">
<div class="category-icon bg-green-500">
<i class="fas fa-baby"></i>
</div>
Diapering
</button>
</li>
<li>
<button onclick="showCategory('bathing')" class="category-btn w-full text-left px-4 py-3 rounded-lg hover:bg-indigo-50 hover:text-indigo-600 transition flex items-center" data-category="bathing">
<div class="category-icon bg-indigo-500">
<i class="fas fa-bath"></i>
</div>
Bathing
</button>
</li>
<li>
<button onclick="showCategory('health')" class="category-btn w-full text-left px-4 py-3 rounded-lg hover:bg-red-50 hover:text-red-600 transition flex items-center" data-category="health">
<div class="category-icon bg-red-500">
<i class="fas fa-first-aid"></i>
</div>
Health & Safety
</button>
</li>
<li>
<button onclick="showCategory('travel')" class="category-btn w-full text-left px-4 py-3 rounded-lg hover:bg-purple-50 hover:text-purple-600 transition flex items-center" data-category="travel">
<div class="category-icon bg-purple-500">
<i class="fas fa-car"></i>
</div>
Travel
</button>
</li>
</ul>
<div class="mt-10">
<h3 class="text-lg font-medium text-gray-800 mb-4 flex items-center">
<i class="fas fa-calendar-alt mr-3 text-purple-500"></i>
Preparation Timeline
</h3>
<div class="timeline pl-2">
<div class="timeline-item">
<h4 class="font-medium text-gray-800">3 Months Before</h4>
<p class="text-sm text-gray-600">Start researching and budgeting</p>
</div>
<div class="timeline-item">
<h4 class="font-medium text-gray-800">2 Months Before</h4>
<p class="text-sm text-gray-600">Purchase nursery furniture</p>
</div>
<div class="timeline-item">
<h4 class="font-medium text-gray-800">1 Month Before</h4>
<p class="text-sm text-gray-600">Buy essential clothing and diapers</p>
</div>
<div class="timeline-item">
<h4 class="font-medium text-gray-800">2 Weeks Before</h4>
<p class="text-sm text-gray-600">Pack hospital bag</p>
</div>
</div>
</div>
</div>
</div>
<!-- Items List -->
<div class="lg:w-3/4">
<div class="bg-white rounded-xl shadow-lg p-8 mb-8">
<div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-8 gap-4">
<div>
<h2 class="text-3xl font-semibold text-gray-800" id="current-category">Nursery Items</h2>
<p class="text-gray-500 mt-1" id="category-description">Essential items for your baby's nursery</p>
</div>
<div class="flex gap-3">
<button onclick="printList()" class="bg-gradient-to-r from-blue-500 to-purple-600 hover:from-blue-600 hover:to-purple-700 text-white px-5 py-2.5 rounded-lg flex items-center floating-btn">
<i class="fas fa-print mr-2"></i> Print List
</button>
<button onclick="saveList()" class="bg-white border border-gray-200 hover:bg-gray-50 text-gray-800 px-5 py-2.5 rounded-lg flex items-center floating-btn">
<i class="fas fa-save mr-2"></i> Save
</button>
</div>
</div>
<!-- Search and Filter -->
<div class="mb-8">
<div class="flex flex-col md:flex-row gap-4">
<div class="relative flex-grow">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i class="fas fa-search text-gray-400"></i>
</div>
<input type="text" id="search-items" placeholder="Search items..." class="w-full pl-10 pr-4 py-3 border border-gray-200 rounded-lg input-focus focus:ring-0 focus:border-purple-500">
</div>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i class="fas fa-filter text-gray-400"></i>
</div>
<select id="filter-timing" class="border border-gray-200 rounded-lg px-10 py-3 input-focus focus:ring-0 focus:border-purple-500 appearance-none">
<option value="all">All Items</option>
<option value="before">Before Hospital</option>
<option value="after">After Hospital</option>
</select>
<div class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
<i class="fas fa-chevron-down text-gray-400"></i>
</div>
</div>
</div>
</div>
<!-- Items Container -->
<div class="print-area" id="items-container">
<!-- Items will be loaded here dynamically -->
</div>
<!-- Suggestions -->
<div class="mt-12">
<div class="flex justify-between items-center mb-6">
<h3 class="text-2xl font-semibold text-gray-800">Suggested Items</h3>
<div class="text-sm text-gray-500">Based on popular choices</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" id="suggestions-container">
<!-- Suggestions will be loaded here dynamically -->
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Floating Add Button -->
<button onclick="addCustomItem()" class="fixed bottom-8 right-8 w-14 h-14 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-full flex items-center justify-center shadow-xl floating-btn animate-pulse">
<i class="fas fa-plus text-xl"></i>
</button>
<script>
// Initialize the shopping list data
const shoppingList = {
nursery: [
{ name: "Crib or bassinet", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Mattress", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Mattress pad", quantity: 1, purchased: false, timing: "before", priority: "medium" },
{ name: "Crib sheets (2-3)", quantity: 3, purchased: false, timing: "before", priority: "high" },
{ name: "Waterproof mattress cover", quantity: 1, purchased: false, timing: "before", priority: "medium" },
{ name: "Rocking chair or glider", quantity: 1, purchased: false, timing: "before", priority: "medium" },
{ name: "Dresser or changing table", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Night light", quantity: 1, purchased: false, timing: "before", priority: "low" },
{ name: "Baby monitor", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Humidifier", quantity: 1, purchased: false, timing: "before", priority: "medium" }
],
clothing: [
{ name: "Onesies (5-7)", quantity: 7, purchased: false, timing: "before", priority: "high" },
{ name: "Sleepers (3-5)", quantity: 5, purchased: false, timing: "before", priority: "high" },
{ name: "Socks or booties (5-7 pairs)", quantity: 7, purchased: false, timing: "before", priority: "high" },
{ name: "Hats (2-3)", quantity: 3, purchased: false, timing: "before", priority: "high" },
{ name: "Mittens (to prevent scratching)", quantity: 2, purchased: false, timing: "before", priority: "medium" },
{ name: "Swaddle blankets (3-5)", quantity: 5, purchased: false, timing: "before", priority: "high" },
{ name: "Receiving blankets (5-7)", quantity: 7, purchased: false, timing: "before", priority: "medium" },
{ name: "Outfits for going home (2)", quantity: 2, purchased: false, timing: "before", priority: "high" }
],
feeding: [
{ name: "Breast pump (if breastfeeding)", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Nursing bras (3-4)", quantity: 4, purchased: false, timing: "before", priority: "high" },
{ name: "Nursing pads", quantity: 1, purchased: false, timing: "before", priority: "medium" },
{ name: "Nipple cream", quantity: 1, purchased: false, timing: "before", priority: "medium" },
{ name: "Bottles (6-8)", quantity: 8, purchased: false, timing: "before", priority: "high" },
{ name: "Bottle brush", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Formula (if not breastfeeding)", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Burp cloths (5-7)", quantity: 7, purchased: false, timing: "before", priority: "high" },
{ name: "Bibs (5-7)", quantity: 7, purchased: false, timing: "before", priority: "medium" }
],
diapering: [
{ name: "Diapers (newborn size, 1-2 packs)", quantity: 2, purchased: false, timing: "before", priority: "high" },
{ name: "Diaper pail", quantity: 1, purchased: false, timing: "before", priority: "medium" },
{ name: "Diaper bag", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Diaper rash cream", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Baby wipes (2-3 packs)", quantity: 3, purchased: false, timing: "before", priority: "high" },
{ name: "Changing pad", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Changing pad covers (2-3)", quantity: 3, purchased: false, timing: "before", priority: "medium" }
],
bathing: [
{ name: "Baby bathtub", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Baby shampoo & body wash", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Baby lotion", quantity: 1, purchased: false, timing: "before", priority: "medium" },
{ name: "Hooded towels (2-3)", quantity: 3, purchased: false, timing: "before", priority: "medium" },
{ name: "Washcloths (5-7)", quantity: 7, purchased: false, timing: "before", priority: "medium" },
{ name: "Soft-bristled hair brush", quantity: 1, purchased: false, timing: "before", priority: "low" },
{ name: "Nail clippers or file", quantity: 1, purchased: false, timing: "before", priority: "high" }
],
health: [
{ name: "Digital thermometer", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Nasal aspirator", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Baby-safe nail scissors", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Medicine dropper", quantity: 1, purchased: false, timing: "before", priority: "medium" },
{ name: "Infant acetaminophen", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Baby sunscreen (for after 6 months)", quantity: 1, purchased: false, timing: "after", priority: "low" },
{ name: "First aid kit", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Outlet covers", quantity: 10, purchased: false, timing: "before", priority: "high" },
{ name: "Cabinet locks", quantity: 4, purchased: false, timing: "before", priority: "high" }
],
travel: [
{ name: "Infant car seat", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Stroller", quantity: 1, purchased: false, timing: "before", priority: "high" },
{ name: "Baby carrier or wrap", quantity: 1, purchased: false, timing: "before", priority: "medium" },
{ name: "Car seat cover (for cold weather)", quantity: 1, purchased: false, timing: "before", priority: "low" },
{ name: "Stroller blanket", quantity: 1, purchased: false, timing: "before", priority: "medium" },
{ name: "Car window shades", quantity: 2, purchased: false, timing: "after", priority: "low" }
]
};
// Category descriptions
const categoryDescriptions = {
nursery: "Essential items for your baby's nursery and sleep space",
clothing: "All the clothing essentials for your newborn",
feeding: "Everything you need for feeding your baby",
diapering: "Diapering essentials for your newborn",
bathing: "Items for keeping your baby clean and fresh",
health: "Health and safety items for your baby",
travel: "Items for traveling with your newborn"
};
// Suggested items (based on popular choices)
const suggestedItems = [
{ name: "White noise machine", category: "nursery", timing: "before", icon: "fas fa-volume-up", color: "bg-blue-100 text-blue-600" },
{ name: "Diaper genie", category: "diapering", timing: "before", icon: "fas fa-trash-alt", color: "bg-green-100 text-green-600" },
{ name: "Baby swing", category: "nursery", timing: "before", icon: "fas fa-child", color: "bg-blue-100 text-blue-600" },
{ name: "Wipe warmer", category: "diapering", timing: "before", icon: "fas fa-temperature-high", color: "bg-green-100 text-green-600" },
{ name: "Bottle sterilizer", category: "feeding", timing: "before", icon: "fas fa-spray-can", color: "bg-yellow-100 text-yellow-600" },
{ name: "Baby food maker", category: "feeding", timing: "after", icon: "fas fa-blender", color: "bg-yellow-100 text-yellow-600" },
{ name: "Nursing pillow", category: "feeding", timing: "before", icon: "fas fa-pillow", color: "bg-yellow-100 text-yellow-600" },
{ name: "Baby gym", category: "nursery", timing: "before", icon: "fas fa-dumbbell", color: "bg-blue-100 text-blue-600" },
{ name: "Sound machine", category: "nursery", timing: "before", icon: "fas fa-music", color: "bg-blue-100 text-blue-600" }
];
// Current category
let currentCategory = 'nursery';
// Load the shopping list from localStorage if available
function loadShoppingList() {
const savedList = localStorage.getItem('newbornShoppingList');
if (savedList) {
Object.assign(shoppingList, JSON.parse(savedList));
}
}
// Save the shopping list to localStorage
function saveShoppingList() {
localStorage.setItem('newbornShoppingList', JSON.stringify(shoppingList));
showAlert('List saved successfully!', 'success');
}
// Show alert message
function showAlert(message, type) {
const alert = document.createElement('div');
alert.className = `fixed top-4 right-4 px-6 py-4 rounded-lg shadow-lg text-white flex items-center ${
type === 'success' ? 'bg-green-500' : 'bg-red-500'
} animate__animated animate__fadeInDown`;
alert.innerHTML = `
<i class="fas fa-${type === 'success' ? 'check-circle' : 'exclamation-triangle'} mr-3"></i>
<span>${message}</span>
`;
document.body.appendChild(alert);
setTimeout(() => {
alert.classList.add('animate__fadeOutUp');
setTimeout(() => {
alert.remove();
}, 500);
}, 3000);
}
// Toggle item purchased status
function togglePurchased(category, index) {
shoppingList[category][index].purchased = !shoppingList[category][index].purchased;
renderItems(currentCategory);
updateProgress();
saveShoppingList();
}
// Update item quantity
function updateQuantity(category, index, value) {
shoppingList[category][index].quantity = parseInt(value) || 0;
saveShoppingList();
}
// Add custom item
function addCustomItem() {
const itemName = prompt("Enter the name of the item you want to add:");
if (itemName && itemName.trim() !== '') {
shoppingList[currentCategory].push({
name: itemName.trim(),
quantity: 1,
purchased: false,
timing: "before",
priority: "medium"
});
renderItems(currentCategory);
updateProgress();
saveShoppingList();
showAlert(`${itemName.trim()} added to your list!`, 'success');
}
}
// Remove item
function removeItem(category, index) {
if (confirm("Are you sure you want to remove this item?")) {
const removedItem = shoppingList[category][index].name;
shoppingList[category].splice(index, 1);
renderItems(currentCategory);
updateProgress();
saveShoppingList();
showAlert(`${removedItem} removed from your list`, 'success');
}
}
// Show category items
function showCategory(category) {
currentCategory = category;
// Update active category button
document.querySelectorAll('.category-btn').forEach(btn => {
btn.classList.remove('active-category');
btn.classList.remove('bg-blue-50', 'text-blue-600');
btn.classList.remove('bg-pink-50', 'text-pink-600');
btn.classList.remove('bg-yellow-50', 'text-yellow-600');
btn.classList.remove('bg-green-50', 'text-green-600');
btn.classList.remove('bg-indigo-50', 'text-indigo-600');
btn.classList.remove('bg-red-50', 'text-red-600');
btn.classList.remove('bg-purple-50', 'text-purple-600');
});
// Add appropriate color classes based on category
const activeBtn = document.querySelector(`.category-btn[data-category="${category}"]`);
activeBtn.classList.add('active-category');
switch(category) {
case 'nursery': activeBtn.classList.add('bg-blue-50', 'text-blue-600'); break;
case 'clothing': activeBtn.classList.add('bg-pink-50', 'text-pink-600'); break;
case 'feeding': activeBtn.classList.add('bg-yellow-50', 'text-yellow-600'); break;
case 'diapering': activeBtn.classList.add('bg-green-50', 'text-green-600'); break;
case 'bathing': activeBtn.classList.add('bg-indigo-50', 'text-indigo-600'); break;
case 'health': activeBtn.classList.add('bg-red-50', 'text-red-600'); break;
case 'travel': activeBtn.classList.add('bg-purple-50', 'text-purple-600'); break;
}
// Update category title and description
let categoryTitle = '';
switch(category) {
case 'nursery': categoryTitle = 'Nursery Items'; break;
case 'clothing': categoryTitle = 'Clothing Items'; break;
case 'feeding': categoryTitle = 'Feeding Items'; break;
case 'diapering': categoryTitle = 'Diapering Items'; break;
case 'bathing': categoryTitle = 'Bathing Items'; break;
case 'health': categoryTitle = 'Health & Safety Items'; break;
case 'travel': categoryTitle = 'Travel Items'; break;
}
document.getElementById('current-category').textContent = categoryTitle;
document.getElementById('category-description').textContent = categoryDescriptions[category];
renderItems(category);
renderSuggestions();
}
// Render items for a category
function renderItems(category) {
const container = document.getElementById('items-container');
const filterTiming = document.getElementById('filter-timing').value;
const searchQuery = document.getElementById('search-items').value.toLowerCase();
let itemsHTML = `
<div class="mb-8">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-medium text-gray-800">${category.charAt(0).toUpperCase() + category.slice(1)} Checklist</h3>
<span class="text-sm text-gray-500">${shoppingList[category].length} items</span>
</div>
<div class="overflow-hidden rounded-lg border border-gray-200">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Item</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Quantity</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Timing</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Priority</th>
<th scope="col" class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Action</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
`;
const filteredItems = shoppingList[category].filter(item => {
const matchesSearch = item.name.toLowerCase().includes(searchQuery);
const matchesTiming = filterTiming === 'all' || item.timing === filterTiming;
return matchesSearch && matchesTiming;
});
if (filteredItems.length === 0) {
itemsHTML += `
<tr>
<td colspan="6" class="px-6 py-4 text-center text-gray-500">No items found</td>
</tr>
`;
} else {
filteredItems.forEach((item, index) => {
// Determine priority color
let priorityColor = '';
let priorityText = '';
switch(item.priority) {
case 'high':
priorityColor = 'bg-red-100 text-red-800';
priorityText = 'High';
break;
case 'medium':
priorityColor = 'bg-yellow-100 text-yellow-800';
priorityText = 'Medium';
break;
case 'low':
priorityColor = 'bg-green-100 text-green-800';
priorityText = 'Low';
break;
}
itemsHTML += `
<tr class="${item.purchased ? 'bg-gray-50' : ''}">
<td class="px-6 py-4 whitespace-nowrap">
<span onclick="togglePurchased('${category}', ${index})" class="checkmark ${item.purchased ? 'checked' : ''}"></span>
</td>
<td class="px-6 py-4">
<div class="flex items-center">
<div class="text-sm font-medium ${item.purchased ? 'text-gray-400 line-through' : 'text-gray-900'}">${item.name}</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<input type="number" min="1" value="${item.quantity}"
onchange="updateQuantity('${category}', ${index}, this.value)"
class="w-16 px-2 py-1 border border-gray-200 rounded focus:ring-0 focus:border-purple-500 custom-number-input">
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 py-1 text-xs rounded-full ${item.timing === 'before' ? 'bg-blue-100 text-blue-800' : 'bg-purple-100 text-purple-800'}">
${item.timing === 'before' ? 'Before' : 'After'}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 py-1 text-xs rounded-full ${priorityColor}">
${priorityText}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button onclick="removeItem('${category}', ${index})" class="text-red-600 hover:text-red-900">
<i class="fas fa-trash-alt"></i>
</button>
</td>
</tr>
`;
});
}
itemsHTML += `
</tbody>
</table>
</div>
</div>
<button onclick="addCustomItem()" class="w-full bg-gray-50 hover:bg-gray-100 border-2 border-dashed border-gray-300 text-gray-600 px-4 py-6 rounded-lg flex flex-col items-center transition">
<i class="fas fa-plus-circle text-2xl mb-2"></i>
<span>Add Custom Item</span>
</button>
`;
container.innerHTML = itemsHTML;
}
// Render suggested items
function renderSuggestions() {
const container = document.getElementById('suggestions-container');
let suggestionsHTML = '';
// Filter suggestions for current category
const categorySuggestions = suggestedItems.filter(item => item.category === currentCategory);
if (categorySuggestions.length === 0) {
suggestionsHTML = `
<div class="col-span-3 text-center py-8">
<i class="fas fa-lightbulb text-3xl text-yellow-400 mb-3"></i>
<p class="text-gray-500">No suggestions for this category</p>
</div>
`;
} else {
categorySuggestions.forEach((item, index) => {
suggestionsHTML += `
<div class="suggestion-card bg-white rounded-lg p-5 flex flex-col">
<div class="flex items-center mb-3">
<div class="${item.color} w-10 h-10 rounded-full flex items-center justify-center mr-3">
<i class="${item.icon}"></i>
</div>
<h4 class="font-medium text-gray-800">${item.name}</h4>
</div>
<div class="mt-auto flex justify-between items-center">
<span class="text-xs px-2 py-1 rounded-full ${item.timing === 'before' ? 'bg-blue-100 text-blue-800' : 'bg-purple-100 text-purple-800'}">
${item.timing === 'before' ? 'Before hospital' : 'After hospital'}
</span>
<button onclick="addSuggestedItem(${index})" class="text-sm bg-white border border-purple-200 hover:bg-purple-50 text-purple-600 px-3 py-1 rounded-lg flex items-center">
<i class="fas fa-plus mr-1"></i> Add
</button>
</div>
</div>
`;
});
}
container.innerHTML = suggestionsHTML;
}
// Add suggested item to the list
function addSuggestedItem(index) {
const item = suggestedItems[index];
shoppingList[item.category].push({
name: item.name,
quantity: 1,
purchased: false,
timing: item.timing,
priority: "medium"
});
renderItems(currentCategory);
updateProgress();
saveShoppingList();
showAlert(`${item.name} added to your list!`, 'success');
}
// Update progress bar
function updateProgress() {
let totalItems = 0;
let completedItems = 0;
// Calculate totals across all categories
Object.values(shoppingList).forEach(category => {
category.forEach(item => {
totalItems++;
if (item.purchased) completedItems++;
});
});
const percentage = totalItems > 0 ? Math.round((completedItems / totalItems) * 100) : 0;
document.getElementById('progress-percentage').textContent = `${percentage}%`;
document.getElementById('progress-fill').style.width = `${percentage}%`;
document.getElementById('items-completed').textContent = `${completedItems} items completed`;
document.getElementById('items-total').textContent = `${totalItems} total items`;
}
// Print the list as PDF
function printList() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
// Add title
doc.setFontSize(24);
doc.setTextColor(59, 130, 246);
doc.text('Newborn Baby Shopping List', 105, 20, { align: 'center' });
// Add subtitle
doc.setFontSize(14);
doc.setTextColor(100, 116, 139);
doc.text('Everything you need for your little one', 105, 30, { align: 'center' });
// Add date
doc.setFontSize(10);
doc.setTextColor(100, 116, 139);
doc.text(`Generated on: ${new Date().toLocaleDateString()}`, 105, 38, { align: 'center' });
// Add progress
const progress = document.getElementById('progress-percentage').textContent;
doc.setTextColor(59, 130, 246);
doc.text(`Preparation Progress: ${progress}`, 105, 46, { align: 'center' });
let yPosition = 60;
// Add items by category
Object.entries(shoppingList).forEach(([category, items]) => {
if (items.length > 0) {
// Category header
doc.setFontSize(16);
doc.setTextColor(15, 23, 42);
doc.text(category.charAt(0).toUpperCase() + category.slice(1) + ':', 15, yPosition);
yPosition += 8;
// Add line
doc.setDrawColor(226, 232, 240);
doc.setLineWidth(0.5);
doc.line(15, yPosition, 195, yPosition);
yPosition += 5;
// Items
doc.setFontSize(12);
items.forEach(item => {
if (yPosition > 280) {
doc.addPage();
yPosition = 20;
}
doc.setTextColor(item.purchased ? 148, 163, 184 : 15, 23, 42);
const status = item.purchased ? '✓ Purchased' : '○ Needed';
// Item name and status
doc.text(`- ${item.name}`, 20, yPosition);
doc.text(status, 180, yPosition, { align: 'right' });
yPosition += 5;
// Quantity and timing
doc.text(` Qty: ${item.quantity} | Timing: ${item.timing === 'before' ? 'Before hospital' : 'After hospital'}`, 20, yPosition);
yPosition += 5;
// Priority
doc.text(` Priority: ${item.priority}`, 20, yPosition);
yPosition += 8;
});
yPosition += 5;
}
});
// Add footer
doc.setFontSize(10);
doc.setTextColor(100, 116, 139);
doc.text('Generated by Newborn Baby Shopping List - www.babyshoppinglist.com', 105, 290, { align: 'center' });
// Save the PDF
doc.save('newborn-shopping-list.pdf');
}
// Save the list
function saveList() {
saveShoppingList();
}
// Initialize the page
document.addEventListener('DOMContentLoaded', () => {
loadShoppingList();
showCategory('nursery');
updateProgress();
// Add event listeners for search and filter
document.getElementById('search-items').addEventListener('input', () => {
renderItems(currentCategory);
});
document.getElementById('filter-timing').addEventListener('change', () => {
renderItems(currentCategory);
});
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=davidkkkk/baby" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>