════════ Exception caught by rendering library ═════════════════════════════════ A RenderFlex overflowed by 3.0 pixels on the bottom. The relevant error-causing widget was: Column Column:file:///C:/Users/chuon/flutter/DoAnLapTrinhDiDong/fitness_health/lib/view/home/home_view.dart:557:36 ════════════════════════════════════════════════════════════════════════════════ W/WindowOnBackDispatcher(32050): OnBackInvokedCallback is not enabled for the application. W/WindowOnBackDispatcher(32050): Set 'android:enableOnBackInvokedCallback="true"' in the application manifest. ════════ Exception caught by rendering library ═════════════════════════════════ A RenderFlex overflowed by 2.0 pixels on the bottom. The relevant error-causing widget was: Column Column:file:///C:/Users/chuon/flutter/DoAnLapTrinhDiDong/fitness_health/lib/common_widget/today_target_cell.dart:29:20 ════════════════════════════════════════════════════════════════════════════════ ════════ Exception caught by rendering library ═════════════════════════════════ A RenderFlex overflowed by 1.00 pixels on the bottom. The relevant error-causing widget was: Column Column:file:///C:/Users/chuon/flutter/DoAnLapTrinhDiDong/fitness_health/lib/common_widget/today_target_cell.dart:29:20 ════════════════════════════════════════════════════════════════════════════════ ════════ Exception caught by image resource service ════════════════════════════ Unable to load asset: "https://res.cloudinary.com/dqxh4rmi3/image/upload/v1749457430/th_zmjdas.jpg". ════════════════════════════════════════════════════════════════════════════════ ════════ Exception caught by rendering library ═════════════════════════════════ A RenderFlex overflowed by 525 pixels on the right. The relevant error-causing widget was: Row Row:file:///C:/Users/chuon/flutter/DoAnLapTrinhDiDong/fitness_health/lib/common_widget/latest_activity_row.dart:13:14 ════════════════════════════════════════════════════════════════════════════════ ════════ Exception caught by rendering library ═════════════════════════════════ A RenderFlex overflowed by 525 pixels on the right. The relevant error-causing widget was: Row Row:file:///C:/Users/chuon/flutter/DoAnLapTrinhDiDong/fitness_health/lib/common_widget/latest_activity_row.dart:13:14 ════════════════════════════════════════════════════════════════════════════════ I/VRI[MainActivity]@1693956(32050): onDisplayChanged oldDisplayState=2 newDisplayState=2 I/VRI[MainActivity]@1693956(32050): call setFrameRateCategory for import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import '../../common/colo_extension.dart'; import '../../common_widget/latest_activity_row.dart'; import '../../common_widget/today_target_cell.dart'; // Import services và models import 'package:fitness_health/services/activity_service.dart'; import 'package:fitness_health/models/daily_activity_summary_model.dart'; import 'package:fitness_health/models/activity_progress_model.dart'; import 'package:fitness_health/models/latest_activity_model.dart'; class ActivityTrackerView extends StatefulWidget { const ActivityTrackerView({super.key}); @override State<ActivityTrackerView> createState() => _ActivityTrackerViewState(); } class _ActivityTrackerViewState extends State<ActivityTrackerView> { final ActivityService _activityService = ActivityService(); DailyActivitySummary? _todaySummary; List<ActivityProgressData> _weeklyProgress = []; List<ActivityProgressData> _monthlyProgress = []; List<LatestActivity> _latestActivities = []; bool _isLoadingSummary = true; bool _isLoadingProgress = true; bool _isLoadingLatest = true; String _selectedPeriod = "Tuần"; int touchedIndex = -1; @override void initState() { super.initState(); _fetchData(); } Future<void> _fetchData() async { await _fetchTodaySummary(); await _fetchActivityProgress(_selectedPeriod); await _fetchLatestActivities(); } Future<void> _fetchTodaySummary() async { setState(() { _isLoadingSummary = true; }); try { final summary = await _activityService.getTodayActivitySummary(); if (mounted) setState(() { _todaySummary = summary; }); } catch (e) { if (mounted) _showError('Lỗi tải mục tiêu hôm nay: $e'); } finally { if (mounted) setState(() { _isLoadingSummary = false; }); } } Future<void> _fetchActivityProgress(String period) async { setState(() { _isLoadingProgress = true; }); try { final progressData = await _activityService.getActivityProgress( period == "Tuần" ? "weekly" : "monthly", ); if (mounted) { setState(() { if (period == "Tuần") _weeklyProgress = progressData; else _monthlyProgress = progressData; }); } } catch (e) { if (mounted) _showError('Lỗi tải tiến trình hoạt động: $e'); } finally { if (mounted) setState(() { _isLoadingProgress = false; }); } } Future<void> _fetchLatestActivities() async { setState(() { _isLoadingLatest = true; }); try { final activities = await _activityService.getLatestActivities(count: 2); if (mounted) setState(() { _latestActivities = activities; }); } catch (e) { if (mounted) _showError('Lỗi tải hoạt động gần đây: $e'); } finally { if (mounted) setState(() { _isLoadingLatest = false; }); } } void _showError(String message) { if (mounted) { ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text(message))); } } @override Widget build(BuildContext context) { var media = MediaQuery.of(context).size; return Scaffold( appBar: AppBar( backgroundColor: TColor.white, centerTitle: true, elevation: 0, leading: InkWell( onTap: () { Navigator.pop(context); }, child: Container( margin: const EdgeInsets.all(8), height: 40, width: 40, alignment: Alignment.center, decoration: BoxDecoration( color: TColor.lightGray, borderRadius: BorderRadius.circular(10), ), child: Image.asset( "assets/img/black_btn.png", width: 15, height: 15, fit: BoxFit.contain, ), ), ), title: Text( "Theo Dõi Hoạt Động", style: TextStyle( color: TColor.black, fontSize: 16, fontWeight: FontWeight.w700, ), ), actions: [ InkWell( onTap: () {}, child: Container( margin: const EdgeInsets.all(8), height: 40, width: 40, alignment: Alignment.center, decoration: BoxDecoration( color: TColor.lightGray, borderRadius: BorderRadius.circular(10), ), child: Image.asset( "assets/img/more_btn.png", width: 15, height: 15, fit: BoxFit.contain, ), ), ), ], ), backgroundColor: TColor.white, body: SingleChildScrollView( child: Container( padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 25), child: Column( children: [ Container( padding: const EdgeInsets.symmetric( vertical: 15, horizontal: 15, ), decoration: BoxDecoration( gradient: LinearGradient( colors: [ TColor.primaryColor2.withOpacity(0.3), TColor.primaryColor1.withOpacity(0.3), ], ), borderRadius: BorderRadius.circular(15), ), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Mục Tiêu Hôm Nay", style: TextStyle( color: TColor.black, fontSize: 14, fontWeight: FontWeight.w700, ), ), SizedBox( width: 30, height: 30, child: Container( decoration: BoxDecoration( gradient: LinearGradient(colors: TColor.primaryG), borderRadius: BorderRadius.circular(10), ), child: MaterialButton( onPressed: () {}, padding: EdgeInsets.zero, height: 30, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(25), ), textColor: TColor.primaryColor1, minWidth: double.maxFinite, elevation: 0, color: Colors.transparent, child: const Icon( Icons.add, color: Colors.white, size: 15, ), ), ), ), ], ), const SizedBox(height: 15), _isLoadingSummary ? const CircularProgressIndicator() : Row( children: [ Expanded( child: TodayTargetCell( icon: "assets/img/water.png", value: "${(_todaySummary?.waterIntakeMl ?? 0) / 1000}L", title: "Lượng Nước Uống", ), ), const SizedBox(width: 15), Expanded( child: TodayTargetCell( icon: "assets/img/foot.png", value: NumberFormat( "#,##0", ).format(_todaySummary?.stepsCount ?? 0), title: "Số Bước Chân", ), ), ], ), ], ), ), SizedBox(height: media.width * 0.1), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Tiến Trình Hoạt Động", style: TextStyle( color: TColor.black, fontSize: 16, fontWeight: FontWeight.w700, ), ), Container( height: 30, padding: const EdgeInsets.symmetric(horizontal: 8), decoration: BoxDecoration( gradient: LinearGradient(colors: TColor.primaryG), borderRadius: BorderRadius.circular(15), ), child: DropdownButtonHideUnderline( child: DropdownButton<String>( items: ["Tuần", "Tháng"] .map( (name) => DropdownMenuItem( value: name, child: Text( name, style: TextStyle( color: TColor.white, fontSize: 12, ), ), ), ) .toList(), onChanged: (String? value) { if (value != null) { setState(() { _selectedPeriod = value; }); _fetchActivityProgress(value); } }, icon: Icon(Icons.expand_more, color: TColor.white), value: _selectedPeriod, dropdownColor: TColor.primaryColor1, style: TextStyle(color: TColor.white, fontSize: 12), ), ), ), ], ), SizedBox(height: media.width * 0.05), _isLoadingProgress ? Container( height: media.width * 0.5, alignment: Alignment.center, child: const CircularProgressIndicator(), ) : Container( height: media.width * 0.5, padding: const EdgeInsets.symmetric( vertical: 15, horizontal: 0, ), decoration: BoxDecoration( color: TColor.white, borderRadius: BorderRadius.circular(15), boxShadow: const [ BoxShadow(color: Colors.black12, blurRadius: 3), ], ), child: BarChart( BarChartData( barTouchData: barTouchData(), // Gọi hàm helper titlesData: titlesData(), // Gọi hàm helper borderData: FlBorderData(show: false), barGroups: _selectedPeriod == "Tuần" ? showingGroupsFromData(_weeklyProgress) : showingGroupsFromData(_monthlyProgress), gridData: const FlGridData(show: false), ), ), ), SizedBox(height: media.width * 0.05), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Hoạt Động Gần Đây", style: TextStyle( color: TColor.black, fontSize: 16, fontWeight: FontWeight.w700, ), ), TextButton( onPressed: () {}, child: Text( "Xem Thêm", style: TextStyle( color: TColor.gray, fontSize: 14, fontWeight: FontWeight.w700, ), ), ), ], ), _isLoadingLatest ? const CircularProgressIndicator() : _latestActivities.isEmpty ? const Padding( padding: EdgeInsets.symmetric(vertical: 20.0), child: Text( "Chưa có hoạt động nào gần đây.", style: TextStyle(color: Colors.grey), ), ) : ListView.builder( padding: EdgeInsets.zero, physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemCount: _latestActivities.length, itemBuilder: (context, index) { var activity = _latestActivities[index]; var wObj = { "image": activity.image ?? "assets/img/default_activity.png", "title": activity.title, "time": formatTimeAgo(activity.time), }; return LatestActivityRow(wObj: wObj); }, ), SizedBox(height: media.width * 0.1), ], ), ), ), ); } // --- CÁC HÀM HELPER CHO BIỂU ĐỒ (ĐÃ VIẾT LẠI ĐẦY ĐỦ) --- BarTouchData barTouchData() { return BarTouchData( touchTooltipData: BarTouchTooltipData( tooltipBgColor: Colors.grey, tooltipHorizontalAlignment: FLHorizontalAlignment.right, tooltipMargin: 10, getTooltipItem: (group, groupIndex, rod, rodIndex) { final currentProgressData = _selectedPeriod == "Tuần" ? _weeklyProgress : _monthlyProgress; if (groupIndex >= currentProgressData.length) return null; final dataPointForThisGroup = currentProgressData[groupIndex]; String dayLabel; if (_selectedPeriod == "Tuần") { try { final date = DateFormat( 'yyyy-MM-dd', ).parse(dataPointForThisGroup.date); dayLabel = DateFormat('EEEE', 'vi_VN').format(date); } catch (e) { dayLabel = "Lỗi ngày"; } } else { try { final date = DateFormat( 'yyyy-MM-dd', ).parse(dataPointForThisGroup.date); dayLabel = "Ngày ${date.day}"; } catch (e) { dayLabel = "Ngày ${group.x.toInt() + 1}"; } } return BarTooltipItem( '$dayLabel\n', const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 14, ), children: <TextSpan>[ TextSpan( text: NumberFormat("#,##0").format(rod.toY), style: TextStyle( color: TColor.white, fontSize: 16, fontWeight: FontWeight.w500, ), ), const TextSpan( text: ' bước', style: TextStyle(color: Colors.white, fontSize: 12), ), ], ); }, ), touchCallback: (FlTouchEvent event, barTouchResponse) { setState(() { if (!event.isInterestedForInteractions || barTouchResponse == null || barTouchResponse.spot == null) { touchedIndex = -1; return; } touchedIndex = barTouchResponse.spot!.touchedBarGroupIndex; }); }, ); } FlTitlesData titlesData() { return FlTitlesData( show: true, rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, getTitlesWidget: getTitles, reservedSize: 38, ), ), leftTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), ); } Widget getTitles(double value, TitleMeta meta) { var style = TextStyle( color: TColor.gray, fontWeight: FontWeight.w500, fontSize: 10, ); Widget textWidget; int index = value.toInt(); final currentProgressData = _selectedPeriod == "Tuần" ? _weeklyProgress : _monthlyProgress; if (index >= 0 && index < currentProgressData.length) { final dataPoint = currentProgressData[index]; if (_selectedPeriod == "Tuần") { try { final date = DateFormat('yyyy-MM-dd').parse(dataPoint.date); textWidget = Text( DateFormat('E', 'vi_VN').format(date), style: style, ); } catch (e) { textWidget = Text('', style: style); } } else { try { final date = DateFormat('yyyy-MM-dd').parse(dataPoint.date); if (date.day == 1 || date.day % 7 == 0 || index == currentProgressData.length - 1) { textWidget = Text(date.day.toString(), style: style); } else { textWidget = Text('', style: style); } } catch (e) { textWidget = Text('', style: style); } } } else { textWidget = Text('', style: style); } return SideTitleWidget( axisSide: meta.axisSide, space: 8, child: textWidget, ); } List<BarChartGroupData> showingGroupsFromData( List<ActivityProgressData> progressData, ) { if (progressData.isEmpty) return []; double maxY = 20; final maxValue = progressData .map((d) => d.value) .reduce((a, b) => a > b ? a : b); if (maxValue > 0) { maxY = (maxValue * 1.2).ceilToDouble(); if (maxY < 20) maxY = 20; } return List.generate(progressData.length, (i) { final dataPoint = progressData[i]; return makeGroupData( i, dataPoint.value.toDouble(), (i % 2 == 0) ? TColor.primaryG : TColor.secondaryG, isTouched: i == touchedIndex, maxYForBackground: maxY, ); }); } BarChartGroupData makeGroupData( int x, double y, List<Color> barColor, { bool isTouched = false, double width = 16, List<int> showTooltips = const [], double maxYForBackground = 20, }) { return BarChartGroupData( x: x, barRods: [ BarChartRodData( toY: isTouched ? y + 1 : y, gradient: LinearGradient( colors: barColor, begin: Alignment.topCenter, end: Alignment.bottomCenter, ), width: width, borderSide: isTouched ? BorderSide( color: TColor.primaryColor1.withOpacity(0.7), width: 2, ) : const BorderSide(color: Colors.white, width: 0), borderRadius: const BorderRadius.only( topLeft: Radius.circular(3), topRight: Radius.circular(3), ), backDrawRodData: BackgroundBarChartRodData( show: true, toY: maxYForBackground, color: TColor.lightGray.withOpacity(0.5), ), ), ], showingTooltipIndicators: showTooltips, ); } String formatTimeAgo(DateTime dateTime) { final now = DateTime.now(); final difference = now.difference(dateTime); if (difference.inSeconds < 60) return "${difference.inSeconds} giây trước"; if (difference.inMinutes < 60) return "${difference.inMinutes} phút trước"; if (difference.inHours < 24) return "${difference.inHours} giờ trước"; if (difference.inDays < 7) return "${difference.inDays} ngày trước"; return DateFormat( 'dd MMM', 'vi_VN', ).format(dateTime); // Hiển thị ngày/tháng nếu lâu hơn } } import 'package:fitness_health/common/colo_extension.dart'; import 'package:flutter/material.dart'; class LatestActivityRow extends StatelessWidget { final Map wObj; const LatestActivityRow({super.key, required this.wObj}); @override Widget build(BuildContext context) { return Container( margin: const EdgeInsets.symmetric(vertical: 8), child: Row( children: [ ClipRRect( borderRadius: BorderRadius.circular(30), child: Image.asset( wObj["image"].toString(), width: 50, height: 50, fit: BoxFit.cover, ), ), const SizedBox(width: 15), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( wObj["title"].toString(), style: TextStyle( color: TColor.black, fontSize: 12, fontWeight: FontWeight.w500, ), ), Text( wObj["time"].toString(), style: TextStyle(color: TColor.gray, fontSize: 10), ), ], ), ), IconButton( onPressed: () {}, icon: Image.asset( "assets/img/sub_menu.png", width: 12, height: 12, fit: BoxFit.contain, ), ), ], ), ); } } import 'package:fitness_health/common/colo_extension.dart'; import 'package:flutter/material.dart'; class TodayTargetCell extends StatelessWidget { final String icon; final String value; final String title; const TodayTargetCell({ super.key, required this.icon, required this.value, required this.title, }); @override Widget build(BuildContext context) { return Container( height: 70, padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: TColor.white, borderRadius: BorderRadius.circular(15), ), child: Row( children: [ Image.asset(icon, width: 40, height: 40, fit: BoxFit.contain), const SizedBox(width: 8), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ ShaderMask( blendMode: BlendMode.srcIn, shaderCallback: (bounds) { return LinearGradient( colors: TColor.primaryG, begin: Alignment.centerLeft, end: Alignment.centerRight, ).createShader( Rect.fromLTRB(0, 0, bounds.width, bounds.height), ); }, child: Text( value, style: TextStyle( color: TColor.white.withOpacity(0.7), fontWeight: FontWeight.w700, fontSize: 14, ), ), ), Text( title, style: TextStyle(color: TColor.black, fontSize: 12), ), ], ), ), ], ), ); } } // services/activity_service.dart import 'dart:convert'; import 'package:fitness_health/models/activity_progress_model.dart'; import 'package:fitness_health/models/api_result_model.dart'; import 'package:fitness_health/models/heart_rate_data_point_model.dart'; import 'package:fitness_health/models/latest_activity_model.dart'; import 'package:fitness_health/services/api_endpoint.dart'; import 'package:http/http.dart' as http; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; // Import models import '../models/daily_activity_summary_model.dart'; class ActivityService { final String _gatewayBaseUrl = API_ENDPOINT; // Đảm bảo apiEndpoint đã được định nghĩa final FlutterSecureStorage _secureStorage = const FlutterSecureStorage(); Future<String?> _getToken() async { return await _secureStorage.read(key: 'user_token'); } Future<DailyActivitySummary> getTodayActivitySummary() async { final token = await _getToken(); if (token == null) throw Exception('User not authenticated'); // Endpoint ví dụ: /daily-activities/today (Service B) final response = await http.get( Uri.parse('$_gatewayBaseUrl/daily-activities/today'), headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', }, ); if (response.statusCode == 200) { final Map<String, dynamic> data = jsonDecode(response.body); // Giả sử API Gateway trả về trực tiếp object data, không có cấu trúc IResult // Nếu có IResult, bạn cần parse nó trước return DailyActivitySummary.fromJson( data['data'] ?? data, ); // Ưu tiên data['data'] nếu có IResult } else { print( 'Failed to load today summary: ${response.statusCode} ${response.body}', ); throw Exception('Failed to load today\'s activity summary'); } } Future<List<ActivityProgressData>> getActivityProgress(String period) async { // period: "weekly" or "monthly" final token = await _getToken(); if (token == null) throw Exception('User not authenticated'); // Endpoint ví dụ: /daily-activities/progress?period=weekly (Service B) final response = await http.get( Uri.parse('$_gatewayBaseUrl/daily-activities/progress?period=$period'), headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', }, ); if (response.statusCode == 200) { final Map<String, dynamic> responseData = jsonDecode(response.body); // Giả sử API Gateway trả về trực tiếp mảng data, không có cấu trúc IResult // Hoặc nếu có IResult thì là responseData['data'] final List<dynamic> data = responseData['data'] as List<dynamic>? ?? responseData as List<dynamic>; return data .map( (json) => ActivityProgressData.fromJson(json as Map<String, dynamic>), ) .toList(); } else { print( 'Failed to load activity progress: ${response.statusCode} ${response.body}', ); throw Exception('Failed to load activity progress'); } } Future<List<LatestActivity>> getLatestActivities({int count = 2}) async { final token = await _getToken(); if (token == null) throw Exception('User not authenticated'); // Endpoint ví dụ: /activities/latest?count=2 (Service B, có thể tổng hợp) final response = await http.get( Uri.parse('$_gatewayBaseUrl/activities/latest?count=$count'), headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', }, ); if (response.statusCode == 200) { final Map<String, dynamic> responseData = jsonDecode(response.body); final List<dynamic> data = responseData['data'] as List<dynamic>? ?? responseData as List<dynamic>; return data .map((json) => LatestActivity.fromJson(json as Map<String, dynamic>)) .toList(); } else { print( 'Failed to load latest activities: ${response.statusCode} ${response.body}', ); throw Exception('Failed to load latest activities'); } } Future<List<HeartRateDataPoint>> getTodayHeartRate() async { final token = await _getToken(); if (token == null) throw Exception('Người dùng chưa được xác thực'); final uri = Uri.parse('$_gatewayBaseUrl/heartrate/today'); print("Calling API: GET $uri"); try { final response = await http.get( uri, headers: {'Authorization': 'Bearer $token'}, ); if (response.statusCode == 200) { final apiResult = ApiResult<List<dynamic>>.fromJson( jsonDecode(response.body), (data) => data as List<dynamic>, ); if (apiResult.succeeded && apiResult.data != null) { return apiResult.data! .map( (json) => HeartRateDataPoint.fromJson(json as Map<String, dynamic>), ) .toList(); } else { return []; // Trả về rỗng nếu không có dữ liệu } } else { throw Exception( 'Lỗi tải dữ liệu nhịp tim. Mã lỗi: ${response.statusCode}', ); } } catch (e) { print('Error in getTodayHeartRate: $e'); throw Exception('Đã có lỗi xảy ra khi tải dữ liệu nhịp tim.'); } } } fiix dùm tôi các lỗi trên
Tôi sẽ sửa các lỗi overflow và lỗi tải hình ảnh trong mã của bạn:
latest_activity_row.dart(525 pixels overflow):Cách sửa:
mainAxisSize: MainAxisSize.min để giới hạn chiều rộng của Rowoverflow: TextOverflow.ellipsis cho Texttoday_target_cell.dart(1-2 pixels overflow):Cách sửa:
mainAxisSize: MainAxisSize.min cho Columnoverflow: TextOverflow.ellipsis cho Textactivity_tracker_view.dart(3 pixels overflow):Cách sửa:
constraints: BoxConstraints(maxWidth: media.width) cho ContainercrossAxisAlignment: CrossAxisAlignment.start cho ColumnCách sửa:
_buildImage() trong latest_activity_row.dartCách sửa:
android:enableOnBackInvokedCallback="true" vào thẻ <application>Các thay đổi này sẽ giúp khắc phục tất cả các lỗi bạn đang gặp phải!
import 'package:fitness_health/common_widget/icon_title_next_row.dart';
import 'package:fitness_health/common_widget/round_button.dart';
import 'package:fitness_health/view/photo_progress/result_view.dart';
import 'package:flutter/material.dart';
import '../../common/colo_extension.dart';
class ComparisonView extends StatefulWidget {
const ComparisonView({super.key});
@override
State<ComparisonView> createState() => _ComparisonViewState();
}
class _ComparisonViewState extends State<ComparisonView> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: TColor.white,
centerTitle: true,
elevation: 0,
leading: InkWell(
onTap: () {
Navigator.pop(context);
},
child: Container(
margin: const EdgeInsets.all(8),
height: 40,
width: 40,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.lightGray,
borderRadius: BorderRadius.circular(10),
),
child: Image.asset(
"assets/img/black_btn.png",
width: 15,
height: 15,
fit: BoxFit.contain,
),
),
),
title: Text(
"Comparison",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700,
),
),
actions: [
InkWell(
onTap: () {},
child: Container(
margin: const EdgeInsets.all(8),
height: 40,
width: 40,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.lightGray,
borderRadius: BorderRadius.circular(10),
),
child: Image.asset(
"assets/img/more_btn.png",
width: 15,
height: 15,
fit: BoxFit.contain,
),
),
),
],
),
backgroundColor: TColor.white,
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
child: Column(
children: [
IconTitleNextRow(
icon: "assets/img/date.png",
title: "Select Month 1",
time: "May",
onPressed: () {},
color: TColor.lightGray,
),
const SizedBox(height: 15),
IconTitleNextRow(
icon: "assets/img/date.png",
title: "Select Month 2",
time: "select Month",
onPressed: () {},
color: TColor.lightGray,
),
const Spacer(),
RoundButton(
title: "Compare",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder:
(context) => ResultView(
date1: DateTime(2023, 5, 1),
date2: DateTime(2023, 6, 1),
),
),
);
},
),
const SizedBox(height: 15),
],
),
),
);
}
}
chuyển các giao diện này thành tiếng việt cho tôi
Tôi sẽ chuyển đổi tất cả các giao diện này sang tiếng Việt cho bạn:
_getVietnameseMonth() để chuyển đổi tháng sang tiếng ViệtTất cả các giao diện đã được chuyển đổi hoàn toàn sang tiếng Việt với cách diễn đạt tự nhiên và phù hợp với người dùng Việt Nam!
The argument type 'Future<void> Function()?' can't be assigned to the parameter type 'VoidCallback'. dartargument_type_not_assignable
onPressed: _isLoading ? null : _handleSaveSchedule,
The named parameter 'trailing' isn't defined.
Try correcting the name to an existing named parameter's name, or defining a named parameter with the name 'trailing'.dartundefined_named_parameter
fix 2 lỗi trên dùm tôi ở 2 file tôi vừa gửi