From 93a2b8acb1670f1bcca161eb1c6d2bde85de55e9 Mon Sep 17 00:00:00 2001 From: jessikitty Date: Tue, 27 Jan 2026 22:22:21 +1100 Subject: [PATCH] Add dashboard page with chore management --- frontend/src/pages/Dashboard.tsx | 220 +++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 frontend/src/pages/Dashboard.tsx diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx new file mode 100644 index 0000000..d76110c --- /dev/null +++ b/frontend/src/pages/Dashboard.tsx @@ -0,0 +1,220 @@ +import React, { useState, useEffect } from 'react'; +import { useAuth } from '../contexts/AuthContext'; +import { choreService, Chore } from '../api/chores'; +import ChoreCard from '../components/ChoreCard'; +import CreateChoreModal from '../components/CreateChoreModal'; + +const Dashboard: React.FC = () => { + const { user, logout } = useAuth(); + const [chores, setChores] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [showCreateModal, setShowCreateModal] = useState(false); + const [filter, setFilter] = useState<'all' | 'my' | 'today'>('all'); + + useEffect(() => { + loadChores(); + }, []); + + const loadChores = async () => { + try { + const data = await choreService.getChores(); + setChores(data); + } catch (error) { + console.error('Failed to load chores:', error); + } finally { + setIsLoading(false); + } + }; + + const handleCompleteChore = async (id: number) => { + try { + await choreService.completeChore(id); + await loadChores(); + } catch (error) { + console.error('Failed to complete chore:', error); + } + }; + + const handleDeleteChore = async (id: number) => { + if (window.confirm('Are you sure you want to delete this chore?')) { + try { + await choreService.deleteChore(id); + await loadChores(); + } catch (error) { + console.error('Failed to delete chore:', error); + } + } + }; + + const filteredChores = chores.filter((chore) => { + if (filter === 'my') { + return chore.assigned_to === user?.id; + } + if (filter === 'today') { + const today = new Date().toISOString().split('T')[0]; + return chore.due_date === today || chore.frequency === 'daily'; + } + return true; + }); + + const todayChores = chores.filter((chore) => { + const today = new Date().toISOString().split('T')[0]; + return (chore.due_date === today || chore.frequency === 'daily') && chore.status !== 'completed'; + }); + + const myChores = chores.filter((chore) => chore.assigned_to === user?.id && chore.status !== 'completed'); + + return ( +
+ {/* Header */} +
+
+
+

Family Hub

+

Welcome back, {user?.full_name}!

+
+ +
+
+ + {/* Main Content */} +
+ {/* Stats */} +
+
+
+
+

Today's Tasks

+

{todayChores.length}

+
+
+ + + +
+
+
+ +
+
+
+

My Tasks

+

{myChores.length}

+
+
+ + + +
+
+
+ +
+
+
+

Total Tasks

+

{chores.length}

+
+
+ + + +
+
+
+
+ + {/* Actions */} +
+
+ + + +
+ + +
+ + {/* Chores List */} + {isLoading ? ( +
+
+

Loading tasks...

+
+ ) : filteredChores.length === 0 ? ( +
+ + + +

No tasks

+

Get started by creating a new task.

+
+ ) : ( +
+ {filteredChores.map((chore) => ( + + ))} +
+ )} +
+ + {/* Create Chore Modal */} + {showCreateModal && ( + setShowCreateModal(false)} + onSuccess={() => { + setShowCreateModal(false); + loadChores(); + }} + /> + )} +
+ ); +}; + +export default Dashboard;