diff --git a/android/app/src/main/res/mipmap-hdpi/launcher_icon.png b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png index 4f9ad06..ae2bfb0 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/launcher_icon.png and b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/launcher_icon.png b/android/app/src/main/res/mipmap-mdpi/launcher_icon.png index 5543c04..5c16081 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/launcher_icon.png and b/android/app/src/main/res/mipmap-mdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png index 60c2fe4..5c1a108 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png and b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png index db7157c..f3a6c71 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png and b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png index eabcb02..2d823b2 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png and b/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png differ diff --git a/assets/icon/icon.png b/assets/icon/icon.png deleted file mode 100644 index f46c9a7..0000000 Binary files a/assets/icon/icon.png and /dev/null differ diff --git a/assets/icon/logo.png b/assets/icon/logo.png new file mode 100644 index 0000000..04123d3 Binary files /dev/null and b/assets/icon/logo.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index f995caa..f85ce37 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index 0b993e3..68883c5 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index d2a91bc..e2dc871 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index e72ecd6..513dc4e 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 5efe801..4e8b06f 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index cb009e1..7395da5 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index a21ce08..33906ef 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index d2a91bc..e2dc871 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index 144f62f..002c3cc 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index efa9ec6..20f9abf 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png index 35b89dd..d027f8b 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png index f64e14e..98c08df 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png index da7cc25..c8a2b4c 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png index 90d7011..39a179d 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index efa9ec6..20f9abf 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index c553c10..e1607fe 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png index 4f9ad06..ae2bfb0 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png index db7157c..f3a6c71 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index a55ce3a..9a65f55 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 791fb63..993a126 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index 43a43fd..60eee18 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/lib/application.dart b/lib/application.dart index 74e5808..49628ce 100644 --- a/lib/application.dart +++ b/lib/application.dart @@ -1,6 +1,7 @@ import 'dart:developer'; import 'package:flutter/material.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import 'package:reverse_nn/application/controllers/application_controller.dart'; @@ -18,6 +19,16 @@ class ReversNNApplication extends StatelessWidget { return GetMaterialApp( title: 'Реверс НН', + + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalCupertinoLocalizations.delegate + ], + + supportedLocales: const [ + Locale('ru') + ], + theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal, brightness: Brightness.light), useMaterial3: true, diff --git a/lib/application/controllers/calendar_schedule_controller.dart b/lib/application/controllers/calendar_schedule_controller.dart index 213e1fe..30ad306 100644 --- a/lib/application/controllers/calendar_schedule_controller.dart +++ b/lib/application/controllers/calendar_schedule_controller.dart @@ -18,7 +18,22 @@ class CalendarScheduleController extends GetxController { loading = false.obs; update(); } - static void openScreen() async { - Get.to(() => const CalendarScreen()); + static void openScreen() async { Get.to(() => const CalendarScreen()); } + + void goToConcreteDay(DateTime day) async { + date = (day.copyWith(hour: 12, minute: 0, millisecond: 0, microsecond: 0)).obs; + loadSchedule(date.value); + } + + void goToPrevDay() async { + if(date.value.isBefore(DateTime(2024, 8, 1, 23, 59))) return; + date = (date.value.copyWith().subtract(const Duration(days: 1)).copyWith(hour: 12, minute: 0)).obs; + loadSchedule(date.value); + } + + void goToNextDay() async { + if(date.value.isAfter(DateTime(2025, 12, 31))) return; + date = (date.value.copyWith().add(const Duration(days: 1)).copyWith(hour: 12, minute: 0)).obs; + loadSchedule(date.value); } } \ No newline at end of file diff --git a/lib/application/controllers/schedule_controller.dart b/lib/application/controllers/schedule_controller.dart index 8bfeb17..e5472f6 100644 --- a/lib/application/controllers/schedule_controller.dart +++ b/lib/application/controllers/schedule_controller.dart @@ -1,5 +1,6 @@ import 'dart:developer'; +import 'package:flutter/foundation.dart'; import 'package:get/get.dart'; import 'package:reverse_nn/application/services/schedule.dart'; @@ -12,6 +13,7 @@ class ScheduleController extends GetxController { } void updateCurrentSchedule() async { + if(kDebugMode) { log('update current status'); } currentSchedule = (await ScheduleService().getCurrentStatus()).obs; update(); diff --git a/lib/application/services/schedule.dart b/lib/application/services/schedule.dart index c65036c..8cff9c6 100644 --- a/lib/application/services/schedule.dart +++ b/lib/application/services/schedule.dart @@ -66,9 +66,10 @@ class ScheduleService { }).toList(); } - Future>?> getScheduleByDate(DateTime datetime) async { - final datetimeStartWithOffset = datetime.copyWith(hour: 0, minute: 0, second: 0, microsecond: 0, millisecond: 0) - .add(dayOffset); + Future>?> getScheduleByDate(DateTime datetime, {bool force = false}) async { + final dateStart = datetime.copyWith(hour: 0, minute: 0, second: 0, microsecond: 0, millisecond: 0); + final dateEnd = datetime.copyWith(hour: 23, minute: 59, second: 59, microsecond: 999, millisecond: 999); + final datetimeStartWithOffset = dateStart.copyWith().add(dayOffset); final DateTime usedScheduleDatetime = datetime.isAfter(datetimeStartWithOffset) ? datetime @@ -93,23 +94,34 @@ class ScheduleService { for (var i = 0; i < schedule.length; i++) { final scheduleItem = schedule[i]; final int duration = (scheduleItem['duration'] as int); - final DateTime start = datetimeStartWithOffset.copyWith().add(Duration(minutes: durationOffset)); + DateTime start = datetimeStartWithOffset.copyWith().add(Duration(minutes: durationOffset)); DateTime end = datetimeStartWithOffset.copyWith().add(Duration(minutes: durationOffset + duration)); durationOffset += duration; - bool showEndDate = false; - if(i == (schedule.length -1)) { - final scheduleNextDay = await getScheduleByDate(datetime.copyWith().add(const Duration(days: 1))); - final firstScheduleElement = scheduleNextDay?[0]; - if(firstScheduleElement != null && (firstScheduleElement['direction'] as String) == (scheduleItem['direction'] as String)) { - end = end.add(Duration(minutes: firstScheduleElement['duration'] as int)); - showEndDate = true; + if(!force) { + if(i == 0) { + final schedulePrevDay = await getScheduleByDate(datetime.copyWith().subtract(const Duration(days: 1)), force: true); + final lastScheduleElement = schedulePrevDay?.last; + if(lastScheduleElement != null && (lastScheduleElement['direction'] as String) == (scheduleItem['direction'] as String)) { + start = start.subtract(Duration(minutes: lastScheduleElement['duration'] as int)); + } + } + + if(i == (schedule.length -1)) { + final scheduleNextDay = await getScheduleByDate(datetime.copyWith().add(const Duration(days: 1)), force: true); + final firstScheduleElement = scheduleNextDay?.first; + if(firstScheduleElement != null && (firstScheduleElement['direction'] as String) == (scheduleItem['direction'] as String)) { + end = end.add(Duration(minutes: firstScheduleElement['duration'] as int)); + } } } schedule[i]['start'] = start; + schedule[i]['show_start_date'] = !(start.isAfter(dateStart) && start.isBefore(dateEnd)); schedule[i]['end'] = end; + schedule[i]['show_end_date'] = !(end.isAfter(dateStart) && end.isBefore(dateEnd)); } + return schedule; } @@ -118,39 +130,12 @@ class ScheduleService { final List>? schedule = await getScheduleByDate(now); if(schedule == null) return null; - DateTime datetimeStartWithOffset = now.copyWith(hour: 0, minute: 0, second: 0, microsecond: 0, millisecond: 0) - .add(dayOffset); - - if(now.isBefore(datetimeStartWithOffset)) { - datetimeStartWithOffset = datetimeStartWithOffset.subtract(const Duration(days: 1)); - } - - int durationOffset = 0; - for (var i = 0; i < schedule.length; i++) { - final scheduleItem = schedule[i]; - final int duration = (scheduleItem['duration'] as int); - final DateTime start = datetimeStartWithOffset.copyWith().add(Duration(minutes: durationOffset)); - DateTime end = datetimeStartWithOffset.copyWith().add(Duration(minutes: durationOffset + duration)); - durationOffset += duration; - - bool showEndDate = false; - - if(i == (schedule.length -1)) { - final scheduleNextDay = await getScheduleByDate(now.copyWith().add(const Duration(days: 1))); - final firstScheduleElement = scheduleNextDay?[0]; - if(firstScheduleElement != null && (firstScheduleElement['direction'] as String) == (scheduleItem['direction'] as String)) { - end = end.add(Duration(minutes: firstScheduleElement['duration'] as int)); - showEndDate = true; - } - } + for(var i = 0; i < schedule.length; i++) { + final start = schedule[i]['start']; + final end = schedule[i]['end']; if(now.isAfter(start) && now.isBefore(end)) { - return { - "direction": scheduleItem['direction'] as String, - "start": start, - "end": end, - "need_show_end_date": showEndDate, - }; + return schedule[i]; } } diff --git a/lib/ui/components/current_status_component.dart b/lib/ui/components/current_status_component.dart index bd16bcb..c5a94b1 100644 --- a/lib/ui/components/current_status_component.dart +++ b/lib/ui/components/current_status_component.dart @@ -1,8 +1,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:intl/intl.dart' show DateFormat; import 'package:reverse_nn/application/controllers/schedule_controller.dart'; -import 'package:reverse_nn/application/services/schedule.dart'; +import 'package:reverse_nn/ui/components/schedule_item_component.dart'; class CurrentStatusComponent extends StatelessWidget { const CurrentStatusComponent({super.key}); @@ -10,40 +9,13 @@ class CurrentStatusComponent extends StatelessWidget { @override Widget build(BuildContext context) { final ScheduleController controller = Get.put(ScheduleController()); - return Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primaryContainer, - borderRadius: BorderRadius.circular(10), - ), - child: Padding( - padding: const EdgeInsets.all(10), - child: GetBuilder( - builder: (scheduleController) { - return Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Icon(ScheduleService.getIconByDirection(scheduleController.currentSchedule.value?['direction']), size: 96), - const SizedBox(width: 16), - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if(scheduleController.currentSchedule.value != null) ...[ - Text(ScheduleService.formatDirection(scheduleController.currentSchedule.value?['direction'] ?? ''), style: Theme.of(context).textTheme.headlineLarge), - Text('C\t\t\t\t${formatDate(scheduleController.currentSchedule.value?['start'], showDate: scheduleController.currentSchedule.value!['need_show_end_date'])}', style: Theme.of(context).textTheme.titleMedium), - Text('До\t${formatDate(scheduleController.currentSchedule.value!['end'], showDate: scheduleController.currentSchedule.value!['need_show_end_date'])}', style: Theme.of(context).textTheme.titleMedium), - ] - ], - ) - ], - ); - } - ), - ), + + return GetBuilder( + builder: (controller) { + if(controller.currentSchedule.value == null) { return Container(); } + + return ScheduleItemComponent(item: controller.currentSchedule.value!); + } ); } - - String formatDate(DateTime date, {bool showDate = false}) => DateFormat(showDate ? 'hh:mm (dd.MM.yyyy)' : 'hh:mm').format(date); - } \ No newline at end of file diff --git a/lib/ui/components/schedule_item_component.dart b/lib/ui/components/schedule_item_component.dart new file mode 100644 index 0000000..19a4400 --- /dev/null +++ b/lib/ui/components/schedule_item_component.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart' show DateFormat; +import 'package:reverse_nn/application/services/schedule.dart'; + +class ScheduleItemComponent extends StatelessWidget { + final Map item; + const ScheduleItemComponent({super.key, required this.item}); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(top: 10), + padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.secondaryContainer, + borderRadius: BorderRadius.circular(10), + ), + alignment: Alignment.center, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon(ScheduleService.getIconByDirection(item['direction'] as String), size: 56), + const SizedBox(width: 16), + Expanded(child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _directionText(context), + _startText(context), + _endText(context), + ], + )) + ], + ), + ); + } + + String formatDate(DateTime date, {bool showDate = false}) { + return DateFormat(showDate ? 'HH:mm dd.MM.yyyy' : 'HH:mm').format(date); + } + + Widget _directionText(BuildContext context) => Text( + ScheduleService.formatDirection(item['direction'] ?? ''), + style: Theme.of(context).textTheme.headlineLarge + ); + + Widget _startText(BuildContext context) => Text( + 'C\t\t\t\t${formatDate(item['start'], showDate: item['show_start_date'] ?? false)}', + style: Theme.of(context).textTheme.titleLarge + ); + + Widget _endText(BuildContext context) => Text( + 'До\t${formatDate(item['end'], showDate: item['show_end_date'] ?? false)}', + style: Theme.of(context).textTheme.titleLarge + ); +} diff --git a/lib/ui/screens/calendar_screen.dart b/lib/ui/screens/calendar_screen.dart index 1c09fd2..878fe6c 100644 --- a/lib/ui/screens/calendar_screen.dart +++ b/lib/ui/screens/calendar_screen.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:reverse_nn/application/controllers/calendar_schedule_controller.dart'; import 'package:reverse_nn/application/services/schedule.dart'; +import 'package:reverse_nn/ui/components/schedule_item_component.dart'; import 'package:reverse_nn/ui/layouts/application_layout.dart'; import 'package:intl/intl.dart' show DateFormat; @@ -15,40 +16,42 @@ class CalendarScreen extends StatelessWidget { return ApplicationLayout( body: RefreshIndicator( onRefresh: () async { controller.loadSchedule(controller.date.value); }, - child: SingleChildScrollView( - physics: const AlwaysScrollableScrollPhysics(), + child: GetBuilder( + builder: (controller) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _SelectedDateWidget( + date: controller.date.value, + onSelectDate: controller.goToConcreteDay, + onTapPrev: controller.goToPrevDay, + onTapNext: controller.goToNextDay, + ), - child: GetBuilder( - builder: (controller) { - return Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - _SelectedDateWidget(date: controller.date.value), + if(controller.loading.value) const Padding( + padding: EdgeInsets.all(40), + child: Center(child: CircularProgressIndicator()) + ), - if(controller.loading.value) const Padding( - padding: EdgeInsets.all(40), - child: Center(child: CircularProgressIndicator()) + if(!controller.loading.value && controller.schedule.value != null) Expanded( + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: controller.schedule.value! + .map((item) => ScheduleItemComponent(item: item)) + .toList(), + ), ), - - if(!controller.loading.value && controller.schedule.value != null) ListView.builder( - shrinkWrap: true, - itemBuilder: (_, index) => _ScheduleItemWidget(item: controller.schedule.value![index]), - itemCount: controller.schedule.value!.length - ), - - - - // if(!controller.loading.value && controller.schedule.value != null) ...controller.schedule.value!.map((element) { - // return _ScheduleItemWidget(item: element); - // }), - ], - ), - ); - } - ), + ), + ], + ), + ); + } ), ), ); @@ -57,7 +60,10 @@ class CalendarScreen extends StatelessWidget { class _SelectedDateWidget extends StatelessWidget { final DateTime date; - const _SelectedDateWidget({super.key, required this.date}); + final void Function(DateTime)? onSelectDate; + final void Function()? onTapPrev; + final void Function()? onTapNext; + const _SelectedDateWidget({super.key, required this.date, this.onSelectDate, this.onTapPrev, this.onTapNext}); @override Widget build(BuildContext context) { @@ -68,47 +74,36 @@ class _SelectedDateWidget extends StatelessWidget { borderRadius: BorderRadius.circular(10), ), alignment: Alignment.center, - child: Text( - formatDate(date), - style: Theme.of(context).textTheme.displayMedium, - ), - ); - } - - String formatDate(DateTime date) { - return DateFormat('dd.MM.yyyy').format(date); - } -} - -class _ScheduleItemWidget extends StatelessWidget { - final Map item; - const _ScheduleItemWidget({super.key, required this.item}); - - @override - Widget build(BuildContext context) { - return Container( - margin: const EdgeInsets.only(top: 10), - padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.secondaryContainer, - borderRadius: BorderRadius.circular(10), - ), - alignment: Alignment.center, child: Row( - mainAxisAlignment: MainAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Icon(ScheduleService.getIconByDirection(item['direction'] as String), size: 56), - Expanded(child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text(ScheduleService.formatDirection(item['direction'] ?? ''), style: Theme.of(context).textTheme.headlineLarge), - Text('C\t\t\t\t${formatDate(item['start'])}', style: Theme.of(context).textTheme.titleMedium), - Text('До\t${formatDate(item['end'])}', style: Theme.of(context).textTheme.titleMedium), - ], - )) - ], + GestureDetector( + onTap: () { onTapPrev?.call(); }, + child: const SizedBox( + width: 40, + child: Center(child: Icon(Icons.arrow_left, size: 40)), + ), + ), + Expanded( + child: GestureDetector( + onTap: () {_openCalendar(context); }, + child: Center( + child: Text( + formatDate(date), + style: Theme.of(context).textTheme.displaySmall, + ), + ), + ), + ), + GestureDetector( + onTap: () { onTapNext?.call(); }, + child: const SizedBox( + width: 40, + child: Center(child: Icon(Icons.arrow_right, size: 40)), + ), + ), + ] ), ); } @@ -116,6 +111,19 @@ class _ScheduleItemWidget extends StatelessWidget { String formatDate(DateTime date) { return DateFormat('dd.MM.yyyy').format(date); } + + void _openCalendar(BuildContext context) async { + DateTime now = DateTime.now(); + DateTime? picked = await showDatePicker( + context: context, + initialDate: now, + firstDate: DateTime(2024, 8, 1, 12), + lastDate: DateTime(2025, 12, 31, 12), + locale: const Locale('ru') + ); + + if(picked != null) { onSelectDate?.call(picked); } + } } diff --git a/lib/widgets/schedule_element_widget.dart b/lib/widgets/schedule_element_widget.dart index 2656015..aca4cff 100644 --- a/lib/widgets/schedule_element_widget.dart +++ b/lib/widgets/schedule_element_widget.dart @@ -43,21 +43,6 @@ class CurrentReversWidget extends StatelessWidget { ) ], ), - - // child: Column( - // mainAxisAlignment: MainAxisAlignment.start, - // crossAxisAlignment: CrossAxisAlignment.center, - // children: [ - // const Text('Текущий статус реверса:', style: TextStyle( - // color: Colors.black87, - // fontSize: 14.0 - // )), - // Text(scheduleElement.direction.displayName, style: const TextStyle( - // color: Colors.black, - // fontSize: 32.0 - // ),), - // ], - // ), ); } } diff --git a/pubspec.lock b/pubspec.lock index 6d4926c..3d9c286 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -126,6 +126,11 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" flutter_test: dependency: "direct dev" description: flutter @@ -147,22 +152,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" - http: - dependency: transitive - description: - name: http - sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 - url: "https://pub.dev" - source: hosted - version: "1.2.2" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.dev" - source: hosted - version: "4.0.2" image: dependency: transitive description: @@ -175,10 +164,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "99f282cb0e02edcbbf8c6b3bbc7c90b65635156c412e58f3975a7e55284ce685" + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf url: "https://pub.dev" source: hosted - version: "0.20.0" + version: "0.19.0" json_annotation: dependency: transitive description: @@ -408,14 +397,6 @@ packages: url: "https://pub.dev" source: hosted version: "14.2.5" - web: - dependency: transitive - description: - name: web - sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" - url: "https://pub.dev" - source: hosted - version: "0.5.1" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 2cfed19..467ddc9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.0+2 +version: 1.1.0+3 environment: sdk: '>=3.3.3 <4.0.0' @@ -30,15 +30,17 @@ environment: dependencies: flutter: sdk: flutter - sprintf: "^7.0.0" + flutter_localizations: + sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.6 + intl: ^0.19.0 get: ^4.6.6 - intl: ^0.20.0 get_storage: ^2.1.1 + sprintf: "^7.0.0" dev_dependencies: flutter_test: @@ -55,7 +57,7 @@ dev_dependencies: flutter_launcher_icons: android: "launcher_icon" ios: true - image_path: "assets/icon/icon.png" + image_path: "assets/icon/logo.png" min_sdk_android: 21 # android min sdk min:16, default 21 # For information on the generic Dart part of this file, see the