From d530b6b409ab306869a5511192a2c8db9248a9b3 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Mon, 15 Jan 2024 15:44:23 +0300 Subject: [PATCH] Finished weight chart --- lib/localization/ru/ru_translations.dart | 3 +- .../auth/auth_screen/auth_screen.dart | 3 +- .../bloc/my_profile_bloc.dart | 32 ++- .../bloc/my_profile_event.dart | 5 + .../bloc/my_profile_state.dart | 18 +- .../my_profile_screen/my_profile_screen.dart | 236 +++++++++++++----- .../additional_information_screen.dart | 3 +- pubspec.yaml | 1 + 8 files changed, 226 insertions(+), 75 deletions(-) diff --git a/lib/localization/ru/ru_translations.dart b/lib/localization/ru/ru_translations.dart index 49b8047d..4bbe7074 100644 --- a/lib/localization/ru/ru_translations.dart +++ b/lib/localization/ru/ru_translations.dart @@ -106,7 +106,8 @@ final Map ru = { "user_authorization": "Аутентификация", // Личный кабинет Screen - "Dmitry_Koval": "Дмитрий Коваль", "done": "Готово", "exit": "Выйти", + "loading": "Загрузка...", + "exit": "Выйти", "my_blog": "Мой блог", "lbl_01_04_21": "01.04.21", "lbl_01_05_21": "01.05.21", // Настройки Screen diff --git a/lib/presentation/auth/auth_screen/auth_screen.dart b/lib/presentation/auth/auth_screen/auth_screen.dart index 61d25848..6a0c3447 100644 --- a/lib/presentation/auth/auth_screen/auth_screen.dart +++ b/lib/presentation/auth/auth_screen/auth_screen.dart @@ -83,7 +83,8 @@ class AuthScreen extends StatelessWidget { 'password': state.passwordController!.text, }; final response = await http.post( - Uri.parse('http://10.55.5.126:1092/api/login'), + Uri.parse( + 'https://emaibo4wahye-dev3.eatvio.ru/api/login'), headers: {'Content-Type': 'application/json'}, body: json.encode(credentials), encoding: utf8); diff --git a/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart b/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart index 51efc8f8..eafd579f 100644 --- a/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart +++ b/lib/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart @@ -1,3 +1,5 @@ +import 'dart:ffi'; + import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; import '/core/app_export.dart'; @@ -14,6 +16,29 @@ class MyProfileBloc extends Bloc { MyProfileBloc(MyProfileState initialState) : super(initialState) { on(_onInitialize); } + Stream mapEventToState(MyProfileEvent event) async* { + if (event is LogoutEvent) { + // Удаление токенов из баз данных Hive и Laravel Sanctum + var box = await Hive.openBox('myBox'); + final token = box.get('token'); + box.delete('token'); + + final response = await http.post( + Uri.parse('http://10.55.5.126:1092/api/profile/logout'), + headers: { + 'Authorization': 'Bearer $token', + }, + ); + + if (response.statusCode == 200) { + // Токен Laravel Sanctum успешно удален из базы данных + } else { + // Обработка ошибки + } + + // Перенаправление пользователя на экран AuthScreen + } + } _onInitialize( MyProfileInitialEvent event, @@ -22,12 +47,15 @@ class MyProfileBloc extends Bloc { final box = await Hive.openBox('token'); final token = box.get('token'); final response = await http.get( - Uri.parse('http://10.55.5.126:1092/api/profile/index'), + Uri.parse('https://emaibo4wahye-dev3.eatvio.ru/api/profile/index'), headers: { 'Authorization': 'Bearer $token', }, ); final data = jsonDecode(response.body); - emit(state.copyWith(user: data)); + emit(state.copyWith( + user: data['user'], + chartPoints: data['chartPoints'], + userDetails: data['userDetails'])); } } diff --git a/lib/presentation/profile/my_profile_screen/bloc/my_profile_event.dart b/lib/presentation/profile/my_profile_screen/bloc/my_profile_event.dart index 99c025a4..0eae41e5 100644 --- a/lib/presentation/profile/my_profile_screen/bloc/my_profile_event.dart +++ b/lib/presentation/profile/my_profile_screen/bloc/my_profile_event.dart @@ -14,3 +14,8 @@ class MyProfileInitialEvent extends MyProfileEvent { @override List get props => []; } + +class LogoutEvent extends Equatable { + @override + List get props => []; +} diff --git a/lib/presentation/profile/my_profile_screen/bloc/my_profile_state.dart b/lib/presentation/profile/my_profile_screen/bloc/my_profile_state.dart index c6fa75ac..1232781a 100644 --- a/lib/presentation/profile/my_profile_screen/bloc/my_profile_state.dart +++ b/lib/presentation/profile/my_profile_screen/bloc/my_profile_state.dart @@ -4,19 +4,25 @@ part of 'my_profile_bloc.dart'; /// Represents the state of MyProfile in the application. class MyProfileState extends Equatable { - MyProfileState({this.myProfileModelObj, this.user}); + MyProfileState( + {this.myProfileModelObj, this.user, this.userDetails, this.chartPoints}); MyProfileModel? myProfileModelObj; Map? user; + Map? userDetails; + Map? chartPoints; @override - List get props => [ - myProfileModelObj, - ]; + List get props => [myProfileModelObj, user, chartPoints]; MyProfileState copyWith( - {MyProfileModel? myProfileModelObj, Map? user}) { + {MyProfileModel? myProfileModelObj, + Map? user, + Map? userDetails, + Map? chartPoints}) { return MyProfileState( myProfileModelObj: myProfileModelObj ?? this.myProfileModelObj, - user: user ?? this.user); + user: user ?? this.user, + userDetails: userDetails ?? this.userDetails, + chartPoints: chartPoints ?? this.chartPoints); } } diff --git a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart index f2d5b75d..88fb2c42 100644 --- a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart +++ b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart @@ -1,7 +1,6 @@ import 'bloc/my_profile_bloc.dart'; import 'models/my_profile_model.dart'; import 'package:eatvio_app/core/app_export.dart'; -import 'package:eatvio_app/widgets/app_bar/appbar_leading_image.dart'; import 'package:eatvio_app/widgets/app_bar/appbar_subtitle.dart'; import 'package:eatvio_app/widgets/app_bar/appbar_title_circleimage.dart'; import 'package:eatvio_app/widgets/app_bar/custom_app_bar.dart'; @@ -9,6 +8,7 @@ import 'package:eatvio_app/widgets/custom_bottom_bar.dart'; import 'package:eatvio_app/widgets/app_bar/exit_button.dart'; import 'package:eatvio_app/widgets/next_step_button.dart'; import 'package:flutter/material.dart'; +import 'dart:math'; import 'package:fl_chart/fl_chart.dart'; class MyProfileScreen extends StatelessWidget { @@ -28,7 +28,8 @@ class MyProfileScreen extends StatelessWidget { builder: (context, state) { return SafeArea( child: Scaffold( - appBar: _buildAppBar(context, state.user!['name']), + appBar: + _buildAppBar(context, state.user?['name'] ?? 'loading'.tr), body: Container( width: double.maxFinite, padding: @@ -38,15 +39,17 @@ class MyProfileScreen extends StatelessWidget { SizedBox(height: 15.v), _buildSettings(context), SizedBox(height: 30.v), - /*_buildChart( - [70.0, 72.0, 71.0, 73.0], - [ - DateTime(2021, 10, 1), - DateTime(2021, 10, 2), - DateTime(2021, 10, 3), - DateTime(2021, 10, 4), - ], - ),*/ + _buildChart( + context, + state.chartPoints?.values + .map((e) => e['weight']) + .toList() + .map((i) => i.toDouble()) + .toList() ?? + [0.0, 0.0, 0.0, 0.0], + state.chartPoints?.values + .map((e) => e['created_at']) + .toList()), SizedBox(height: 15.v), _buildWidget(context), SizedBox(height: 5.v), @@ -60,12 +63,6 @@ class MyProfileScreen extends StatelessWidget { return CustomAppBar( height: 54.v, leadingWidth: 28.h, - leading: AppbarLeadingImage( - imagePath: ImageConstant.imgArrowLeft, - margin: EdgeInsets.only(left: 15.h, top: 13.v, bottom: 14.v), - onTap: () { - onTapArrowLeft(context); - }), title: Padding( padding: EdgeInsets.only(left: 20.h), child: Row(children: [ @@ -76,8 +73,10 @@ class MyProfileScreen extends StatelessWidget { ])), actions: [ ExitButton( - text: "exit".tr, - margin: EdgeInsets.symmetric(horizontal: 16.h, vertical: 17.v)) + text: "exit".tr, + margin: EdgeInsets.symmetric(horizontal: 16.h, vertical: 17.v), + onTap: () {}, + ) ]); } @@ -122,49 +121,163 @@ class MyProfileScreen extends StatelessWidget { } /// Section Widget -/* Widget _buildChart(List values, List dates) { - // Создаем список точек для графика - final List spots = []; - for (int i = 0; i < values.length; i++) { - spots.add(FlSpot(i.toDouble(), values[i])); - } + Widget _buildChart(BuildContext context, List chartPoints, dates) { + // Определение данных для графика + /* List chartData = chartPoints + .map((point) => + FlSpot(point['created_at'] as double, point['weight'] as double)) + .toList(); */ - return LineChart( - LineChartData( - // Ось X - даты - minX: 0, - maxX: dates.length.toDouble() - 1, - // Ось Y - значения - minY: 0, - maxY: values.reduce((a, b) => a > b ? a : b) + 10, - // Список точек - lineBarsData: [ - LineChartBarData( - spots: spots, - isCurved: false, - color: Colors.blue, - barWidth: 3, - ), - ], - // Оси и легенда - titlesData: FlTitlesData( - bottomTitles: AxisTitles(sideTitles:SideTitles( - showTitles: true, - getTitlesWidget: (value) { - final index = value.toInt(); - return '${dates[index].day}.${dates[index].month}'; - }, - )), - leftTitles: AxisTitles(sideTitles: SideTitles( - showTitles: true, - getTitlesWidget: (value,TitleMeta ) { - return '${value.toInt()}'; +// Определение осей графика + List spots = []; + for (int i = 0; i < 4; i++) { + spots.add( + FlSpot((i * 10 / 10) + 1, chartPoints[i]), + ); + } + print(spots); + + Widget bottomTitleWidgets(double value, TitleMeta meta, double chartWidth) { + if (value % 1 != 0) { + return Container(); + } + final style = TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: min(18, 18 * chartWidth / 300), + ); + return SideTitleWidget( + axisSide: meta.axisSide, + space: 16, + child: Text(meta.formattedValue, style: style), + ); + } + + Widget leftTitleWidgets(double value, TitleMeta meta, double chartWidth) { + final style = TextStyle( + color: Colors.blue, + fontWeight: FontWeight.bold, + fontSize: min(18, 18 * chartWidth / 300), + ); + return SideTitleWidget( + axisSide: meta.axisSide, + space: 16, + child: Text(meta.formattedValue, style: style), + ); + } + + return Padding( + padding: const EdgeInsets.only( + left: 12, + bottom: 12, + right: 20, + top: 18, + ), + child: AspectRatio( + aspectRatio: 1, + child: LayoutBuilder( + builder: (context, constraints) { + return LineChart( + LineChartData( + lineTouchData: LineTouchData( + touchTooltipData: LineTouchTooltipData( + maxContentWidth: 100, + tooltipBgColor: Colors.black, + getTooltipItems: (touchedSpots) { + return touchedSpots.map((LineBarSpot touchedSpot) { + final textStyle = TextStyle( + color: touchedSpot.bar.gradient?.colors[0] ?? + touchedSpot.bar.color, + fontWeight: FontWeight.bold, + fontSize: 14, + ); + return LineTooltipItem( + '${touchedSpot.x}, ${touchedSpot.y.toStringAsFixed(2)}', + textStyle, + ); + }).toList(); + }, + ), + handleBuiltInTouches: true, + getTouchLineStart: (data, index) => 0, + ), + lineBarsData: [ + LineChartBarData( + color: Colors.pink, + spots: spots, + isCurved: true, + isStrokeCapRound: true, + barWidth: 3, + belowBarData: BarAreaData( + show: false, + ), + dotData: const FlDotData(show: false), + ), + ], + minY: chartPoints.reduce( + (value, element) => value < element ? value : element), + maxY: chartPoints.reduce( + (value, element) => value > element ? value : element), + minX: 1, + maxX: 4, + titlesData: FlTitlesData( + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + getTitlesWidget: (value, meta) => + leftTitleWidgets(value, meta, constraints.maxWidth), + reservedSize: 56, + ), + drawBelowEverything: true, + ), + rightTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + getTitlesWidget: (value, meta) => + bottomTitleWidgets(value, meta, constraints.maxWidth), + reservedSize: 36, + interval: 1, + ), + drawBelowEverything: true, + ), + topTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + ), + gridData: FlGridData( + show: true, + drawHorizontalLine: true, + drawVerticalLine: true, + horizontalInterval: 1.5, + verticalInterval: 5, + checkToShowHorizontalLine: (value) { + return value.toInt() == 0; + }, + getDrawingHorizontalLine: (_) => FlLine( + color: Colors.blue.withOpacity(1), + dashArray: [8, 2], + strokeWidth: 0.8, + ), + getDrawingVerticalLine: (_) => FlLine( + color: Colors.blue.withOpacity(1), + dashArray: [8, 2], + strokeWidth: 0.8, + ), + checkToShowVerticalLine: (value) { + return value.toInt() == 0; + }, + ), + borderData: FlBorderData(show: false), + ), + ); }, ), - )), - ), - ); -}*/ + ), + ); + } /// Section Widget Widget _buildWidget(BuildContext context) { @@ -341,9 +454,4 @@ class MyProfileScreen extends StatelessWidget { ])) ])); } - - /// Navigates to the previous screen. - onTapArrowLeft(BuildContext context) { - NavigatorService.goBack(); - } } diff --git a/lib/presentation/registration/additional_information_screen/additional_information_screen.dart b/lib/presentation/registration/additional_information_screen/additional_information_screen.dart index 34fe4bf2..4d3f3b3c 100644 --- a/lib/presentation/registration/additional_information_screen/additional_information_screen.dart +++ b/lib/presentation/registration/additional_information_screen/additional_information_screen.dart @@ -72,7 +72,8 @@ class AdditionalInformationScreen extends StatelessWidget { .userRegistrationSheet; sheet.additionalInfo = state.editTextController!.text; final response = await http.post( - Uri.parse('http://10.55.5.126:1092/api/register'), + Uri.parse( + 'https://emaibo4wahye-dev3.eatvio.ru/api/register'), headers: {'Content-Type': 'application/json'}, body: json.encode(sheet), ); diff --git a/pubspec.yaml b/pubspec.yaml index f9601192..1d6f969d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,6 +20,7 @@ dependencies: isar_flutter_libs: ^4.0.0-dev.13 path_provider: ^2.1.0 fl_chart: ^0.66.0 + flutter_spinkit: ^5.0.0 dev_dependencies: flutter_test: