point-system / index.html
BHelfmann's picture
Now, add a paersistent store behind the points actions. Add and subtract point according to the actions. Suggest a persistent store except cookies and local storage. - Follow Up Deployment
88b650a verified
Raw
History Blame Contribute Delete
42.7 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Family Point System</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">
<style>
.gradient-bg {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
.point-badge {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.chart-container {
height: 300px;
}
.flip-card {
perspective: 1000px;
height: 160px; /* Fixed height for all cards */
margin-bottom: 1rem; /* Ensure spacing between cards */
}
.flip-card-inner {
transition: transform 0.6s;
transform-style: preserve-3d;
position: relative;
width: 100%;
height: 100%;
}
.flip-card:hover .flip-card-inner {
transform: rotateY(180deg);
}
.flip-card-front, .flip-card-back {
backface-visibility: hidden;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
padding: 1rem;
box-sizing: border-box;
}
.flip-card-back {
transform: rotateY(180deg);
}
</style>
</head>
<body class="gradient-bg min-h-screen font-sans">
<div class="container mx-auto px-4 py-8">
<!-- Header -->
<header class="flex justify-between items-center mb-8">
<div>
<h1 class="text-3xl font-bold text-indigo-800">Family Point System</h1>
<p class="text-indigo-600">Teaching responsibility through rewards</p>
</div>
<div class="flex items-center space-x-4">
<div class="relative group">
<button id="parentToggle" class="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition">
<i class="fas fa-user-shield mr-2"></i>Parent Mode
</button>
<div id="parentPanel" class="hidden absolute right-0 mt-2 w-64 bg-white rounded-lg shadow-lg p-4 z-10">
<div class="mb-4">
<label class="block text-gray-700 mb-2">Add Points</label>
<div class="flex">
<select id="childSelect" class="flex-1 border rounded-l-lg px-2 py-1">
<option value="emma">Emma</option>
<option value="liam">Liam</option>
</select>
<input type="number" id="pointAmount" class="w-20 border-t border-b px-2 py-1" placeholder="10">
<button id="addPointsBtn" class="bg-green-500 text-white px-3 py-1 rounded-r-lg hover:bg-green-600">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
<div>
<label class="block text-gray-700 mb-2">New Chore</label>
<div class="flex">
<input type="text" id="newChore" class="flex-1 border rounded-l-lg px-2 py-1" placeholder="Chore name">
<input type="number" id="chorePoints" class="w-20 border-t border-b px-2 py-1" placeholder="Points">
<button id="addChoreBtn" class="bg-blue-500 text-white px-3 py-1 rounded-r-lg hover:bg-blue-600">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow p-2">
<div class="text-sm text-gray-500">Today</div>
<div class="text-lg font-semibold" id="currentDate"></div>
</div>
</div>
</header>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Children Points Summary -->
<div class="bg-white rounded-xl shadow-lg p-6 lg:col-span-1">
<h2 class="text-xl font-bold text-gray-800 mb-4 flex items-center">
<i class="fas fa-child-reaching mr-2 text-indigo-600"></i> Children Points
</h2>
<div class="space-y-4">
<div class="flex items-center justify-between p-3 bg-indigo-50 rounded-lg">
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-pink-200 flex items-center justify-center mr-3">
<i class="fas fa-female text-pink-600"></i>
</div>
<div>
<h3 class="font-semibold">Emma</h3>
<p class="text-xs text-gray-500">Age 9</p>
</div>
</div>
<div class="point-badge bg-pink-100 text-pink-800 px-3 py-1 rounded-full font-bold flex items-center">
<i class="fas fa-coins mr-1"></i>
<span id="emmaPoints">125</span>
</div>
</div>
<div class="flex items-center justify-between p-3 bg-indigo-50 rounded-lg">
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-blue-200 flex items-center justify-center mr-3">
<i class="fas fa-male text-blue-600"></i>
</div>
<div>
<h3 class="font-semibold">Liam</h3>
<p class="text-xs text-gray-500">Age 7</p>
</div>
</div>
<div class="point-badge bg-blue-100 text-blue-800 px-3 py-1 rounded-full font-bold flex items-center">
<i class="fas fa-coins mr-1"></i>
<span id="liamPoints">80</span>
</div>
</div>
</div>
<div class="mt-6">
<h3 class="font-semibold text-gray-700 mb-2">Recent Activity</h3>
<div class="space-y-2 max-h-48 overflow-y-auto">
<div class="flex items-start text-sm p-2 hover:bg-gray-50 rounded">
<div class="w-6 h-6 bg-green-100 text-green-600 rounded-full flex items-center justify-center mr-2 mt-0.5">
<i class="fas fa-plus text-xs"></i>
</div>
<div>
<p>Emma earned 10 points for <span class="font-medium">Setting the table</span></p>
<p class="text-xs text-gray-400">Today, 6:30 PM</p>
</div>
</div>
<div class="flex items-start text-sm p-2 hover:bg-gray-50 rounded">
<div class="w-6 h-6 bg-red-100 text-red-600 rounded-full flex items-center justify-center mr-2 mt-0.5">
<i class="fas fa-minus text-xs"></i>
</div>
<div>
<p>Liam spent 15 points for <span class="font-medium">Video game time</span></p>
<p class="text-xs text-gray-400">Today, 5:15 PM</p>
</div>
</div>
<div class="flex items-start text-sm p-2 hover:bg-gray-50 rounded">
<div class="w-6 h-6 bg-green-100 text-green-600 rounded-full flex items-center justify-center mr-2 mt-0.5">
<i class="fas fa-plus text-xs"></i>
</div>
<div>
<p>Liam earned 5 points for <span class="font-medium">Taking out trash</span></p>
<p class="text-xs text-gray-400">Today, 4:45 PM</p>
</div>
</div>
<div class="flex items-start text-sm p-2 hover:bg-gray-50 rounded">
<div class="w-6 h-6 bg-green-100 text-green-600 rounded-full flex items-center justify-center mr-2 mt-0.5">
<i class="fas fa-plus text-xs"></i>
</div>
<div>
<p>Emma earned 20 points for <span class="font-medium">Laundry help</span></p>
<p class="text-xs text-gray-400">Yesterday, 7:30 PM</p>
</div>
</div>
</div>
</div>
</div>
<!-- Main Content -->
<div class="lg:col-span-2 space-y-6">
<!-- Available Chores -->
<div class="bg-white rounded-xl shadow-lg p-6">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold text-gray-800 flex items-center">
<i class="fas fa-broom mr-2 text-indigo-600"></i> Available Chores
</h2>
<div class="relative">
<button id="filterBtn" class="flex items-center text-sm text-gray-600 hover:text-indigo-600">
<i class="fas fa-filter mr-1"></i> Filter
</button>
<div id="filterDropdown" class="hidden absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg z-10 p-2">
<label class="flex items-center px-2 py-1 hover:bg-gray-100 rounded cursor-pointer">
<input type="checkbox" class="mr-2" checked> Easy (1-5 pts)
</label>
<label class="flex items-center px-2 py-1 hover:bg-gray-100 rounded cursor-pointer">
<input type="checkbox" class="mr-2" checked> Medium (6-15 pts)
</label>
<label class="flex items-center px-2 py-1 hover:bg-gray-100 rounded cursor-pointer">
<input type="checkbox" class="mr-2" checked> Hard (16+ pts)
</label>
</div>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- Chore cards will be added here dynamically -->
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front border border-gray-200 rounded-lg p-4 hover:shadow-md transition cursor-pointer h-full">
<div class="flex justify-between items-start">
<div>
<h3 class="font-semibold">Set the table</h3>
<p class="text-sm text-gray-500">Before dinner time</p>
</div>
<div class="bg-green-100 text-green-800 px-2 py-1 rounded-full text-xs font-bold">
10 pts
</div>
</div>
<div class="mt-3 flex justify-between items-center">
<span class="text-xs bg-indigo-100 text-indigo-800 px-2 py-1 rounded">Daily</span>
<button class="text-xs bg-indigo-600 text-white px-3 py-1 rounded hover:bg-indigo-700 transition">
Complete <i class="fas fa-check ml-1"></i>
</button>
</div>
</div>
<div class="flip-card-back bg-indigo-50 rounded-lg p-4 flex flex-col justify-between">
<div>
<h3 class="font-semibold text-indigo-800">Set the table</h3>
<p class="text-sm text-indigo-600 mt-1">Includes plates, utensils, glasses, and napkins for all family members</p>
</div>
<div class="flex justify-between items-center mt-4">
<div class="text-xs">
<p class="text-indigo-600">Last completed:</p>
<p class="font-medium">Today by Emma</p>
</div>
<button class="text-xs bg-indigo-600 text-white px-3 py-1 rounded hover:bg-indigo-700 transition">
Complete <i class="fas fa-check ml-1"></i>
</button>
</div>
</div>
</div>
</div>
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front border border-gray-200 rounded-lg p-4 hover:shadow-md transition cursor-pointer h-full">
<div class="flex justify-between items-start">
<div>
<h3 class="font-semibold">Take out trash</h3>
<p class="text-sm text-gray-500">When bin is full</p>
</div>
<div class="bg-green-100 text-green-800 px-2 py-1 rounded-full text-xs font-bold">
5 pts
</div>
</div>
<div class="mt-3 flex justify-between items-center">
<span class="text-xs bg-indigo-100 text-indigo-800 px-2 py-1 rounded">As needed</span>
<button class="text-xs bg-indigo-600 text-white px-3 py-1 rounded hover:bg-indigo-700 transition">
Complete <i class="fas fa-check ml-1"></i>
</button>
</div>
</div>
<div class="flip-card-back bg-indigo-50 rounded-lg p-4 flex flex-col justify-between h-full">
<div>
<h3 class="font-semibold text-indigo-800">Take out trash</h3>
<p class="text-sm text-indigo-600 mt-1">Take kitchen trash to outside bin and replace with new bag</p>
</div>
<div class="flex justify-between items-center mt-4">
<div class="text-xs">
<p class="text-indigo-600">Last completed:</p>
<p class="font-medium">Today by Liam</p>
</div>
<button class="text-xs bg-indigo-600 text-white px-3 py-1 rounded hover:bg-indigo-700 transition">
Complete <i class="fas fa-check ml-1"></i>
</button>
</div>
</div>
</div>
</div>
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front border border-gray-200 rounded-lg p-4 hover:shadow-md transition cursor-pointer">
<div class="flex justify-between items-start">
<div>
<h3 class="font-semibold">Carry laundry baskets</h3>
<p class="text-sm text-gray-500">Upstairs and downstairs</p>
</div>
<div class="bg-green-100 text-green-800 px-2 py-1 rounded-full text-xs font-bold">
20 pts
</div>
</div>
<div class="mt-3 flex justify-between items-center">
<span class="text-xs bg-indigo-100 text-indigo-800 px-2 py-1 rounded">Weekly</span>
<button class="text-xs bg-indigo-600 text-white px-3 py-1 rounded hover:bg-indigo-700 transition">
Complete <i class="fas fa-check ml-1"></i>
</button>
</div>
</div>
<div class="flip-card-back bg-indigo-50 rounded-lg p-4 flex flex-col justify-between h-full">
<div>
<h3 class="font-semibold text-indigo-800">Carry laundry baskets</h3>
<p class="text-sm text-indigo-600 mt-1">Take full baskets upstairs and empty ones back down</p>
</div>
<div class="flex justify-between items-center mt-4">
<div class="text-xs">
<p class="text-indigo-600">Last completed:</p>
<p class="font-medium">Yesterday by Emma</p>
</div>
<button class="text-xs bg-indigo-600 text-white px-3 py-1 rounded hover:bg-indigo-700 transition">
Complete <i class="fas fa-check ml-1"></i>
</button>
</div>
</div>
</div>
</div>
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front border border-gray-200 rounded-lg p-4 hover:shadow-md transition cursor-pointer">
<div class="flex justify-between items-start">
<div>
<h3 class="font-semibold">Clean bedroom</h3>
<p class="text-sm text-gray-500">Weekly deep clean</p>
</div>
<div class="bg-green-100 text-green-800 px-2 py-1 rounded-full text-xs font-bold">
25 pts
</div>
</div>
<div class="mt-3 flex justify-between items-center">
<span class="text-xs bg-indigo-100 text-indigo-800 px-2 py-1 rounded">Weekly</span>
<button class="text-xs bg-indigo-600 text-white px-3 py-1 rounded hover:bg-indigo-700 transition">
Complete <i class="fas fa-check ml-1"></i>
</button>
</div>
</div>
<div class="flip-card-back bg-indigo-50 rounded-lg p-4 flex flex-col justify-between h-full">
<div>
<h3 class="font-semibold text-indigo-800">Clean bedroom</h3>
<p class="text-sm text-indigo-600 mt-1">Vacuum, dust, organize toys, and make bed neatly</p>
</div>
<div class="flex justify-between items-center mt-4">
<div class="text-xs">
<p class="text-indigo-600">Last completed:</p>
<p class="font-medium">3 days ago by Liam</p>
</div>
<button class="text-xs bg-indigo-600 text-white px-3 py-1 rounded hover:bg-indigo-700 transition">
Complete <i class="fas fa-check ml-1"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Rewards Store -->
<div class="bg-white rounded-xl shadow-lg p-6">
<h2 class="text-xl font-bold text-gray-800 mb-4 flex items-center">
<i class="fas fa-gift mr-2 text-indigo-600"></i> Rewards Store
</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div class="border border-gray-200 rounded-lg p-4 hover:shadow-md transition">
<div class="bg-yellow-50 p-3 rounded-lg mb-3 text-center">
<i class="fas fa-gamepad text-3xl text-yellow-500"></i>
</div>
<h3 class="font-semibold">Video Game Time</h3>
<p class="text-sm text-gray-500 mb-2">30 minutes of screen time</p>
<div class="flex justify-between items-center">
<div class="bg-purple-100 text-purple-800 px-2 py-1 rounded-full text-xs font-bold">
15 pts
</div>
<button class="text-xs bg-purple-600 text-white px-3 py-1 rounded hover:bg-purple-700 transition">
Redeem <i class="fas fa-shopping-cart ml-1"></i>
</button>
</div>
</div>
<div class="border border-gray-200 rounded-lg p-4 hover:shadow-md transition">
<div class="bg-pink-50 p-3 rounded-lg mb-3 text-center">
<i class="fas fa-ice-cream text-3xl text-pink-500"></i>
</div>
<h3 class="font-semibold">Ice Cream Treat</h3>
<p class="text-sm text-gray-500 mb-2">One scoop of favorite flavor</p>
<div class="flex justify-between items-center">
<div class="bg-purple-100 text-purple-800 px-2 py-1 rounded-full text-xs font-bold">
20 pts
</div>
<button class="text-xs bg-purple-600 text-white px-3 py-1 rounded hover:bg-purple-700 transition">
Redeem <i class="fas fa-shopping-cart ml-1"></i>
</button>
</div>
</div>
<div class="border border-gray-200 rounded-lg p-4 hover:shadow-md transition">
<div class="bg-blue-50 p-3 rounded-lg mb-3 text-center">
<i class="fas fa-film text-3xl text-blue-500"></i>
</div>
<h3 class="font-semibold">Movie Night</h3>
<p class="text-sm text-gray-500 mb-2">Choose the family movie</p>
<div class="flex justify-between items-center">
<div class="bg-purple-100 text-purple-800 px-2 py-1 rounded-full text-xs font-bold">
50 pts
</div>
<button class="text-xs bg-purple-600 text-white px-3 py-1 rounded hover:bg-purple-700 transition">
Redeem <i class="fas fa-shopping-cart ml-1"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Statistics Section -->
<div class="mt-8 bg-white rounded-xl shadow-lg p-6">
<h2 class="text-xl font-bold text-gray-800 mb-6 flex items-center">
<i class="fas fa-chart-line mr-2 text-indigo-600"></i> Family Statistics
</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="bg-indigo-50 rounded-lg p-4">
<h3 class="font-semibold text-indigo-800 mb-3">Points Distribution</h3>
<div class="chart-container">
<canvas id="pointsChart"></canvas>
</div>
</div>
<div class="bg-green-50 rounded-lg p-4">
<h3 class="font-semibold text-green-800 mb-3">Top Chores</h3>
<div class="chart-container">
<canvas id="choresChart"></canvas>
</div>
</div>
<div class="bg-purple-50 rounded-lg p-4">
<h3 class="font-semibold text-purple-800 mb-3">Rewards Popularity</h3>
<div class="chart-container">
<canvas id="rewardsChart"></canvas>
</div>
</div>
</div>
<div class="mt-6 grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<h3 class="font-semibold text-gray-700 mb-3">Weekly Points Trend</h3>
<div class="bg-white border border-gray-200 rounded-lg p-4">
<canvas id="weeklyTrendChart"></canvas>
</div>
</div>
<div>
<h3 class="font-semibold text-gray-700 mb-3">Monthly Leaderboard</h3>
<div class="bg-white border border-gray-200 rounded-lg p-4">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-pink-200 flex items-center justify-center mr-3">
<i class="fas fa-female text-pink-600"></i>
</div>
<div>
<h4 class="font-medium">Emma</h4>
<p class="text-xs text-gray-500">Total: 320 pts</p>
</div>
</div>
<div class="bg-yellow-100 text-yellow-800 px-2 py-1 rounded-full text-xs font-bold flex items-center">
<i class="fas fa-trophy mr-1"></i> 1st
</div>
</div>
<div class="flex items-center justify-between mb-3">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-blue-200 flex items-center justify-center mr-3">
<i class="fas fa-male text-blue-600"></i>
</div>
<div>
<h4 class="font-medium">Liam</h4>
<p class="text-xs text-gray-500">Total: 275 pts</p>
</div>
</div>
<div class="bg-gray-100 text-gray-800 px-2 py-1 rounded-full text-xs font-bold flex items-center">
<i class="fas fa-medal mr-1"></i> 2nd
</div>
</div>
<div class="text-center mt-4">
<p class="text-sm text-gray-500">Month of June 2023</p>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
// IndexedDB setup
let db;
const dbName = 'FamilyPointsDB';
const dbVersion = 1;
function initDB() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(dbName, dbVersion);
request.onupgradeneeded = (event) => {
db = event.target.result;
if (!db.objectStoreNames.contains('children')) {
const store = db.createObjectStore('children', { keyPath: 'name' });
store.createIndex('points', 'points', { unique: false });
// Initial data
store.put({ name: 'emma', points: 125 });
store.put({ name: 'liam', points: 80 });
}
};
request.onsuccess = (event) => {
db = event.target.result;
resolve(db);
};
request.onerror = (event) => {
console.error('IndexedDB error:', event.target.error);
reject(event.target.error);
};
});
}
function updatePoints(childName, pointsChange) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(['children'], 'readwrite');
const store = transaction.objectStore('children');
const request = store.get(childName);
request.onsuccess = () => {
const data = request.result;
data.points += pointsChange;
const updateRequest = store.put(data);
updateRequest.onsuccess = () => {
document.getElementById(`${childName}Points`).textContent = data.points;
resolve(data.points);
};
updateRequest.onerror = (event) => {
reject(event.target.error);
};
};
request.onerror = (event) => {
reject(event.target.error);
};
});
}
// Set current date
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
document.getElementById('currentDate').textContent = new Date().toLocaleDateString('en-US', options);
// Toggle parent panel
document.getElementById('parentToggle').addEventListener('click', function() {
document.getElementById('parentPanel').classList.toggle('hidden');
});
// Toggle filter dropdown
document.getElementById('filterBtn').addEventListener('click', function() {
document.getElementById('filterDropdown').classList.toggle('hidden');
});
// Add points functionality
document.getElementById('addPointsBtn').addEventListener('click', async function() {
const child = document.getElementById('childSelect').value;
const points = parseInt(document.getElementById('pointAmount').value) || 0;
if (points > 0) {
try {
await updatePoints(child, points);
alert(`Added ${points} points to ${child.charAt(0).toUpperCase() + child.slice(1)}`);
document.getElementById('pointAmount').value = '';
} catch (error) {
console.error('Error updating points:', error);
alert('Failed to update points. Please try again.');
}
}
});
// Add new chore functionality
document.getElementById('addChoreBtn').addEventListener('click', function() {
const choreName = document.getElementById('newChore').value.trim();
const chorePoints = parseInt(document.getElementById('chorePoints').value) || 0;
if (choreName && chorePoints > 0) {
// In a real app, you would add this to your database and then refresh the chores list
alert(`Added new chore: ${choreName} (${chorePoints} points)`);
document.getElementById('newChore').value = '';
document.getElementById('chorePoints').value = '';
}
});
// Initialize app
document.addEventListener('DOMContentLoaded', async function() {
// Initialize database
await initDB();
// Load initial points
const transaction = db.transaction(['children'], 'readonly');
const store = transaction.objectStore('children');
store.get('emma').onsuccess = (event) => {
document.getElementById('emmaPoints').textContent = event.target.result.points;
};
store.get('liam').onsuccess = (event) => {
document.getElementById('liamPoints').textContent = event.target.result.points;
};
// Points Distribution Chart
const pointsCtx = document.getElementById('pointsChart').getContext('2d');
const pointsChart = new Chart(pointsCtx, {
type: 'doughnut',
data: {
labels: ['Emma', 'Liam'],
datasets: [{
data: [125, 80],
backgroundColor: ['#ec4899', '#3b82f6'],
borderWidth: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom'
}
}
}
});
// Top Chores Chart
const choresCtx = document.getElementById('choresChart').getContext('2d');
const choresChart = new Chart(choresCtx, {
type: 'bar',
data: {
labels: ['Set Table', 'Take Trash', 'Laundry', 'Clean Room'],
datasets: [{
label: 'Completions',
data: [12, 8, 5, 4],
backgroundColor: '#10b981',
borderWidth: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true
}
},
plugins: {
legend: {
display: false
}
}
}
});
// Rewards Popularity Chart
const rewardsCtx = document.getElementById('rewardsChart').getContext('2d');
const rewardsChart = new Chart(rewardsCtx, {
type: 'pie',
data: {
labels: ['Game Time', 'Ice Cream', 'Movie Night'],
datasets: [{
data: [15, 8, 3],
backgroundColor: ['#8b5cf6', '#ec4899', '#3b82f6'],
borderWidth: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom'
}
}
}
});
// Weekly Trend Chart
const weeklyCtx = document.getElementById('weeklyTrendChart').getContext('2d');
const weeklyChart = new Chart(weeklyCtx, {
type: 'line',
data: {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
datasets: [
{
label: 'Emma',
data: [15, 20, 25, 30, 20, 15, 10],
borderColor: '#ec4899',
backgroundColor: 'rgba(236, 72, 153, 0.1)',
tension: 0.3,
fill: true
},
{
label: 'Liam',
data: [10, 15, 20, 15, 25, 10, 5],
borderColor: '#3b82f6',
backgroundColor: 'rgba(59, 130, 246, 0.1)',
tension: 0.3,
fill: true
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true
}
}
}
});
});
// Complete chore buttons
document.querySelectorAll('.flip-card-front button, .flip-card-back button').forEach(button => {
button.addEventListener('click', async function(e) {
e.stopPropagation(); // Prevent card flip when clicking button
const choreCard = this.closest('.flip-card');
const choreName = choreCard.querySelector('h3').textContent;
const pointsText = choreCard.querySelector('.bg-green-100').textContent;
const points = parseInt(pointsText);
const child = prompt(`Which child completed "${choreName}"? (emma/liam)`);
if (child && (child === 'emma' || child === 'liam')) {
try {
await updatePoints(child, points);
alert(`${child.charAt(0).toUpperCase() + child.slice(1)} earned ${points} points for "${choreName}"!`);
} catch (error) {
console.error('Error updating points:', error);
alert('Failed to update points. Please try again.');
}
}
});
});
// Redeem reward buttons
document.querySelectorAll('.rewards-store button').forEach(button => {
button.addEventListener('click', async function() {
const rewardCard = this.closest('.border');
const rewardName = rewardCard.querySelector('h3').textContent;
const pointsText = rewardCard.querySelector('.bg-purple-100').textContent;
const points = parseInt(pointsText);
const child = prompt(`Which child is redeeming "${rewardName}"? (emma/liam)`);
if (child && (child === 'emma' || child === 'liam')) {
try {
await updatePoints(child, -points);
alert(`${child.charAt(0).toUpperCase() + child.slice(1)} redeemed "${rewardName}" for ${points} points!`);
} catch (error) {
console.error('Error updating points:', error);
alert('Failed to redeem reward. Not enough points or error occurred.');
}
}
});
});
</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=BHelfmann/point-system" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>