1+ import 'package:flutter/material.dart' ;
2+ import 'package:provider/provider.dart' ;
3+ import '../../../core/theme/app_colors.dart' ;
4+
5+ import '../viewmodel/user_profile_viewmodel.dart' ;
6+ import 'widgets/profile_header.dart' ;
7+ import 'widgets/stat_card.dart' ;
8+ import 'widgets/settings_section.dart' ;
9+ import 'widgets/settings_list_tile.dart' ;
10+ import 'widgets/logout_button.dart' ;
11+
12+ class UserProfileView extends StatelessWidget {
13+ const UserProfileView ({super .key});
14+
15+ @override
16+ Widget build (BuildContext context) {
17+ return Scaffold (
18+ backgroundColor: AppColors .background,
19+ appBar: AppBar (
20+ backgroundColor: AppColors .background,
21+ elevation: 0 ,
22+ centerTitle: true ,
23+ scrolledUnderElevation: 0 ,
24+ title: const Text (
25+ 'Profile' ,
26+ style: TextStyle (
27+ color: AppColors .primaryBlue,
28+ fontWeight: FontWeight .w800,
29+ fontSize: 20 ,
30+ ),
31+ ),
32+ actions: [
33+ IconButton (
34+ icon: const Icon (Icons .settings, color: AppColors .primaryBlue),
35+ onPressed: () {},
36+ splashRadius: 24 ,
37+ ),
38+ ],
39+ ),
40+ body: Consumer <UserProfileViewModel >(
41+ builder: (context, vm, child) {
42+ return AnimatedSwitcher (
43+ duration: const Duration (milliseconds: 300 ),
44+ child: vm.isLoading
45+ ? const Center (
46+ key: ValueKey ('loading' ),
47+ child: CircularProgressIndicator (color: AppColors .primaryBlue),
48+ )
49+ : vm.user == null
50+ ? const Center (
51+ key: ValueKey ('error' ),
52+ child: Text ("Error loading profile" ),
53+ )
54+ : _buildProfileContent (context, vm),
55+ );
56+ },
57+ ),
58+ );
59+ }
60+
61+ Widget _buildProfileContent (BuildContext context, UserProfileViewModel vm) {
62+ final user = vm.user! ;
63+ return SingleChildScrollView (
64+ key: const ValueKey ('content' ),
65+ physics: const BouncingScrollPhysics (),
66+ padding: const EdgeInsets .fromLTRB (24 , 8 , 24 , 40 ),
67+ child: Column (
68+ children: [
69+ // 1. Header (Avatar & Name)
70+ ProfileHeader (user: user),
71+ const SizedBox (height: 32 ),
72+
73+ // 2. Stats Row
74+ Row (
75+ children: [
76+ Expanded (
77+ child: StatCard (
78+ value: user.tasksDone.toString (),
79+ label: 'Tasks Done' ,
80+ onTap: () {},
81+ ),
82+ ),
83+ const SizedBox (width: 16 ),
84+ Expanded (
85+ child: StatCard (
86+ value: user.streaks.toString (),
87+ label: 'Streaks' ,
88+ onTap: () {},
89+ ),
90+ ),
91+ ],
92+ ),
93+ const SizedBox (height: 32 ),
94+
95+ SettingsSection (
96+ title: 'Preferences' ,
97+ children: [
98+ SettingsListTile (
99+ icon: Icons .notifications,
100+ title: 'Notifications' ,
101+ iconBgColor: AppColors .border,
102+ iconColor: AppColors .grayText,
103+ onTap: () => vm.toggleNotification (! user.isNotificationEnabled),
104+ trailing: Switch (
105+ value: user.isNotificationEnabled,
106+ activeColor: AppColors .white,
107+ activeTrackColor: AppColors .primaryBlue,
108+ inactiveThumbColor: AppColors .grayText,
109+ inactiveTrackColor: AppColors .border,
110+ onChanged: (val) => vm.toggleNotification (val),
111+ ),
112+ ),
113+ const Divider (height: 1 , indent: 64 , endIndent: 24 , color: AppColors .border),
114+ SettingsListTile (
115+ icon: Icons .dark_mode,
116+ title: 'Appearance' ,
117+ iconBgColor: AppColors .border,
118+ iconColor: AppColors .grayText,
119+ trailing: Text (
120+ user.appearance,
121+ style: const TextStyle (
122+ fontSize: 14 ,
123+ fontWeight: FontWeight .w600,
124+ color: AppColors .grayText,
125+ ),
126+ ),
127+ onTap: () {},
128+ ),
129+ ],
130+ ),
131+ const SizedBox (height: 40 ),
132+
133+ // 4. Logout Button
134+ LogoutButton (onPressed: () => vm.logout (context)),
135+ ],
136+ ),
137+ );
138+ }
139+ }
0 commit comments