diff --git a/.fvmrc b/.fvmrc index 77dfa45..2c69a1c 100644 --- a/.fvmrc +++ b/.fvmrc @@ -1,4 +1,7 @@ { "flutter": "3.19.6", - "flavors": {} + "flavors": {}, + "runPubGetOnSdkChanges": true, + "updateVscodeSettings": true, + "updateGitIgnore": true } \ No newline at end of file diff --git a/analysis_options.yaml b/analysis_options.yaml index b8b5470..44077ab 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -17,7 +17,7 @@ analyzer: - packages/** - "**.gen.dart" plugins: - - custom-lint + - custom_lint linter: # The lint rules applied to this project can be customized in the diff --git a/assets/l10n/fi-FI/localizations.json b/assets/l10n/fi-FI/localizations.json index 1f92835..bda1dcb 100644 --- a/assets/l10n/fi-FI/localizations.json +++ b/assets/l10n/fi-FI/localizations.json @@ -9,7 +9,8 @@ "login": "Kirjaudu", "errors": { "listPublicTrucks": "Virhe listatessa ajoneuvoja", - "listRoutes": "Virhe listatessa reittejä" + "listRoutes": "Virhe listatessa reittejä", + "findTask": "Virhe haettaessa tehtävää" }, "equipment": "Kalusto", "routes": "Reitit", @@ -20,5 +21,13 @@ "tasks": "Tehtävät", "noTasksForRoute": "Ei tehtäviä", "load": "Lastaus", - "unload": "Purku" + "unload": "Purku", + "backToTaskList": "Takaisin tehtävälistaan", + "start": "Aloita", + "end": "Lopeta", + "waybill": "Rahtikirja", + "sender": "Lähettäjä", + "recipient": "Vastaanottaja", + "pointOfDeparture": "Lähtöpaikka", + "destination": "Määräpaikka" } \ No newline at end of file diff --git a/lib/app/openapi_config.dart b/lib/app/openapi_config.dart index 139a7a2..2bb3a33 100644 --- a/lib/app/openapi_config.dart +++ b/lib/app/openapi_config.dart @@ -1,12 +1,12 @@ -// Openapi Generator last run: : 2024-04-24T09:27:04.483875 +// Openapi Generator last run: : 2024-05-02T16:32:35.026923 import "package:openapi_generator_annotations/openapi_generator_annotations.dart"; @Openapi( inputSpec: InputSpec( - path: "specs/specs/app.yaml", + path: "../vp-kuljetus-transport-management-specs/specs/app.yaml", ), generatorName: Generator.dio, - outputDirectory: "../packages/tms_api", + outputDirectory: "./packages/tms_api", additionalProperties: DioProperties(pubName: "tms_api"), ) class OpenApiGeneratorConfig {} \ No newline at end of file diff --git a/lib/app/router.dart b/lib/app/router.dart index 188dfd2..c1a4d1e 100644 --- a/lib/app/router.dart +++ b/lib/app/router.dart @@ -90,7 +90,7 @@ GoRouter router(final RouterRef ref) { routes: [ GoRoute( name: "taskDetails", - path: ":taskId", + path: "task-details", pageBuilder: (final context, final state) => const NoTransitionPage(child: TaskDetailsScreen()), ), diff --git a/lib/app/router.g.dart b/lib/app/router.g.dart index da4de17..c21d934 100644 --- a/lib/app/router.g.dart +++ b/lib/app/router.g.dart @@ -6,7 +6,7 @@ part of 'router.dart'; // RiverpodGenerator // ************************************************************************** -String _$routerHash() => r'bfb567c1f68811f8d9a769b83013bb5baa14af4b'; +String _$routerHash() => r'7d518c9c53c99a7ab1bdb05694ab2f945ed5809e'; /// See also [router]. @ProviderFor(router) diff --git a/lib/app/theme.dart b/lib/app/theme.dart index 4e66917..eff893d 100644 --- a/lib/app/theme.dart +++ b/lib/app/theme.dart @@ -6,6 +6,7 @@ ThemeData getTheme(final BuildContext context) { colorScheme: ColorScheme.fromSeed( seedColor: const Color(0xFF00414F), secondary: const Color(0xFF547476), + error: const Color(0xFFEE3912), ), useMaterial3: true, ); @@ -47,5 +48,17 @@ ThemeData getTheme(final BuildContext context) { ), ), ), + filledButtonTheme: FilledButtonThemeData( + style: ButtonStyle( + padding: const MaterialStatePropertyAll( + EdgeInsets.symmetric(vertical: 16, horizontal: 16), + ), + shape: const MaterialStatePropertyAll(StadiumBorder()), + surfaceTintColor: const MaterialStatePropertyAll(Colors.white), + textStyle: MaterialStatePropertyAll( + themeWithFonts.textTheme.titleMedium, + ), + ), + ), ); } diff --git a/lib/models/views/freight_card.dart b/lib/models/views/freight_card.dart new file mode 100644 index 0000000..0edfe28 --- /dev/null +++ b/lib/models/views/freight_card.dart @@ -0,0 +1,19 @@ +import "package:tms_api/tms_api.dart"; + +class FreightCardData { + const FreightCardData({ + required this.freight, + required this.senderSite, + required this.recipientSite, + required this.pointOfDepartureSite, + required this.destinationSite, + required this.freightUnits, + }); + + final Freight freight; + final Site senderSite; + final Site recipientSite; + final Site pointOfDepartureSite; + final Site destinationSite; + final List freightUnits; +} diff --git a/lib/models/views/route_tasks_screen.dart b/lib/models/views/route_tasks_screen.dart new file mode 100644 index 0000000..66cbb8d --- /dev/null +++ b/lib/models/views/route_tasks_screen.dart @@ -0,0 +1,11 @@ +import "package:tms_api/tms_api.dart"; + +class RouteTasksScreenData { + const RouteTasksScreenData({ + required this.route, + required this.tasks, + }); + + final Route route; + final List tasks; +} diff --git a/lib/models/views/task_details_screen.dart b/lib/models/views/task_details_screen.dart new file mode 100644 index 0000000..f8db72f --- /dev/null +++ b/lib/models/views/task_details_screen.dart @@ -0,0 +1,28 @@ +import "package:flutter/foundation.dart"; +import "package:tms_api/tms_api.dart"; + +class TaskDetailsScreenData { + const TaskDetailsScreenData({ + required this.tasks, + required this.customerSite, + }); + + final List tasks; + final Site customerSite; +} + +class TaskIdList { + const TaskIdList({required this.list}); + + final List list; + + @override + bool operator ==(final Object other) { + if (identical(this, other)) return true; + + return other is TaskIdList && listEquals(other.list, list); + } + + @override + int get hashCode => list.map((final id) => id.hashCode).join("").hashCode; +} diff --git a/lib/providers/freight_units/freight_units_providers.dart b/lib/providers/freight_units/freight_units_providers.dart new file mode 100644 index 0000000..d107524 --- /dev/null +++ b/lib/providers/freight_units/freight_units_providers.dart @@ -0,0 +1,32 @@ +import "dart:developer"; + +import "package:dio/dio.dart"; +import "package:riverpod_annotation/riverpod_annotation.dart"; +import "package:tms_api/tms_api.dart"; +import "package:vp_kuljetus_driver_app/services/api/api.dart"; +import "package:vp_kuljetus_driver_app/utils/provider_cache.dart"; + +part "freight_units_providers.g.dart"; + +@riverpod +Future> listFreightUnits( + final ListFreightUnitsRef ref, { + required final String freightId, +}) async { + final cancelToken = CancelToken(); + ref.onDispose(cancelToken.cancel); + + try { + final response = await tmsApi.getFreightUnitsApi().listFreightUnits( + cancelToken: cancelToken, + freightId: freightId, + ); + + ref.cacheFor(const Duration(minutes: 5)); + return response.data!.asList(); + } on DioException catch (error) { + log("Failed to list freight units: $error"); + log(error.requestOptions.toString()); + rethrow; + } +} diff --git a/lib/providers/freight_units/freight_units_providers.g.dart b/lib/providers/freight_units/freight_units_providers.g.dart new file mode 100644 index 0000000..4fe1daa --- /dev/null +++ b/lib/providers/freight_units/freight_units_providers.g.dart @@ -0,0 +1,160 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'freight_units_providers.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$listFreightUnitsHash() => r'e4034932fac3b714b8be3a82fa8462688f75badf'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +/// See also [listFreightUnits]. +@ProviderFor(listFreightUnits) +const listFreightUnitsProvider = ListFreightUnitsFamily(); + +/// See also [listFreightUnits]. +class ListFreightUnitsFamily extends Family>> { + /// See also [listFreightUnits]. + const ListFreightUnitsFamily(); + + /// See also [listFreightUnits]. + ListFreightUnitsProvider call({ + required String freightId, + }) { + return ListFreightUnitsProvider( + freightId: freightId, + ); + } + + @override + ListFreightUnitsProvider getProviderOverride( + covariant ListFreightUnitsProvider provider, + ) { + return call( + freightId: provider.freightId, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'listFreightUnitsProvider'; +} + +/// See also [listFreightUnits]. +class ListFreightUnitsProvider + extends AutoDisposeFutureProvider> { + /// See also [listFreightUnits]. + ListFreightUnitsProvider({ + required String freightId, + }) : this._internal( + (ref) => listFreightUnits( + ref as ListFreightUnitsRef, + freightId: freightId, + ), + from: listFreightUnitsProvider, + name: r'listFreightUnitsProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$listFreightUnitsHash, + dependencies: ListFreightUnitsFamily._dependencies, + allTransitiveDependencies: + ListFreightUnitsFamily._allTransitiveDependencies, + freightId: freightId, + ); + + ListFreightUnitsProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.freightId, + }) : super.internal(); + + final String freightId; + + @override + Override overrideWith( + FutureOr> Function(ListFreightUnitsRef provider) create, + ) { + return ProviderOverride( + origin: this, + override: ListFreightUnitsProvider._internal( + (ref) => create(ref as ListFreightUnitsRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + freightId: freightId, + ), + ); + } + + @override + AutoDisposeFutureProviderElement> createElement() { + return _ListFreightUnitsProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is ListFreightUnitsProvider && other.freightId == freightId; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, freightId.hashCode); + + return _SystemHash.finish(hash); + } +} + +mixin ListFreightUnitsRef on AutoDisposeFutureProviderRef> { + /// The parameter `freightId` of this provider. + String get freightId; +} + +class _ListFreightUnitsProviderElement + extends AutoDisposeFutureProviderElement> + with ListFreightUnitsRef { + _ListFreightUnitsProviderElement(super.provider); + + @override + String get freightId => (origin as ListFreightUnitsProvider).freightId; +} +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/providers/freights/freights_providers.dart b/lib/providers/freights/freights_providers.dart new file mode 100644 index 0000000..3964a9b --- /dev/null +++ b/lib/providers/freights/freights_providers.dart @@ -0,0 +1,32 @@ +import "dart:developer"; + +import "package:dio/dio.dart"; +import "package:riverpod_annotation/riverpod_annotation.dart"; +import "package:tms_api/tms_api.dart"; +import "package:vp_kuljetus_driver_app/services/api/api.dart"; +import "package:vp_kuljetus_driver_app/utils/provider_cache.dart"; + +part "freights_providers.g.dart"; + +@riverpod +Future findFreight( + final FindFreightRef ref, { + required final String freightId, +}) async { + final cancelToken = CancelToken(); + ref.onDispose(cancelToken.cancel); + + try { + final response = await tmsApi.getFreightsApi().findFreight( + cancelToken: cancelToken, + freightId: freightId, + ); + + ref.cacheFor(const Duration(minutes: 5)); + return response.data!; + } on DioException catch (error) { + log("Failed to find freight: $error"); + log(error.requestOptions.toString()); + rethrow; + } +} diff --git a/lib/providers/freights/freights_providers.g.dart b/lib/providers/freights/freights_providers.g.dart new file mode 100644 index 0000000..88c2c88 --- /dev/null +++ b/lib/providers/freights/freights_providers.g.dart @@ -0,0 +1,158 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'freights_providers.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$findFreightHash() => r'6d26dafd7ff2d0348ea764e5d09f131c7ecf0bf4'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +/// See also [findFreight]. +@ProviderFor(findFreight) +const findFreightProvider = FindFreightFamily(); + +/// See also [findFreight]. +class FindFreightFamily extends Family> { + /// See also [findFreight]. + const FindFreightFamily(); + + /// See also [findFreight]. + FindFreightProvider call({ + required String freightId, + }) { + return FindFreightProvider( + freightId: freightId, + ); + } + + @override + FindFreightProvider getProviderOverride( + covariant FindFreightProvider provider, + ) { + return call( + freightId: provider.freightId, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'findFreightProvider'; +} + +/// See also [findFreight]. +class FindFreightProvider extends AutoDisposeFutureProvider { + /// See also [findFreight]. + FindFreightProvider({ + required String freightId, + }) : this._internal( + (ref) => findFreight( + ref as FindFreightRef, + freightId: freightId, + ), + from: findFreightProvider, + name: r'findFreightProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$findFreightHash, + dependencies: FindFreightFamily._dependencies, + allTransitiveDependencies: + FindFreightFamily._allTransitiveDependencies, + freightId: freightId, + ); + + FindFreightProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.freightId, + }) : super.internal(); + + final String freightId; + + @override + Override overrideWith( + FutureOr Function(FindFreightRef provider) create, + ) { + return ProviderOverride( + origin: this, + override: FindFreightProvider._internal( + (ref) => create(ref as FindFreightRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + freightId: freightId, + ), + ); + } + + @override + AutoDisposeFutureProviderElement createElement() { + return _FindFreightProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is FindFreightProvider && other.freightId == freightId; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, freightId.hashCode); + + return _SystemHash.finish(hash); + } +} + +mixin FindFreightRef on AutoDisposeFutureProviderRef { + /// The parameter `freightId` of this provider. + String get freightId; +} + +class _FindFreightProviderElement + extends AutoDisposeFutureProviderElement with FindFreightRef { + _FindFreightProviderElement(super.provider); + + @override + String get freightId => (origin as FindFreightProvider).freightId; +} +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/providers/routes/routes_providers.dart b/lib/providers/routes/routes_providers.dart index e10fb19..8a123d1 100644 --- a/lib/providers/routes/routes_providers.dart +++ b/lib/providers/routes/routes_providers.dart @@ -41,7 +41,7 @@ Future> listRoutes( } @riverpod -Future findRoute( +Future findRoute( final FindRouteRef ref, { required final String routeId, }) async { @@ -60,6 +60,6 @@ Future findRoute( } on DioException catch (error) { log("Failed to find route: $error"); log(error.requestOptions.toString()); - return null; + rethrow; } } diff --git a/lib/providers/routes/routes_providers.g.dart b/lib/providers/routes/routes_providers.g.dart index 57ac53f..b1cffc5 100644 --- a/lib/providers/routes/routes_providers.g.dart +++ b/lib/providers/routes/routes_providers.g.dart @@ -237,14 +237,14 @@ class _ListRoutesProviderElement int? get max => (origin as ListRoutesProvider).max; } -String _$findRouteHash() => r'6fda19fe90615cbad3cc27981780c96a3977642b'; +String _$findRouteHash() => r'3a36712b3d24b3951442fc5e48ad5d51f14e65cd'; /// See also [findRoute]. @ProviderFor(findRoute) const findRouteProvider = FindRouteFamily(); /// See also [findRoute]. -class FindRouteFamily extends Family> { +class FindRouteFamily extends Family> { /// See also [findRoute]. const FindRouteFamily(); @@ -282,7 +282,7 @@ class FindRouteFamily extends Family> { } /// See also [findRoute]. -class FindRouteProvider extends AutoDisposeFutureProvider { +class FindRouteProvider extends AutoDisposeFutureProvider { /// See also [findRoute]. FindRouteProvider({ required String routeId, @@ -316,7 +316,7 @@ class FindRouteProvider extends AutoDisposeFutureProvider { @override Override overrideWith( - FutureOr Function(FindRouteRef provider) create, + FutureOr Function(FindRouteRef provider) create, ) { return ProviderOverride( origin: this, @@ -333,7 +333,7 @@ class FindRouteProvider extends AutoDisposeFutureProvider { } @override - AutoDisposeFutureProviderElement createElement() { + AutoDisposeFutureProviderElement createElement() { return _FindRouteProviderElement(this); } @@ -351,12 +351,12 @@ class FindRouteProvider extends AutoDisposeFutureProvider { } } -mixin FindRouteRef on AutoDisposeFutureProviderRef { +mixin FindRouteRef on AutoDisposeFutureProviderRef { /// The parameter `routeId` of this provider. String get routeId; } -class _FindRouteProviderElement extends AutoDisposeFutureProviderElement +class _FindRouteProviderElement extends AutoDisposeFutureProviderElement with FindRouteRef { _FindRouteProviderElement(super.provider); diff --git a/lib/providers/sites/sites_providers.dart b/lib/providers/sites/sites_providers.dart index 839d0e7..e632501 100644 --- a/lib/providers/sites/sites_providers.dart +++ b/lib/providers/sites/sites_providers.dart @@ -9,7 +9,7 @@ import "package:vp_kuljetus_driver_app/utils/provider_cache.dart"; part "sites_providers.g.dart"; @riverpod -Future findSite( +Future findSite( final FindSiteRef ref, { required final String siteId, }) async { @@ -27,6 +27,6 @@ Future findSite( } on DioException catch (error) { log("Failed to find site: $error"); log(error.requestOptions.toString()); - return null; + rethrow; } } diff --git a/lib/providers/sites/sites_providers.g.dart b/lib/providers/sites/sites_providers.g.dart index 34b4524..26ee009 100644 --- a/lib/providers/sites/sites_providers.g.dart +++ b/lib/providers/sites/sites_providers.g.dart @@ -6,7 +6,7 @@ part of 'sites_providers.dart'; // RiverpodGenerator // ************************************************************************** -String _$findSiteHash() => r'054cb38d8d2fee21e76a9b8f5d37c704b729b620'; +String _$findSiteHash() => r'f632822969d7a2794a9b4e4b391044e433c19b43'; /// Copied from Dart SDK class _SystemHash { @@ -34,7 +34,7 @@ class _SystemHash { const findSiteProvider = FindSiteFamily(); /// See also [findSite]. -class FindSiteFamily extends Family> { +class FindSiteFamily extends Family> { /// See also [findSite]. const FindSiteFamily(); @@ -72,7 +72,7 @@ class FindSiteFamily extends Family> { } /// See also [findSite]. -class FindSiteProvider extends AutoDisposeFutureProvider { +class FindSiteProvider extends AutoDisposeFutureProvider { /// See also [findSite]. FindSiteProvider({ required String siteId, @@ -106,7 +106,7 @@ class FindSiteProvider extends AutoDisposeFutureProvider { @override Override overrideWith( - FutureOr Function(FindSiteRef provider) create, + FutureOr Function(FindSiteRef provider) create, ) { return ProviderOverride( origin: this, @@ -123,7 +123,7 @@ class FindSiteProvider extends AutoDisposeFutureProvider { } @override - AutoDisposeFutureProviderElement createElement() { + AutoDisposeFutureProviderElement createElement() { return _FindSiteProviderElement(this); } @@ -141,12 +141,12 @@ class FindSiteProvider extends AutoDisposeFutureProvider { } } -mixin FindSiteRef on AutoDisposeFutureProviderRef { +mixin FindSiteRef on AutoDisposeFutureProviderRef { /// The parameter `siteId` of this provider. String get siteId; } -class _FindSiteProviderElement extends AutoDisposeFutureProviderElement +class _FindSiteProviderElement extends AutoDisposeFutureProviderElement with FindSiteRef { _FindSiteProviderElement(super.provider); diff --git a/lib/providers/tasks/tasks_providers.dart b/lib/providers/tasks/tasks_providers.dart index ba372f3..3e5214c 100644 --- a/lib/providers/tasks/tasks_providers.dart +++ b/lib/providers/tasks/tasks_providers.dart @@ -43,10 +43,10 @@ Future> listTasks( } @riverpod -Future findTask( - final FindTaskRef ref, { - required final String taskId, -}) async { +Future findTask( + final FindTaskRef ref, + final String taskId, +) async { final cancelToken = CancelToken(); ref.onDispose(cancelToken.cancel); @@ -62,17 +62,16 @@ Future findTask( } on DioException catch (error) { log("Failed to find task: $error"); log(error.requestOptions.toString()); - return null; + rethrow; } } @riverpod class UpdateTask extends _$UpdateTask { @override - Future build(final String taskId) async => - ref.watch(FindTaskProvider(taskId: taskId)).value; + build() async => ""; - Future mutate(final Task task) async { + Future mutate(final Task task) async { try { final response = await tmsApi.getTasksApi().updateTask( taskId: task.id!, diff --git a/lib/providers/tasks/tasks_providers.g.dart b/lib/providers/tasks/tasks_providers.g.dart index a19fe7e..b154bea 100644 --- a/lib/providers/tasks/tasks_providers.g.dart +++ b/lib/providers/tasks/tasks_providers.g.dart @@ -251,23 +251,23 @@ class _ListTasksProviderElement int? get max => (origin as ListTasksProvider).max; } -String _$findTaskHash() => r'053569c11cb4eef34ceb12159e04b7a4df56fe0f'; +String _$findTaskHash() => r'2363e0b6ffb4c1ff9f5d1780b50cee9dd03011c7'; /// See also [findTask]. @ProviderFor(findTask) const findTaskProvider = FindTaskFamily(); /// See also [findTask]. -class FindTaskFamily extends Family> { +class FindTaskFamily extends Family> { /// See also [findTask]. const FindTaskFamily(); /// See also [findTask]. - FindTaskProvider call({ - required String taskId, - }) { + FindTaskProvider call( + String taskId, + ) { return FindTaskProvider( - taskId: taskId, + taskId, ); } @@ -276,7 +276,7 @@ class FindTaskFamily extends Family> { covariant FindTaskProvider provider, ) { return call( - taskId: provider.taskId, + provider.taskId, ); } @@ -296,14 +296,14 @@ class FindTaskFamily extends Family> { } /// See also [findTask]. -class FindTaskProvider extends AutoDisposeFutureProvider { +class FindTaskProvider extends AutoDisposeFutureProvider { /// See also [findTask]. - FindTaskProvider({ - required String taskId, - }) : this._internal( + FindTaskProvider( + String taskId, + ) : this._internal( (ref) => findTask( ref as FindTaskRef, - taskId: taskId, + taskId, ), from: findTaskProvider, name: r'findTaskProvider', @@ -330,7 +330,7 @@ class FindTaskProvider extends AutoDisposeFutureProvider { @override Override overrideWith( - FutureOr Function(FindTaskRef provider) create, + FutureOr Function(FindTaskRef provider) create, ) { return ProviderOverride( origin: this, @@ -347,7 +347,7 @@ class FindTaskProvider extends AutoDisposeFutureProvider { } @override - AutoDisposeFutureProviderElement createElement() { + AutoDisposeFutureProviderElement createElement() { return _FindTaskProviderElement(this); } @@ -365,12 +365,12 @@ class FindTaskProvider extends AutoDisposeFutureProvider { } } -mixin FindTaskRef on AutoDisposeFutureProviderRef { +mixin FindTaskRef on AutoDisposeFutureProviderRef { /// The parameter `taskId` of this provider. String get taskId; } -class _FindTaskProviderElement extends AutoDisposeFutureProviderElement +class _FindTaskProviderElement extends AutoDisposeFutureProviderElement with FindTaskRef { _FindTaskProviderElement(super.provider); @@ -378,146 +378,20 @@ class _FindTaskProviderElement extends AutoDisposeFutureProviderElement String get taskId => (origin as FindTaskProvider).taskId; } -String _$updateTaskHash() => r'b88304dc5365881309271928bde285373163f146'; - -abstract class _$UpdateTask extends BuildlessAutoDisposeAsyncNotifier { - late final String taskId; - - FutureOr build( - String taskId, - ); -} +String _$updateTaskHash() => r'224332738aac4d20934f5a886682c36964cc2463'; /// See also [UpdateTask]. @ProviderFor(UpdateTask) -const updateTaskProvider = UpdateTaskFamily(); - -/// See also [UpdateTask]. -class UpdateTaskFamily extends Family> { - /// See also [UpdateTask]. - const UpdateTaskFamily(); - - /// See also [UpdateTask]. - UpdateTaskProvider call( - String taskId, - ) { - return UpdateTaskProvider( - taskId, - ); - } - - @override - UpdateTaskProvider getProviderOverride( - covariant UpdateTaskProvider provider, - ) { - return call( - provider.taskId, - ); - } - - static const Iterable? _dependencies = null; - - @override - Iterable? get dependencies => _dependencies; - - static const Iterable? _allTransitiveDependencies = null; - - @override - Iterable? get allTransitiveDependencies => - _allTransitiveDependencies; - - @override - String? get name => r'updateTaskProvider'; -} - -/// See also [UpdateTask]. -class UpdateTaskProvider - extends AutoDisposeAsyncNotifierProviderImpl { - /// See also [UpdateTask]. - UpdateTaskProvider( - String taskId, - ) : this._internal( - () => UpdateTask()..taskId = taskId, - from: updateTaskProvider, - name: r'updateTaskProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') - ? null - : _$updateTaskHash, - dependencies: UpdateTaskFamily._dependencies, - allTransitiveDependencies: - UpdateTaskFamily._allTransitiveDependencies, - taskId: taskId, - ); - - UpdateTaskProvider._internal( - super._createNotifier, { - required super.name, - required super.dependencies, - required super.allTransitiveDependencies, - required super.debugGetCreateSourceHash, - required super.from, - required this.taskId, - }) : super.internal(); - - final String taskId; - - @override - FutureOr runNotifierBuild( - covariant UpdateTask notifier, - ) { - return notifier.build( - taskId, - ); - } - - @override - Override overrideWith(UpdateTask Function() create) { - return ProviderOverride( - origin: this, - override: UpdateTaskProvider._internal( - () => create()..taskId = taskId, - from: from, - name: null, - dependencies: null, - allTransitiveDependencies: null, - debugGetCreateSourceHash: null, - taskId: taskId, - ), - ); - } - - @override - AutoDisposeAsyncNotifierProviderElement createElement() { - return _UpdateTaskProviderElement(this); - } - - @override - bool operator ==(Object other) { - return other is UpdateTaskProvider && other.taskId == taskId; - } - - @override - int get hashCode { - var hash = _SystemHash.combine(0, runtimeType.hashCode); - hash = _SystemHash.combine(hash, taskId.hashCode); - - return _SystemHash.finish(hash); - } -} - -mixin UpdateTaskRef on AutoDisposeAsyncNotifierProviderRef { - /// The parameter `taskId` of this provider. - String get taskId; -} - -class _UpdateTaskProviderElement - extends AutoDisposeAsyncNotifierProviderElement - with UpdateTaskRef { - _UpdateTaskProviderElement(super.provider); - - @override - String get taskId => (origin as UpdateTaskProvider).taskId; -} +final updateTaskProvider = + AutoDisposeNotifierProvider.internal( + UpdateTask.new, + name: r'updateTaskProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') ? null : _$updateTaskHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$UpdateTask = AutoDisposeNotifier; // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/providers/views/freight_card/freight_card_providers.dart b/lib/providers/views/freight_card/freight_card_providers.dart new file mode 100644 index 0000000..d8ad128 --- /dev/null +++ b/lib/providers/views/freight_card/freight_card_providers.dart @@ -0,0 +1,36 @@ +import "package:riverpod_annotation/riverpod_annotation.dart"; +import "package:tms_api/tms_api.dart"; +import "package:vp_kuljetus_driver_app/models/views/freight_card.dart"; +import "package:vp_kuljetus_driver_app/providers/freight_units/freight_units_providers.dart"; +import "package:vp_kuljetus_driver_app/providers/freights/freights_providers.dart"; +import "package:vp_kuljetus_driver_app/providers/sites/sites_providers.dart"; + +part "freight_card_providers.g.dart"; + +@riverpod +Future fetchFreightCardData( + final FetchFreightCardDataRef ref, + final String freightId, +) async { + final freight = + await ref.watch(findFreightProvider(freightId: freightId).future); + + final sites = await Future.wait([ + ref.watch(findSiteProvider(siteId: freight.senderSiteId).future), + ref.watch(findSiteProvider(siteId: freight.recipientSiteId).future), + ref.watch(findSiteProvider(siteId: freight.pointOfDepartureSiteId).future), + ref.watch(findSiteProvider(siteId: freight.destinationSiteId).future), + ]); + + final freightUnits = + await ref.watch(listFreightUnitsProvider(freightId: freightId).future); + + return FreightCardData( + freight: freight, + senderSite: sites[0], + recipientSite: sites[1], + pointOfDepartureSite: sites[2], + destinationSite: sites[3], + freightUnits: freightUnits, + ); +} diff --git a/lib/providers/views/freight_card/freight_card_providers.g.dart b/lib/providers/views/freight_card/freight_card_providers.g.dart new file mode 100644 index 0000000..6d6dd21 --- /dev/null +++ b/lib/providers/views/freight_card/freight_card_providers.g.dart @@ -0,0 +1,162 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'freight_card_providers.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$fetchFreightCardDataHash() => + r'af3128099d28a07aee1c729e3d9d5a21926b89f5'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +/// See also [fetchFreightCardData]. +@ProviderFor(fetchFreightCardData) +const fetchFreightCardDataProvider = FetchFreightCardDataFamily(); + +/// See also [fetchFreightCardData]. +class FetchFreightCardDataFamily extends Family> { + /// See also [fetchFreightCardData]. + const FetchFreightCardDataFamily(); + + /// See also [fetchFreightCardData]. + FetchFreightCardDataProvider call( + String freightId, + ) { + return FetchFreightCardDataProvider( + freightId, + ); + } + + @override + FetchFreightCardDataProvider getProviderOverride( + covariant FetchFreightCardDataProvider provider, + ) { + return call( + provider.freightId, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'fetchFreightCardDataProvider'; +} + +/// See also [fetchFreightCardData]. +class FetchFreightCardDataProvider + extends AutoDisposeFutureProvider { + /// See also [fetchFreightCardData]. + FetchFreightCardDataProvider( + String freightId, + ) : this._internal( + (ref) => fetchFreightCardData( + ref as FetchFreightCardDataRef, + freightId, + ), + from: fetchFreightCardDataProvider, + name: r'fetchFreightCardDataProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$fetchFreightCardDataHash, + dependencies: FetchFreightCardDataFamily._dependencies, + allTransitiveDependencies: + FetchFreightCardDataFamily._allTransitiveDependencies, + freightId: freightId, + ); + + FetchFreightCardDataProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.freightId, + }) : super.internal(); + + final String freightId; + + @override + Override overrideWith( + FutureOr Function(FetchFreightCardDataRef provider) create, + ) { + return ProviderOverride( + origin: this, + override: FetchFreightCardDataProvider._internal( + (ref) => create(ref as FetchFreightCardDataRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + freightId: freightId, + ), + ); + } + + @override + AutoDisposeFutureProviderElement createElement() { + return _FetchFreightCardDataProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is FetchFreightCardDataProvider && + other.freightId == freightId; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, freightId.hashCode); + + return _SystemHash.finish(hash); + } +} + +mixin FetchFreightCardDataRef on AutoDisposeFutureProviderRef { + /// The parameter `freightId` of this provider. + String get freightId; +} + +class _FetchFreightCardDataProviderElement + extends AutoDisposeFutureProviderElement + with FetchFreightCardDataRef { + _FetchFreightCardDataProviderElement(super.provider); + + @override + String get freightId => (origin as FetchFreightCardDataProvider).freightId; +} +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/providers/views/route_task_screen/route_task_screen_providers.dart b/lib/providers/views/route_task_screen/route_task_screen_providers.dart new file mode 100644 index 0000000..1d8bcd3 --- /dev/null +++ b/lib/providers/views/route_task_screen/route_task_screen_providers.dart @@ -0,0 +1,23 @@ +import "package:riverpod_annotation/riverpod_annotation.dart"; +import "package:tms_api/tms_api.dart"; +import "package:vp_kuljetus_driver_app/models/views/route_tasks_screen.dart"; +import "package:vp_kuljetus_driver_app/providers/routes/routes_providers.dart"; +import "package:vp_kuljetus_driver_app/providers/tasks/tasks_providers.dart"; + +part "route_task_screen_providers.g.dart"; + +@riverpod +Future fetchRouteTaskScreenData( + final FetchRouteTaskScreenDataRef ref, + final String routeId, +) async { + final data = await Future.wait([ + ref.watch(findRouteProvider(routeId: routeId).future), + ref.watch(listTasksProvider(routeId: routeId).future), + ]); + + return RouteTasksScreenData( + route: data[0] as Route, + tasks: data[1] as List, + ); +} diff --git a/lib/providers/views/route_task_screen/route_task_screen_providers.g.dart b/lib/providers/views/route_task_screen/route_task_screen_providers.g.dart new file mode 100644 index 0000000..ad65519 --- /dev/null +++ b/lib/providers/views/route_task_screen/route_task_screen_providers.g.dart @@ -0,0 +1,166 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'route_task_screen_providers.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$fetchRouteTaskScreenDataHash() => + r'64769b91c82917193ee507ef2ebdb2a1e9392edb'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +/// See also [fetchRouteTaskScreenData]. +@ProviderFor(fetchRouteTaskScreenData) +const fetchRouteTaskScreenDataProvider = FetchRouteTaskScreenDataFamily(); + +/// See also [fetchRouteTaskScreenData]. +class FetchRouteTaskScreenDataFamily + extends Family> { + /// See also [fetchRouteTaskScreenData]. + const FetchRouteTaskScreenDataFamily(); + + /// See also [fetchRouteTaskScreenData]. + FetchRouteTaskScreenDataProvider call( + String routeId, + ) { + return FetchRouteTaskScreenDataProvider( + routeId, + ); + } + + @override + FetchRouteTaskScreenDataProvider getProviderOverride( + covariant FetchRouteTaskScreenDataProvider provider, + ) { + return call( + provider.routeId, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'fetchRouteTaskScreenDataProvider'; +} + +/// See also [fetchRouteTaskScreenData]. +class FetchRouteTaskScreenDataProvider + extends AutoDisposeFutureProvider { + /// See also [fetchRouteTaskScreenData]. + FetchRouteTaskScreenDataProvider( + String routeId, + ) : this._internal( + (ref) => fetchRouteTaskScreenData( + ref as FetchRouteTaskScreenDataRef, + routeId, + ), + from: fetchRouteTaskScreenDataProvider, + name: r'fetchRouteTaskScreenDataProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$fetchRouteTaskScreenDataHash, + dependencies: FetchRouteTaskScreenDataFamily._dependencies, + allTransitiveDependencies: + FetchRouteTaskScreenDataFamily._allTransitiveDependencies, + routeId: routeId, + ); + + FetchRouteTaskScreenDataProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.routeId, + }) : super.internal(); + + final String routeId; + + @override + Override overrideWith( + FutureOr Function( + FetchRouteTaskScreenDataRef provider) + create, + ) { + return ProviderOverride( + origin: this, + override: FetchRouteTaskScreenDataProvider._internal( + (ref) => create(ref as FetchRouteTaskScreenDataRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + routeId: routeId, + ), + ); + } + + @override + AutoDisposeFutureProviderElement createElement() { + return _FetchRouteTaskScreenDataProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is FetchRouteTaskScreenDataProvider && + other.routeId == routeId; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, routeId.hashCode); + + return _SystemHash.finish(hash); + } +} + +mixin FetchRouteTaskScreenDataRef + on AutoDisposeFutureProviderRef { + /// The parameter `routeId` of this provider. + String get routeId; +} + +class _FetchRouteTaskScreenDataProviderElement + extends AutoDisposeFutureProviderElement + with FetchRouteTaskScreenDataRef { + _FetchRouteTaskScreenDataProviderElement(super.provider); + + @override + String get routeId => (origin as FetchRouteTaskScreenDataProvider).routeId; +} +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/providers/views/task_details_screen/task_details_screen_providers.dart b/lib/providers/views/task_details_screen/task_details_screen_providers.dart new file mode 100644 index 0000000..810b536 --- /dev/null +++ b/lib/providers/views/task_details_screen/task_details_screen_providers.dart @@ -0,0 +1,24 @@ +import "package:riverpod_annotation/riverpod_annotation.dart"; +import "package:vp_kuljetus_driver_app/models/views/task_details_screen.dart"; +import "package:vp_kuljetus_driver_app/providers/sites/sites_providers.dart"; +import "package:vp_kuljetus_driver_app/providers/tasks/tasks_providers.dart"; + +part "task_details_screen_providers.g.dart"; + +@riverpod +Future fetchTaskDetailsScreenData( + final FetchTaskDetailsScreenDataRef ref, + final TaskIdList taskIdList, +) async { + final tasks = await Future.wait( + taskIdList.list.map( + (final taskId) => ref.watch(findTaskProvider(taskId).future), + ), + ); + + final customerSite = await ref.watch( + findSiteProvider(siteId: tasks.first.customerSiteId).future, + ); + + return TaskDetailsScreenData(tasks: tasks, customerSite: customerSite); +} diff --git a/lib/providers/views/task_details_screen/task_details_screen_providers.g.dart b/lib/providers/views/task_details_screen/task_details_screen_providers.g.dart new file mode 100644 index 0000000..2915f5d --- /dev/null +++ b/lib/providers/views/task_details_screen/task_details_screen_providers.g.dart @@ -0,0 +1,167 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'task_details_screen_providers.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$fetchTaskDetailsScreenDataHash() => + r'69c15fca80b6e21ef546b12a58c47e2feea0320e'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +/// See also [fetchTaskDetailsScreenData]. +@ProviderFor(fetchTaskDetailsScreenData) +const fetchTaskDetailsScreenDataProvider = FetchTaskDetailsScreenDataFamily(); + +/// See also [fetchTaskDetailsScreenData]. +class FetchTaskDetailsScreenDataFamily + extends Family> { + /// See also [fetchTaskDetailsScreenData]. + const FetchTaskDetailsScreenDataFamily(); + + /// See also [fetchTaskDetailsScreenData]. + FetchTaskDetailsScreenDataProvider call( + TaskIdList taskIdList, + ) { + return FetchTaskDetailsScreenDataProvider( + taskIdList, + ); + } + + @override + FetchTaskDetailsScreenDataProvider getProviderOverride( + covariant FetchTaskDetailsScreenDataProvider provider, + ) { + return call( + provider.taskIdList, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'fetchTaskDetailsScreenDataProvider'; +} + +/// See also [fetchTaskDetailsScreenData]. +class FetchTaskDetailsScreenDataProvider + extends AutoDisposeFutureProvider { + /// See also [fetchTaskDetailsScreenData]. + FetchTaskDetailsScreenDataProvider( + TaskIdList taskIdList, + ) : this._internal( + (ref) => fetchTaskDetailsScreenData( + ref as FetchTaskDetailsScreenDataRef, + taskIdList, + ), + from: fetchTaskDetailsScreenDataProvider, + name: r'fetchTaskDetailsScreenDataProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$fetchTaskDetailsScreenDataHash, + dependencies: FetchTaskDetailsScreenDataFamily._dependencies, + allTransitiveDependencies: + FetchTaskDetailsScreenDataFamily._allTransitiveDependencies, + taskIdList: taskIdList, + ); + + FetchTaskDetailsScreenDataProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.taskIdList, + }) : super.internal(); + + final TaskIdList taskIdList; + + @override + Override overrideWith( + FutureOr Function( + FetchTaskDetailsScreenDataRef provider) + create, + ) { + return ProviderOverride( + origin: this, + override: FetchTaskDetailsScreenDataProvider._internal( + (ref) => create(ref as FetchTaskDetailsScreenDataRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + taskIdList: taskIdList, + ), + ); + } + + @override + AutoDisposeFutureProviderElement createElement() { + return _FetchTaskDetailsScreenDataProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is FetchTaskDetailsScreenDataProvider && + other.taskIdList == taskIdList; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, taskIdList.hashCode); + + return _SystemHash.finish(hash); + } +} + +mixin FetchTaskDetailsScreenDataRef + on AutoDisposeFutureProviderRef { + /// The parameter `taskIdList` of this provider. + TaskIdList get taskIdList; +} + +class _FetchTaskDetailsScreenDataProviderElement + extends AutoDisposeFutureProviderElement + with FetchTaskDetailsScreenDataRef { + _FetchTaskDetailsScreenDataProviderElement(super.provider); + + @override + TaskIdList get taskIdList => + (origin as FetchTaskDetailsScreenDataProvider).taskIdList; +} +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/utils/site.dart b/lib/utils/site.dart new file mode 100644 index 0000000..9440a6a --- /dev/null +++ b/lib/utils/site.dart @@ -0,0 +1,19 @@ +import "package:tms_api/tms_api.dart"; +import "package:url_launcher/url_launcher.dart"; + +getSiteAddressText(final Site site) => + "${site.address}, ${site.postalCode} ${site.locality}"; + +Future openMapToSiteAddress(final Site site) async { + final mapUrl = Uri( + scheme: "https", + host: "www.google.com", + path: "/maps/search/", + queryParameters: { + "api": "1", + "query": getSiteAddressText(site), + }, + ); + + if (await canLaunchUrl(mapUrl)) await launchUrl(mapUrl); +} diff --git a/lib/utils/task.dart b/lib/utils/task.dart index a548a65..7b94f2f 100644 --- a/lib/utils/task.dart +++ b/lib/utils/task.dart @@ -7,3 +7,9 @@ String getTaskGroupKey(final Task task) => final parts = taskGroupKey.split(":"); return (parts[0], parts[1], TaskType.valueOf(parts[2]), int.parse(parts[3])); } + +getTaskTypeLocaleKey(final TaskType taskType) => switch (taskType) { + TaskType.LOAD => "load", + TaskType.UNLOAD => "unload", + _ => throw Exception("Unknown task type: $taskType") + }; diff --git a/lib/views/route_tasks/route_tasks_screen.dart b/lib/views/route_tasks/route_tasks_screen.dart index b20d436..26be4e3 100644 --- a/lib/views/route_tasks/route_tasks_screen.dart +++ b/lib/views/route_tasks/route_tasks_screen.dart @@ -4,8 +4,7 @@ import "package:go_router/go_router.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:skeletonizer/skeletonizer.dart"; import "package:tms_api/tms_api.dart"; -import "package:vp_kuljetus_driver_app/providers/routes/routes_providers.dart"; -import "package:vp_kuljetus_driver_app/providers/tasks/tasks_providers.dart"; +import "package:vp_kuljetus_driver_app/providers/views/route_task_screen/route_task_screen_providers.dart"; import "package:vp_kuljetus_driver_app/services/localization/l10n.dart"; import "package:vp_kuljetus_driver_app/utils/task.dart"; import "package:vp_kuljetus_driver_app/views/route_tasks/task_card.dart"; @@ -19,16 +18,10 @@ class RouteTasksScreen extends ConsumerWidget { final l10n = L10n.of(context); final theme = Theme.of(context); final routerState = GoRouterState.of(context); + final routeId = routerState.pathParameters["routeId"]; + if (routeId == null) throw ArgumentError("routeId is required"); - final route = ref.watch( - FindRouteProvider( - routeId: routerState.pathParameters["routeId"]!, - ), - ); - - final AsyncValue> routeTasks = route.hasValue - ? ref.watch(ListTasksProvider(routeId: route.value!.id!)) - : const AsyncLoading>(); + final data = ref.watch(fetchRouteTaskScreenDataProvider(routeId)); Widget renderTasks(final List tasks) { if (tasks.isEmpty) { @@ -68,9 +61,9 @@ class RouteTasksScreen extends ConsumerWidget { ?.copyWith(fontWeight: FontWeight.bold), ), Skeletonizer( - enabled: route.isLoading || route.isRefreshing, + enabled: data.isLoading || data.isRefreshing, child: Text( - route.value?.name ?? "", + data.value?.route.name ?? "", style: theme.textTheme.titleSmall ?.copyWith(fontWeight: FontWeight.bold), ), @@ -82,8 +75,8 @@ class RouteTasksScreen extends ConsumerWidget { Expanded( child: Padding( padding: const EdgeInsets.only(top: 16), - child: routeTasks.when( - data: renderTasks, + child: data.when( + data: (final data) => renderTasks(data.tasks), loading: () => Skeletonizer( child: ListView.separated( padding: const EdgeInsets.all(8), diff --git a/lib/views/route_tasks/task_card.dart b/lib/views/route_tasks/task_card.dart index bcbcfdd..ad6e3cc 100644 --- a/lib/views/route_tasks/task_card.dart +++ b/lib/views/route_tasks/task_card.dart @@ -1,10 +1,11 @@ import "package:flutter/material.dart" hide Route; +import "package:go_router/go_router.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:skeletonizer/skeletonizer.dart"; import "package:tms_api/tms_api.dart" hide Error; -import "package:url_launcher/url_launcher.dart"; import "package:vp_kuljetus_driver_app/providers/sites/sites_providers.dart"; import "package:vp_kuljetus_driver_app/services/localization/l10n.dart"; +import "package:vp_kuljetus_driver_app/utils/site.dart"; class TaskCard extends ConsumerWidget { const TaskCard({super.key, required this.tasks}); @@ -15,30 +16,14 @@ class TaskCard extends ConsumerWidget { Widget build(final context, final ref) { final theme = Theme.of(context); final l10n = L10n.of(context); + final currentPath = GoRouterState.of(context).matchedLocation; if (tasks.isEmpty) throw Exception("No tasks provided for TaskCard"); final task = tasks.first; final customerSite = - ref.watch(FindSiteProvider(siteId: task.customerSiteId)); - - getSiteAddressText(final Site site) => - "${site.address}, ${site.postalCode} ${site.locality}"; - - Future openMapToSiteAddress(final Site site) async { - final mapUrl = Uri( - scheme: "https", - host: "www.google.com", - path: "/maps/search/", - queryParameters: { - "api": "1", - "query": getSiteAddressText(site), - }, - ); - - if (await canLaunchUrl(mapUrl)) await launchUrl(mapUrl); - } + ref.watch(findSiteProvider(siteId: task.customerSiteId)); return Card( elevation: 2, @@ -65,7 +50,7 @@ class TaskCard extends ConsumerWidget { enabled: customerSite.isLoading || customerSite.isRefreshing, child: Text( customerSite.maybeWhen( - data: (final value) => value != null ? value.name : "", + data: (final value) => value.name, orElse: () => "", ), style: theme.textTheme.bodyMedium?.copyWith( @@ -77,45 +62,53 @@ class TaskCard extends ConsumerWidget { Icons.chevron_right, size: 32, ), + onTap: () { + final taskIds = tasks.map((final task) => task.id!); + + final uri = Uri( + path: "$currentPath/task-details", + queryParameters: {"taskIds": taskIds}, + ); + + context.go(uri.toString()); + }, ), const Divider(indent: 16, endIndent: 16), Skeletonizer( enabled: customerSite.isLoading || customerSite.isRefreshing, child: customerSite.maybeWhen( orElse: () => const SizedBox(height: 48), - data: (final data) => data != null - ? Padding( - padding: const EdgeInsets.all(16), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + data: (final data) => Padding( + padding: const EdgeInsets.all(16), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (data.additionalInfo != null) ...[ + Text(data.additionalInfo!), + const SizedBox(height: 8), + ], + GestureDetector( + onTap: () => openMapToSiteAddress(data), + child: Row( children: [ - if (data.additionalInfo != null) ...[ - Text(data.additionalInfo!), - const SizedBox(height: 8), - ], - GestureDetector( - onTap: () => openMapToSiteAddress(data), - child: Row( - children: [ - Icon( - Icons.location_pin, - color: theme.colorScheme.primary, - ), - const SizedBox(width: 8), - Text( - getSiteAddressText(data), - style: theme.textTheme.bodySmall?.copyWith( - color: theme.colorScheme.primary, - ), - ), - ], + Icon( + Icons.location_pin, + color: theme.colorScheme.primary, + ), + const SizedBox(width: 8), + Text( + getSiteAddressText(data), + style: theme.textTheme.bodySmall?.copyWith( + color: theme.colorScheme.primary, ), ), ], ), - ) - : const SizedBox(), + ), + ], + ), + ), ), ), ], diff --git a/lib/views/routes/route_card.dart b/lib/views/routes/route_card.dart index 0f5fe83..1b808cc 100644 --- a/lib/views/routes/route_card.dart +++ b/lib/views/routes/route_card.dart @@ -17,7 +17,7 @@ class RouteCard extends ConsumerWidget { final l10n = L10n.of(context); final driver = route.driverId != null - ? ref.watch(FindDriverProvider(driverId: route.driverId!)) + ? ref.watch(findDriverProvider(driverId: route.driverId!)) : null; return InkWell( diff --git a/lib/views/routes/routes_screen.dart b/lib/views/routes/routes_screen.dart index 6b9566e..acd027d 100644 --- a/lib/views/routes/routes_screen.dart +++ b/lib/views/routes/routes_screen.dart @@ -18,7 +18,7 @@ class RoutesScreen extends HookConsumerWidget { if (truckId == null) throw Exception("No truck selected"); final routes = ref.watch( - ListRoutesProvider( + listRoutesProvider( truckId: truckId, departureAfter: startOfToday(), departureBefore: endOfToday(), diff --git a/lib/views/task_details/action_button.dart b/lib/views/task_details/action_button.dart new file mode 100644 index 0000000..2e0c319 --- /dev/null +++ b/lib/views/task_details/action_button.dart @@ -0,0 +1,35 @@ +import "package:flutter/material.dart"; + +class ActionButton extends StatelessWidget { + const ActionButton({ + super.key, + required this.label, + required this.icon, + this.backgroundColor, + this.onPressed, + }); + + final String label; + final Icon icon; + final Color? backgroundColor; + final void Function()? onPressed; + + @override + Widget build(final context) => Directionality( + textDirection: TextDirection.rtl, + child: FilledButton.icon( + style: ButtonStyle( + visualDensity: VisualDensity.compact, + backgroundColor: backgroundColor != null + ? MaterialStateProperty.all(Colors.white) + : null, + ), + onPressed: onPressed, + label: Text( + label, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + icon: icon, + ), + ); +} diff --git a/lib/views/task_details/freight_card.dart b/lib/views/task_details/freight_card.dart new file mode 100644 index 0000000..c938917 --- /dev/null +++ b/lib/views/task_details/freight_card.dart @@ -0,0 +1,89 @@ +import "package:flutter/material.dart"; +import "package:hooks_riverpod/hooks_riverpod.dart"; +import "package:skeletonizer/skeletonizer.dart"; +import "package:vp_kuljetus_driver_app/providers/views/freight_card/freight_card_providers.dart"; +import "package:vp_kuljetus_driver_app/services/localization/l10n.dart"; +import "package:vp_kuljetus_driver_app/views/task_details/freight_card_site.dart"; +import "package:vp_kuljetus_driver_app/views/task_details/freight_units_table.dart"; + +class FreightCard extends ConsumerWidget { + const FreightCard({super.key, required this.freightId}); + + final String freightId; + + @override + Widget build(final BuildContext context, final ref) { + final theme = Theme.of(context); + final l10n = L10n.of(context); + + final freightCardData = ref.watch(fetchFreightCardDataProvider(freightId)); + final data = freightCardData.valueOrNull; + + return Card( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(3)), + elevation: 6, + shadowColor: Colors.black38, + color: Colors.white, + surfaceTintColor: Colors.transparent, + child: Skeletonizer( + enabled: freightCardData.isLoading || freightCardData.isRefreshing, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + l10n.t("waybill"), + style: theme.textTheme.titleMedium?.copyWith( + color: Colors.black45, + ), + ), + Text( + "${freightCardData.value?.freight.freightNumber}", + style: theme.textTheme.titleMedium?.copyWith( + color: Colors.black45, + ), + ), + ], + ), + ), + FreightUnitsTable(freightUnits: data?.freightUnits ?? []), + Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + FreightCardSite( + title: l10n.t("sender").toUpperCase(), + site: data?.senderSite, + ), + const Divider(), + FreightCardSite( + title: l10n.t("pointOfDeparture").toUpperCase(), + site: data?.pointOfDepartureSite, + ), + const Divider(), + FreightCardSite( + title: l10n.t("recipient").toUpperCase(), + site: data?.recipientSite, + ), + const Divider(), + FreightCardSite( + title: l10n.t("destination").toUpperCase(), + site: data?.destinationSite, + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/views/task_details/freight_card_carousel.dart b/lib/views/task_details/freight_card_carousel.dart new file mode 100644 index 0000000..ca173d3 --- /dev/null +++ b/lib/views/task_details/freight_card_carousel.dart @@ -0,0 +1,104 @@ +import "package:carousel_slider/carousel_slider.dart"; +import "package:flutter/material.dart" hide BoxDecoration, BoxShadow; +import "package:flutter_hooks/flutter_hooks.dart"; +import "package:flutter_inset_box_shadow/flutter_inset_box_shadow.dart"; +import "package:vp_kuljetus_driver_app/views/task_details/freight_card.dart"; + +class FreightCardCarousel extends HookWidget { + const FreightCardCarousel({super.key, required this.freightIds}); + + final List freightIds; + + @override + Widget build(final context) { + final carouselController = useState(CarouselController()); + final currentPage = useState(0); + + final onFirstPage = currentPage.value == 0; + final onLastPage = currentPage.value == freightIds.length - 1; + + previousPage() => carouselController.value.previousPage( + duration: const Duration(milliseconds: 300), + curve: Curves.fastOutSlowIn, + ); + + nextPage() => carouselController.value.nextPage( + duration: const Duration(milliseconds: 300), + curve: Curves.fastOutSlowIn, + ); + + return Column( + children: [ + Expanded( + child: CarouselSlider( + disableGesture: true, + items: freightIds + .map( + (final freightId) => DecoratedBox( + position: DecorationPosition.foreground, + decoration: const BoxDecoration( + boxShadow: [ + BoxShadow( + offset: Offset(0, -4), + blurRadius: 4, + spreadRadius: -4, + color: Colors.black54, + inset: true, + ), + BoxShadow( + offset: Offset(0, 4), + blurRadius: 4, + spreadRadius: -4, + color: Colors.black54, + inset: true, + ), + ], + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(8), + child: FreightCard(freightId: freightId), + ), + ), + ), + ) + .toList(), + carouselController: carouselController.value, + options: CarouselOptions( + autoPlay: false, + enableInfiniteScroll: false, + disableCenter: true, + viewportFraction: 1, + scrollPhysics: const NeverScrollableScrollPhysics(), + onPageChanged: (final index, final reason) => + currentPage.value = index, + ), + ), + ), + if (freightIds.length > 1) + Material( + elevation: 20, + color: Colors.white, + surfaceTintColor: Colors.white, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton( + icon: const Icon(Icons.arrow_back), + onPressed: !onFirstPage ? previousPage : null, + ), + Text("${currentPage.value + 1} / ${freightIds.length}"), + IconButton( + icon: const Icon(Icons.arrow_forward), + onPressed: !onLastPage ? nextPage : null, + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/views/task_details/freight_card_site.dart b/lib/views/task_details/freight_card_site.dart new file mode 100644 index 0000000..e37deef --- /dev/null +++ b/lib/views/task_details/freight_card_site.dart @@ -0,0 +1,25 @@ +import "package:flutter/material.dart"; +import "package:tms_api/tms_api.dart"; +import "package:vp_kuljetus_driver_app/utils/site.dart"; + +class FreightCardSite extends StatelessWidget { + const FreightCardSite({ + super.key, + required this.title, + this.site, + }); + + final String title; + final Site? site; + + @override + Widget build(final context) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text(title, style: Theme.of(context).textTheme.titleMedium), + Text("${site?.name}"), + Text(site != null ? getSiteAddressText(site!) : "Address"), + ], + ); +} diff --git a/lib/views/task_details/freight_units_table.dart b/lib/views/task_details/freight_units_table.dart new file mode 100644 index 0000000..82bae8b --- /dev/null +++ b/lib/views/task_details/freight_units_table.dart @@ -0,0 +1,100 @@ +import "package:flutter/material.dart"; +import "package:hooks_riverpod/hooks_riverpod.dart"; +import "package:tms_api/tms_api.dart"; + +class FreightUnitsTable extends ConsumerWidget { + const FreightUnitsTable({ + super.key, + required this.freightUnits, + }); + + final List freightUnits; + + DataCell renderDataCell( + final String text, { + final bool showEditIcon = false, + }) => + DataCell( + SizedBox.expand( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 8), + alignment: Alignment.centerLeft, + child: Text(text), + ), + ), + showEditIcon: showEditIcon, + ); + + DataRow freightUnitToDataRow(final FreightUnit freightUnit) => DataRow( + cells: [ + DataCell( + Container( + alignment: Alignment.centerLeft, + child: Text(freightUnit.contents ?? "-"), + ), + ), + DataCell( + Container( + constraints: const BoxConstraints.expand(), + color: Colors.white, + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(freightUnit.quantity.toString()), + const Icon(Icons.edit, size: 20, color: Colors.black54), + ], + ), + ), + onTap: () {}, + ), + DataCell( + Container( + padding: const EdgeInsets.only(left: 8), + alignment: Alignment.centerLeft, + child: Text(freightUnit.type), + ), + ), + ], + ); + + @override + Widget build(final context, final ref) => DataTable( + border: TableBorder.symmetric( + outside: const BorderSide(width: 0.75, color: Color(0xFFEAEAEA)), + inside: const BorderSide(width: 1, color: Color(0xFFEAEAEA)), + ), + dividerThickness: 0.01, + headingRowHeight: 32, + dataRowMinHeight: 40, + dataRowMaxHeight: 40, + headingRowColor: MaterialStateProperty.all(const Color(0xFFF2F8FA)), + dataRowColor: MaterialStateProperty.all(const Color(0xFFFAFAFA)), + dataTextStyle: const TextStyle(color: Colors.black45), + columnSpacing: 0, + columns: [ + DataColumn( + label: Container( + alignment: Alignment.centerLeft, + child: const Text("Sisältö"), + ), + ), + DataColumn( + label: Container( + padding: const EdgeInsets.only(left: 8), + alignment: Alignment.centerLeft, + child: const Text("Määrä"), + ), + ), + DataColumn( + label: Container( + padding: const EdgeInsets.only(left: 8), + alignment: Alignment.centerLeft, + child: const Text("Tyyppi"), + ), + ), + ], + rows: freightUnits.map(freightUnitToDataRow).toList(), + ); +} diff --git a/lib/views/task_details/site_details.dart b/lib/views/task_details/site_details.dart new file mode 100644 index 0000000..64c9275 --- /dev/null +++ b/lib/views/task_details/site_details.dart @@ -0,0 +1,54 @@ +import "package:flutter/material.dart"; +import "package:hooks_riverpod/hooks_riverpod.dart"; +import "package:tms_api/tms_api.dart"; +import "package:vp_kuljetus_driver_app/utils/site.dart"; + +class SiteDetails extends ConsumerWidget { + const SiteDetails({super.key, required this.customerSite}); + + final Site customerSite; + + @override + Widget build(final context, final ref) { + final theme = Theme.of(context); + + return Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + customerSite.name, + style: theme.textTheme.titleMedium?.copyWith( + color: Colors.black54, + ), + ), + const SizedBox(height: 8), + if (customerSite.additionalInfo?.isNotEmpty ?? false) + Text(customerSite.additionalInfo!), + if (customerSite.additionalInfo?.isNotEmpty ?? false) + const SizedBox(height: 8), + GestureDetector( + onTap: () => openMapToSiteAddress(customerSite), + child: Row( + children: [ + Icon( + Icons.location_pin, + color: theme.colorScheme.primary, + ), + const SizedBox(width: 8), + Text( + getSiteAddressText(customerSite), + style: theme.textTheme.bodySmall?.copyWith( + color: theme.colorScheme.primary, + ), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/views/task_details/task_details_screen.dart b/lib/views/task_details/task_details_screen.dart index 24a2737..0236109 100644 --- a/lib/views/task_details/task_details_screen.dart +++ b/lib/views/task_details/task_details_screen.dart @@ -1,9 +1,72 @@ import "package:flutter/material.dart"; +import "package:go_router/go_router.dart"; +import "package:hooks_riverpod/hooks_riverpod.dart"; +import "package:skeletonizer/skeletonizer.dart"; +import "package:vp_kuljetus_driver_app/models/views/task_details_screen.dart"; +import "package:vp_kuljetus_driver_app/providers/views/task_details_screen/task_details_screen_providers.dart"; +import "package:vp_kuljetus_driver_app/services/localization/l10n.dart"; +import "package:vp_kuljetus_driver_app/views/task_details/freight_card_carousel.dart"; +import "package:vp_kuljetus_driver_app/views/task_details/site_details.dart"; +import "package:vp_kuljetus_driver_app/views/task_details/task_title_area.dart"; +import "package:vp_kuljetus_driver_app/widgets/block_back_button.dart"; -class TaskDetailsScreen extends StatelessWidget { +class TaskDetailsScreen extends HookConsumerWidget { const TaskDetailsScreen({super.key}); @override - Widget build(final BuildContext context) => - const Center(child: Text("task details")); + Widget build(final context, final ref) { + final l10n = L10n.of(context); + final location = GoRouterState.of(context).matchedLocation; + final previousRoute = location.substring(0, location.lastIndexOf("/")); + + final taskIds = GoRouterState.of(context).uri.queryParametersAll["taskIds"]; + if (taskIds == null) throw Exception("No taskIds provided"); + + final taskDetailsScreenData = ref + .watch(fetchTaskDetailsScreenDataProvider(TaskIdList(list: taskIds))); + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + BlockBackButton( + onPressed: () => context.go(previousRoute), + label: l10n.t("backToTaskList"), + ), + Material( + child: ColoredBox( + color: Colors.white, + child: taskDetailsScreenData.when( + data: (final data) => Column( + children: [ + TaskTitleArea(task: data.tasks.first), + const Divider( + height: 8, + thickness: 0.5, + color: Colors.black12, + ), + SiteDetails(customerSite: data.customerSite), + ], + ), + loading: () => const Skeletonizer( + child: SizedBox( + height: 100, + width: double.infinity, + ), + ), + error: (final error, final stackTrace) => const SizedBox(), + ), + ), + ), + Expanded( + child: taskDetailsScreenData.maybeWhen( + data: (final data) => FreightCardCarousel( + freightIds: + data.tasks.map((final task) => task.freightId).toList(), + ), + orElse: () => const Center(child: CircularProgressIndicator()), + ), + ), + ], + ); + } } diff --git a/lib/views/task_details/task_title_area.dart b/lib/views/task_details/task_title_area.dart new file mode 100644 index 0000000..eed6531 --- /dev/null +++ b/lib/views/task_details/task_title_area.dart @@ -0,0 +1,47 @@ +import "package:flutter/material.dart"; +import "package:tms_api/tms_api.dart"; +import "package:vp_kuljetus_driver_app/services/localization/l10n.dart"; +import "package:vp_kuljetus_driver_app/utils/task.dart"; +import "package:vp_kuljetus_driver_app/views/task_details/action_button.dart"; + +class TaskTitleArea extends StatelessWidget { + const TaskTitleArea({super.key, required this.task}); + + final Task task; + + @override + Widget build(final context) { + final theme = Theme.of(context); + final l10n = L10n.of(context); + + final localizedTaskType = l10n.t(getTaskTypeLocaleKey(task.type)); + + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + l10n.t(getTaskTypeLocaleKey(task.type)), + style: theme.textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + if (task.status == TaskStatus.TODO) + ActionButton( + label: "${l10n.t("start")} ${localizedTaskType.toLowerCase()}", + icon: const Icon(Icons.play_arrow), + onPressed: () {}, + ), + if (task.status == TaskStatus.IN_PROGRESS) + ActionButton( + label: "${l10n.t("end")} ${localizedTaskType.toLowerCase()}", + icon: const Icon(Icons.stop), + backgroundColor: Theme.of(context).colorScheme.error, + onPressed: () {}, + ), + ], + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index ac2679f..f6d984b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -129,6 +129,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.9.2" + carousel_slider: + dependency: "direct main" + description: + name: carousel_slider + sha256: "9c695cc963bf1d04a47bd6021f68befce8970bcd61d24938e1fb0918cf5d9c42" + url: "https://pub.dev" + source: hosted + version: "4.2.1" characters: dependency: transitive description: @@ -382,6 +390,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.20.5" + flutter_inset_box_shadow: + dependency: "direct main" + description: + name: flutter_inset_box_shadow + sha256: "0b1930ed5f4ad84b11b41dda907fbc5d4c12929a4c51455c626e5937b47ffb93" + url: "https://pub.dev" + source: hosted + version: "1.0.8" flutter_launcher_icons: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 287becd..1c024eb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,12 +28,14 @@ environment: # the latest version available on pub.dev. To see which dependencies have newer # versions available, run `flutter pub outdated`. dependencies: + carousel_slider: ^4.2.1 collection: ^1.18.0 cupertino_icons: ^1.0.2 dio: ^5.4.2 flutter: sdk: flutter flutter_hooks: ^0.20.5 + flutter_inset_box_shadow: ^1.0.8 flutter_launcher_icons: ^0.13.1 flutter_localizations: sdk: flutter @@ -59,16 +61,16 @@ dev_dependencies: build_runner: ^2.4.8 custom_lint: ^0.6.2 dart_define: ^2.1.1 + flutter_app_installer: ^1.0.0 flutter_lints: ^3.0.2 flutter_test: sdk: flutter freezed: ^2.4.7 json_serializable: ^6.7.1 openapi_generator: ^5.0.0 + package_info_plus: ^8.0.0 riverpod_generator: ^2.3.11 riverpod_lint: ^2.3.9 - flutter_app_installer: ^1.0.0 - package_info_plus: ^8.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec