diff --git a/.github/assets/autism-level-after.png b/.github/assets/autism-level-after.png new file mode 100644 index 0000000..5583abe Binary files /dev/null and b/.github/assets/autism-level-after.png differ diff --git a/.github/assets/autism-level-before.png b/.github/assets/autism-level-before.png new file mode 100644 index 0000000..d217a9f Binary files /dev/null and b/.github/assets/autism-level-before.png differ diff --git a/patient/lib/presentation/home/home_screen.dart b/patient/lib/presentation/home/home_screen.dart index 967218e..dc60705 100644 --- a/patient/lib/presentation/home/home_screen.dart +++ b/patient/lib/presentation/home/home_screen.dart @@ -10,6 +10,7 @@ import 'package:patient/presentation/reports/report_screen.dart'; // Import the import 'package:patient/presentation/notification/updates_screen.dart'; import 'package:patient/presentation/games/games_screen.dart'; import 'package:patient/presentation/profile/profile_screen.dart'; +import 'package:supabase_flutter/supabase_flutter.dart'; import '../../gen/assets.gen.dart'; @@ -28,6 +29,8 @@ class HomeScreen extends StatefulWidget { class _HomeScreenState extends State { int _selectedIndex = 0; late List _screens; + static const int _maxAutismLevel = 18; + double _autismLevel = 0; @override void initState() { @@ -39,6 +42,31 @@ class _HomeScreenState extends State { UpdatesScreen(), const ProfileScreen(), ]; + _fetchAutismLevel(); + } + + Future _fetchAutismLevel() async { + try { + final currentUser = Supabase.instance.client.auth.currentUser; + if (currentUser == null) return; + + final response = await Supabase.instance.client + .from('patient') + .select('autism_level') + .eq('id', currentUser.id) + .maybeSingle(); + + final rawLevel = response?['autism_level']; + final level = rawLevel is num ? rawLevel.toDouble() : 0; + + if (!mounted) return; + setState(() { + _autismLevel = level.clamp(0, _maxAutismLevel.toDouble()).toDouble(); + _screens[0] = _buildHomeContent(); + }); + } catch (_) { + // Keep fallback value when backend field is unavailable. + } } @override @@ -138,7 +166,7 @@ class _HomeScreenState extends State { Expanded( child: ListView( children: [ - const LevelIndicator(currentLevel: 5, maxLevel: 18), + LevelIndicator(currentLevel: _autismLevel, maxLevel: _maxAutismLevel), const SizedBox(height: 15), // Using the reusable TherapyGoalCard three times GestureDetector( @@ -153,7 +181,7 @@ class _HomeScreenState extends State { title: 'Therapy', subtitle: 'Goals', illustration: Assets.illustrations.i9nGoals, - backgroundColor: Color(0xFFF9F3E3), + backgroundColor: const Color(0xFFF9F3E3), ), ), const SizedBox(height: 15), @@ -171,7 +199,7 @@ class _HomeScreenState extends State { title: 'Daily', subtitle: 'Activities', illustration: Assets.illustrations.i9nActivities, - backgroundColor: Color(0xFFFEF4F0), + backgroundColor: const Color(0xFFFEF4F0), imageOnLeft: true, ), ), @@ -182,7 +210,7 @@ class _HomeScreenState extends State { title: 'Development', subtitle: 'Milestones', illustration: Assets.illustrations.i9nMilestones, - backgroundColor: Color(0xFFF5FAF4), + backgroundColor: const Color(0xFFF5FAF4), ), const SizedBox(height: 15), // Games Card diff --git a/patient/lib/presentation/home/widgets/home_screen_slider.dart b/patient/lib/presentation/home/widgets/home_screen_slider.dart index 714f0bc..a9d7b80 100644 --- a/patient/lib/presentation/home/widgets/home_screen_slider.dart +++ b/patient/lib/presentation/home/widgets/home_screen_slider.dart @@ -12,6 +12,9 @@ class LevelIndicator extends StatelessWidget { @override Widget build(BuildContext context) { + final safeMaxLevel = maxLevel <= 0 ? 1 : maxLevel; + final clampedLevel = currentLevel.clamp(0, safeMaxLevel.toDouble()); + return Card( elevation: 0, color: const Color(0xFFCB6CE6), @@ -35,59 +38,78 @@ class LevelIndicator extends StatelessWidget { Row( children: [ Expanded( - child: Stack( - alignment: Alignment.centerLeft, - children: [ - // Slider track - Container( - height: 40, // Increased height for better visibility - decoration: BoxDecoration( - color: const Color(0xFFCB6CE6), - borderRadius: BorderRadius.circular(10), - ), - ), - // Tick marks - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: List.generate( - maxLevel, // Number of divisions based on max level - (index) => Container( - height: index % 2 == 0 - ? 20 - : 15, // Alternating heights for ticks - width: 2, - color: Colors.white.withOpacity(0.7), - ), - ), - ), - // Current level indicator (triangle) - // Current level indicator (triangle with text above) - Positioned( - left: (currentLevel / (maxLevel)) * - (MediaQuery.of(context).size.width * 0.8 - - 25), // Adjust for better alignment - child: Column( + child: LayoutBuilder( + builder: (context, constraints) { + const indicatorWidth = 40.0; + const tickTop = 44.0; + const halfIndicator = indicatorWidth / 2; + final trackWidth = constraints.maxWidth; + final ratio = clampedLevel / safeMaxLevel; + final indicatorLeft = ratio * (trackWidth - indicatorWidth); + + return SizedBox( + height: 84, + child: Stack( children: [ - Text( - currentLevel.toStringAsFixed(0), - style: const TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: Colors.white, + Positioned( + left: 0, + right: 0, + top: tickTop, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: halfIndicator), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: List.generate( + safeMaxLevel + 1, + (index) => Container( + height: index % 2 == 0 ? 20 : 15, + width: 2, + color: Colors.white.withValues(alpha: 0.7), + ), + ), + ), ), ), - const SizedBox(height: 5), - CustomPaint( - size: const Size(20, 20), - painter: TrianglePainter(), + Positioned( + left: indicatorLeft, + top: 0, + child: SizedBox( + width: indicatorWidth, + height: tickTop + 20, + child: Stack( + children: [ + Positioned( + top: 0, + left: 0, + right: 0, + child: Text( + clampedLevel.toStringAsFixed(0), + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + ), + Positioned( + top: tickTop, + left: 10, + child: CustomPaint( + size: const Size(20, 20), + painter: TrianglePainter(), + ), + ), + ], + ), + ), ), ], ), - ), - ], + ); + }, ), ), - const SizedBox(width: 10), ], ), ], diff --git a/patient/pubspec.lock b/patient/pubspec.lock index 347667d..92ef349 100644 --- a/patient/pubspec.lock +++ b/patient/pubspec.lock @@ -165,10 +165,10 @@ packages: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" checked_yaml: dependency: transitive description: @@ -281,6 +281,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + dio: + dependency: transitive + description: + name: dio + sha256: aff32c08f92787a557dd5c0145ac91536481831a01b4648136373cddb0e64f8c + url: "https://pub.dev" + source: hosted + version: "5.9.2" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "2f9e64323a7c3c7ef69567d5c800424a11f8337b8b228bad02524c9fb3c1f340" + url: "https://pub.dev" + source: hosted + version: "2.1.2" dotted_border: dependency: "direct main" description: @@ -301,10 +317,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.3" ffi: dependency: transitive description: @@ -342,6 +358,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.2.1" + flutter_gemini: + dependency: "direct main" + description: + name: flutter_gemini + sha256: b7264b1d19acc4b1a5628a0e26c0976aa1fb948f0d3243bc3510ff51e09476b7 + url: "https://pub.dev" + source: hosted + version: "3.0.0" flutter_gen_core: dependency: transitive description: @@ -413,6 +437,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.1" + get_it: + dependency: "direct main" + description: + name: get_it + sha256: ae78de7c3f2304b8d81f2bb6e320833e5e81de942188542328f074978cc0efa9 + url: "https://pub.dev" + source: hosted + version: "8.3.0" glob: dependency: transitive description: @@ -561,10 +593,10 @@ packages: dependency: "direct main" description: name: intl - sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" url: "https://pub.dev" source: hosted - version: "0.19.0" + version: "0.20.2" io: dependency: transitive description: @@ -601,26 +633,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.8" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -641,26 +673,26 @@ packages: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.19" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mime: dependency: transitive description: @@ -854,7 +886,7 @@ packages: source: hosted version: "3.1.2" rxdart: - dependency: transitive + dependency: "direct main" description: name: rxdart sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" @@ -1022,10 +1054,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.10" time: dependency: transitive description: @@ -1130,6 +1162,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.4" + uuid: + dependency: "direct main" + description: + name: uuid + sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" + url: "https://pub.dev" + source: hosted + version: "4.5.3" vector_graphics: dependency: "direct main" description: @@ -1158,10 +1198,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -1235,5 +1275,5 @@ packages: source: hosted version: "2.0.3" sdks: - dart: ">=3.7.0 <4.0.0" + dart: ">=3.9.0-0 <4.0.0" flutter: ">=3.27.0"