diff --git a/trackingservice/sample-env.txt b/trackingservice/sample-env.txt index d4a61d34..04fe617d 100644 --- a/trackingservice/sample-env.txt +++ b/trackingservice/sample-env.txt @@ -1,5 +1,5 @@ DB_JDBC_URL=jdbc:postgresql://db-postgresql.com:25060/defaultdb DB_USER=doadmin DB_PASSWORD=AVNS_VOzqloso05 -DIGIT_FSM_URL=https://unified-dev.digit.org/fsm/v1/ -DIGIT_VEHICLE_TRIP_URL=https://unified-dev.digit.org/vehicle/trip/v1/ \ No newline at end of file +DIGIT_FSM_URL=https://fsm-demo.digit.org/fsm/v1 +DIGIT_VEHICLE_TRIP_URL=https://fsm-demo.digit.org/vehicle/trip/v1/ diff --git a/trackingservice/src/main/java/org/digit/tracking/util/Constants.java b/trackingservice/src/main/java/org/digit/tracking/util/Constants.java index 36dc22f1..a9e08d6a 100644 --- a/trackingservice/src/main/java/org/digit/tracking/util/Constants.java +++ b/trackingservice/src/main/java/org/digit/tracking/util/Constants.java @@ -14,9 +14,9 @@ public class Constants { final public static int POI_MATCH_THRESHOLD_METERS = 100; final public static String MONITORING_USER_ID = "MonitoringService"; @Value("${DIGIT_FSM_URL}") - final public static String DIGIT_FSM_URL = "https://unified-dev.digit.org/fsm/v1/"; + final public static String DIGIT_FSM_URL = "https://fsm-demo.digit.org/fsm/v1"; @Value("${DIGIT_VEHICLE_TRIP_URL}") - final public static String DIGIT_VEHICLE_TRIP_URL = "https://unified-dev.digit.org/vehicle/trip/v1/"; + final public static String DIGIT_VEHICLE_TRIP_URL = "https://fsm-demo.digit.org/vehicle/trip/v1"; final public static String ILLEGAL_DUMP_YARD_STOPPAGE_CODE = "Stoppage"; final public static int ILLEGAL_DUMP_YARD_STOPPAGE_THRESHOLD = 5; final public static int TRIP_PROGRESS_FETCH_LIMIT = 1000; diff --git a/vehicle-tracker/map_web_app/pubspec.lock b/vehicle-tracker/map_web_app/pubspec.lock index bfb960e7..bbe90d0f 100644 --- a/vehicle-tracker/map_web_app/pubspec.lock +++ b/vehicle-tracker/map_web_app/pubspec.lock @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.17.1" convert: dependency: transitive description: @@ -188,10 +188,9 @@ packages: digit_components: dependency: "direct main" description: - name: digit_components - sha256: "261f4407e5fe2ab3be3800dfbdc69112b632baa90f87c0e66b5c93f12e10df39" - url: "https://pub.dev" - source: hosted + path: "../packages/digit_components" + relative: true + source: path version: "0.0.1+8" fake_async: dependency: transitive @@ -417,10 +416,10 @@ packages: dependency: transitive description: name: intl - sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 url: "https://pub.dev" source: hosted - version: "0.18.1" + version: "0.18.0" io: dependency: transitive description: @@ -513,26 +512,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.2.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" mgrs_dart: dependency: transitive description: @@ -702,26 +701,26 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.1" stream_transform: dependency: transitive description: @@ -750,10 +749,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.5.1" timing: dependency: transitive description: @@ -794,14 +793,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" - web: - dependency: transitive - description: - name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 - url: "https://pub.dev" - source: hosted - version: "0.3.0" web_socket_channel: dependency: transitive description: @@ -827,5 +818,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.10.0" diff --git a/vehicle-tracker/map_web_app/pubspec.yaml b/vehicle-tracker/map_web_app/pubspec.yaml index a6616802..f0df14fa 100644 --- a/vehicle-tracker/map_web_app/pubspec.yaml +++ b/vehicle-tracker/map_web_app/pubspec.yaml @@ -19,7 +19,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: '>=3.0.2 <4.0.0' + sdk: '>=3.0.0 <4.0.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions diff --git a/vehicle-tracker/map_web_app/pubspec_overrides.yaml b/vehicle-tracker/map_web_app/pubspec_overrides.yaml new file mode 100644 index 00000000..a4ed6c5f --- /dev/null +++ b/vehicle-tracker/map_web_app/pubspec_overrides.yaml @@ -0,0 +1,3 @@ +dependency_overrides: + digit_components: + path: ../packages/digit_components \ No newline at end of file diff --git a/vehicle-tracker/map_web_app/route_map/lib/blocs/polygon_map/controllers/map_controllers.dart b/vehicle-tracker/map_web_app/route_map/lib/blocs/polygon_map/controllers/map_controllers.dart index 16157d85..a7951f04 100644 --- a/vehicle-tracker/map_web_app/route_map/lib/blocs/polygon_map/controllers/map_controllers.dart +++ b/vehicle-tracker/map_web_app/route_map/lib/blocs/polygon_map/controllers/map_controllers.dart @@ -45,6 +45,9 @@ class MapControllers extends GetxController { final alertPolygons = await Map2HttpRepository.getAllPolygonsWithAlerts(tenantId); + if(alertMarkers.isNotEmpty) alertMarkers.clear(); + if(this.alertPolygons.isNotEmpty) this.alertPolygons.clear(); + for (var alartPolygon in alertPolygons) { if (alartPolygon.type == "point") { alertMarkers.add(alartPolygon); diff --git a/vehicle-tracker/map_web_app/route_map/pubspec.lock b/vehicle-tracker/map_web_app/route_map/pubspec.lock index ed658da9..83257bc7 100644 --- a/vehicle-tracker/map_web_app/route_map/pubspec.lock +++ b/vehicle-tracker/map_web_app/route_map/pubspec.lock @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.17.1" convert: dependency: transitive description: @@ -377,10 +377,10 @@ packages: dependency: transitive description: name: geolocator_android - sha256: "136f1c97e1903366393bda514c5d9e98843418baea52899aa45edae9af8a5cd6" + sha256: "06e37fa32392f69f133e166ef6b358a8b6afddbf4c418fc236988184cc115a49" url: "https://pub.dev" source: hosted - version: "4.5.2" + version: "4.4.1" geolocator_apple: dependency: transitive description: @@ -473,10 +473,10 @@ packages: dependency: transitive description: name: intl - sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 url: "https://pub.dev" source: hosted - version: "0.18.1" + version: "0.18.0" io: dependency: transitive description: @@ -517,30 +517,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" - url: "https://pub.dev" - source: hosted - version: "10.0.0" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 - url: "https://pub.dev" - source: hosted - version: "2.0.1" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 - url: "https://pub.dev" - source: hosted - version: "2.0.1" lints: dependency: transitive description: @@ -593,26 +569,26 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.2.0" meta: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.9.1" mgrs_dart: dependency: transitive description: @@ -657,10 +633,10 @@ packages: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.8.3" plugin_platform_interface: dependency: transitive description: @@ -782,10 +758,10 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" sprintf: dependency: transitive description: @@ -798,18 +774,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.1" stream_transform: dependency: transitive description: @@ -838,10 +814,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.5.1" timing: dependency: transitive description: @@ -878,10 +854,10 @@ packages: dependency: transitive description: name: uuid - sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 + sha256: "22c94e5ad1e75f9934b766b53c742572ee2677c56bc871d850a57dad0f82127f" url: "https://pub.dev" source: hosted - version: "4.3.3" + version: "4.2.2" vector_math: dependency: transitive description: @@ -890,14 +866,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 - url: "https://pub.dev" - source: hosted - version: "13.0.0" watcher: dependency: transitive description: @@ -931,5 +899,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0-0 <4.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.10.0" diff --git a/vehicle-tracker/packages/digit_components/.dart_tool/package_config.json b/vehicle-tracker/packages/digit_components/.dart_tool/package_config.json new file mode 100644 index 00000000..5a969ec4 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/.dart_tool/package_config.json @@ -0,0 +1,644 @@ +{ + "configVersion": 2, + "packages": [ + { + "name": "_fe_analyzer_shared", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-61.0.0", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "analyzer", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/analyzer-5.13.0", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "args", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/args-2.4.2", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "async", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/async-2.11.0", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "bloc", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/bloc-8.1.3", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "bloc_test", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/bloc_test-9.1.6", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "boolean_selector", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "build", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build-2.4.1", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "build_config", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_config-1.1.1", + "packageUri": "lib/", + "languageVersion": "2.14" + }, + { + "name": "build_daemon", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_daemon-4.0.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "build_resolvers", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_resolvers-2.4.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "build_runner", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_runner-2.4.8", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "build_runner_core", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_runner_core-7.3.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "built_collection", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/built_collection-5.1.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "built_value", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/built_value-8.9.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "characters", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/characters-1.3.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "checked_yaml", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/checked_yaml-2.0.3", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "clock", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/clock-1.1.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "code_builder", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/code_builder-4.10.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "collection", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/collection-1.17.1", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "convert", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/convert-3.1.1", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "coverage", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/coverage-1.6.4", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "crypto", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/crypto-3.0.3", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "dart_style", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/dart_style-2.3.2", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "diff_match_patch", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/diff_match_patch-0.4.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "fake_async", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/fake_async-1.3.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "file", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/file-7.0.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "fixnum", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/fixnum-1.1.0", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "flutter", + "rootUri": "file:///home/naveen-gloify/flutter/packages/flutter", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "flutter_bloc", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_bloc-8.1.4", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility-5.4.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_linux", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_linux-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_macos", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_macos-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_platform_interface", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_platform_interface-2.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_web", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_web-2.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_keyboard_visibility_windows", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_windows-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_lints", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_lints-2.0.3", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "flutter_localizations", + "rootUri": "file:///home/naveen-gloify/flutter/packages/flutter_localizations", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "flutter_spinkit", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_spinkit-5.2.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "flutter_test", + "rootUri": "file:///home/naveen-gloify/flutter/packages/flutter_test", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "flutter_typeahead", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_typeahead-4.8.0", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "flutter_web_plugins", + "rootUri": "file:///home/naveen-gloify/flutter/packages/flutter_web_plugins", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "fluttertoast", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "freezed", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/freezed-2.4.7", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "freezed_annotation", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/freezed_annotation-2.4.1", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "frontend_server_client", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/frontend_server_client-3.2.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "glob", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/glob-2.1.2", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "graphs", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/graphs-2.3.1", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "horizontal_data_table", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/horizontal_data_table-4.3.1", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "http_multi_server", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/http_multi_server-3.2.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "http_parser", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/http_parser-4.0.2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "intl", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/intl-0.18.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "io", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/io-1.0.4", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "js", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/js-0.6.7", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "json_annotation", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/json_annotation-4.8.1", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "json_serializable", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/json_serializable-6.7.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "lints", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/lints-2.1.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "location", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/location-5.0.3", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "location_platform_interface", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/location_platform_interface-3.1.2", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "location_web", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/location_web-4.2.0", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "logging", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/logging-1.2.0", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "matcher", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/matcher-0.12.15", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "material_color_utilities", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/material_color_utilities-0.2.0", + "packageUri": "lib/", + "languageVersion": "2.13" + }, + { + "name": "meta", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/meta-1.9.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "mime", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/mime-1.0.4", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "mocktail", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/mocktail-0.3.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "nested", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/nested-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "node_preamble", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/node_preamble-2.0.2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "overlay_builder", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/overlay_builder-1.1.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "package_config", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/package_config-2.1.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "path", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/path-1.8.3", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "plugin_platform_interface", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "pointer_interceptor", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/pointer_interceptor-0.9.3+5", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "pool", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/pool-1.5.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "provider", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/provider-6.1.2", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "pub_semver", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/pub_semver-2.1.4", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "pubspec_parse", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/pubspec_parse-1.2.3", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "reactive_flutter_typeahead", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/reactive_flutter_typeahead-0.7.0", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "reactive_forms", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/reactive_forms-14.3.0", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "shelf", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/shelf-1.4.1", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "shelf_packages_handler", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/shelf_packages_handler-3.0.2", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "shelf_static", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/shelf_static-1.1.2", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "shelf_web_socket", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/shelf_web_socket-1.0.4", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "sky_engine", + "rootUri": "file:///home/naveen-gloify/flutter/bin/cache/pkg/sky_engine", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "source_gen", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_gen-1.5.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "source_helper", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_helper-1.3.4", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "source_map_stack_trace", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_map_stack_trace-2.1.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "source_maps", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_maps-0.10.12", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "source_span", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_span-1.9.1", + "packageUri": "lib/", + "languageVersion": "2.14" + }, + { + "name": "stack_trace", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/stack_trace-1.11.0", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "stream_channel", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/stream_channel-2.1.1", + "packageUri": "lib/", + "languageVersion": "2.14" + }, + { + "name": "stream_transform", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/stream_transform-2.1.0", + "packageUri": "lib/", + "languageVersion": "2.14" + }, + { + "name": "string_scanner", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/string_scanner-1.2.0", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "term_glyph", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/term_glyph-1.2.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "test", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/test-1.24.1", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "test_api", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/test_api-0.5.1", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "test_core", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/test_core-0.5.1", + "packageUri": "lib/", + "languageVersion": "2.18" + }, + { + "name": "timing", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/timing-1.0.1", + "packageUri": "lib/", + "languageVersion": "2.14" + }, + { + "name": "typed_data", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/typed_data-1.3.2", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "vector_math", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/vector_math-2.1.4", + "packageUri": "lib/", + "languageVersion": "2.14" + }, + { + "name": "vm_service", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/vm_service-11.10.0", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "watcher", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/watcher-1.1.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "web_socket_channel", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/web_socket_channel-2.4.0", + "packageUri": "lib/", + "languageVersion": "2.15" + }, + { + "name": "webkit_inspection_protocol", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/webkit_inspection_protocol-1.2.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "yaml", + "rootUri": "file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/yaml-3.1.2", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "digit_components", + "rootUri": "../", + "packageUri": "lib/", + "languageVersion": "2.19" + } + ], + "generated": "2024-03-21T06:43:24.575479Z", + "generator": "pub", + "generatorVersion": "3.0.0" +} diff --git a/vehicle-tracker/packages/digit_components/.dart_tool/package_config_subset b/vehicle-tracker/packages/digit_components/.dart_tool/package_config_subset new file mode 100644 index 00000000..b467e737 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/.dart_tool/package_config_subset @@ -0,0 +1,425 @@ +_fe_analyzer_shared +2.17 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-61.0.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-61.0.0/lib/ +analyzer +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/analyzer-5.13.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/analyzer-5.13.0/lib/ +args +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/args-2.4.2/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/args-2.4.2/lib/ +async +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/async-2.11.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/async-2.11.0/lib/ +bloc +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/bloc-8.1.3/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/bloc-8.1.3/lib/ +bloc_test +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/bloc_test-9.1.6/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/bloc_test-9.1.6/lib/ +boolean_selector +2.17 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1/lib/ +build +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build-2.4.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build-2.4.1/lib/ +build_config +2.14 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_config-1.1.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_config-1.1.1/lib/ +build_daemon +3.0 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_daemon-4.0.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_daemon-4.0.1/lib/ +build_resolvers +3.0 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_resolvers-2.4.2/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_resolvers-2.4.2/lib/ +build_runner +3.0 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_runner-2.4.8/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_runner-2.4.8/lib/ +build_runner_core +3.0 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_runner_core-7.3.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/build_runner_core-7.3.0/lib/ +built_collection +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/built_collection-5.1.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/built_collection-5.1.1/lib/ +built_value +3.0 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/built_value-8.9.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/built_value-8.9.1/lib/ +characters +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/characters-1.3.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/characters-1.3.0/lib/ +checked_yaml +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/checked_yaml-2.0.3/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/checked_yaml-2.0.3/lib/ +clock +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/clock-1.1.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/clock-1.1.1/lib/ +code_builder +3.0 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/code_builder-4.10.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/code_builder-4.10.0/lib/ +collection +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/collection-1.17.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/collection-1.17.1/lib/ +convert +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/convert-3.1.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/convert-3.1.1/lib/ +coverage +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/coverage-1.6.4/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/coverage-1.6.4/lib/ +crypto +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/crypto-3.0.3/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/crypto-3.0.3/lib/ +dart_style +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/dart_style-2.3.2/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/dart_style-2.3.2/lib/ +diff_match_patch +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/diff_match_patch-0.4.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/diff_match_patch-0.4.1/lib/ +fake_async +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/fake_async-1.3.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/fake_async-1.3.1/lib/ +file +3.0 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/file-7.0.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/file-7.0.0/lib/ +fixnum +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/fixnum-1.1.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/fixnum-1.1.0/lib/ +flutter_bloc +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_bloc-8.1.4/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_bloc-8.1.4/lib/ +flutter_keyboard_visibility +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility-5.4.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility-5.4.1/lib/ +flutter_keyboard_visibility_linux +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_linux-1.0.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_linux-1.0.0/lib/ +flutter_keyboard_visibility_macos +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_macos-1.0.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_macos-1.0.0/lib/ +flutter_keyboard_visibility_platform_interface +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_platform_interface-2.0.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_platform_interface-2.0.0/lib/ +flutter_keyboard_visibility_web +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_web-2.0.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_web-2.0.0/lib/ +flutter_keyboard_visibility_windows +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_windows-1.0.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_windows-1.0.0/lib/ +flutter_lints +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_lints-2.0.3/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_lints-2.0.3/lib/ +flutter_spinkit +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_spinkit-5.2.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_spinkit-5.2.0/lib/ +flutter_typeahead +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_typeahead-4.8.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_typeahead-4.8.0/lib/ +fluttertoast +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4/lib/ +freezed +2.17 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/freezed-2.4.7/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/freezed-2.4.7/lib/ +freezed_annotation +2.17 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/freezed_annotation-2.4.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/freezed_annotation-2.4.1/lib/ +frontend_server_client +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/frontend_server_client-3.2.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/frontend_server_client-3.2.0/lib/ +glob +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/glob-2.1.2/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/glob-2.1.2/lib/ +graphs +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/graphs-2.3.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/graphs-2.3.1/lib/ +horizontal_data_table +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/horizontal_data_table-4.3.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/horizontal_data_table-4.3.1/lib/ +http_multi_server +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/http_multi_server-3.2.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/http_multi_server-3.2.1/lib/ +http_parser +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/http_parser-4.0.2/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/http_parser-4.0.2/lib/ +intl +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/intl-0.18.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/intl-0.18.0/lib/ +io +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/io-1.0.4/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/io-1.0.4/lib/ +js +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/js-0.6.7/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/js-0.6.7/lib/ +json_annotation +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/json_annotation-4.8.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/json_annotation-4.8.1/lib/ +json_serializable +3.0 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/json_serializable-6.7.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/json_serializable-6.7.1/lib/ +lints +3.0 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/lints-2.1.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/lints-2.1.1/lib/ +location +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/location-5.0.3/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/location-5.0.3/lib/ +location_platform_interface +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/location_platform_interface-3.1.2/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/location_platform_interface-3.1.2/lib/ +location_web +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/location_web-4.2.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/location_web-4.2.0/lib/ +logging +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/logging-1.2.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/logging-1.2.0/lib/ +matcher +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/matcher-0.12.15/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/matcher-0.12.15/lib/ +material_color_utilities +2.13 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/material_color_utilities-0.2.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/material_color_utilities-0.2.0/lib/ +meta +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/meta-1.9.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/meta-1.9.1/lib/ +mime +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/mime-1.0.4/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/mime-1.0.4/lib/ +mocktail +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/mocktail-0.3.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/mocktail-0.3.0/lib/ +nested +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/nested-1.0.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/nested-1.0.0/lib/ +node_preamble +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/node_preamble-2.0.2/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/node_preamble-2.0.2/lib/ +overlay_builder +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/overlay_builder-1.1.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/overlay_builder-1.1.0/lib/ +package_config +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/package_config-2.1.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/package_config-2.1.0/lib/ +path +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/path-1.8.3/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/path-1.8.3/lib/ +plugin_platform_interface +3.0 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8/lib/ +pointer_interceptor +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/pointer_interceptor-0.9.3+5/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/pointer_interceptor-0.9.3+5/lib/ +pool +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/pool-1.5.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/pool-1.5.1/lib/ +provider +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/provider-6.1.2/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/provider-6.1.2/lib/ +pub_semver +2.17 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/pub_semver-2.1.4/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/pub_semver-2.1.4/lib/ +pubspec_parse +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/pubspec_parse-1.2.3/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/pubspec_parse-1.2.3/lib/ +reactive_flutter_typeahead +2.17 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/reactive_flutter_typeahead-0.7.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/reactive_flutter_typeahead-0.7.0/lib/ +reactive_forms +2.17 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/reactive_forms-14.3.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/reactive_forms-14.3.0/lib/ +shelf +2.17 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/shelf-1.4.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/shelf-1.4.1/lib/ +shelf_packages_handler +2.17 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/shelf_packages_handler-3.0.2/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/shelf_packages_handler-3.0.2/lib/ +shelf_static +2.17 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/shelf_static-1.1.2/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/shelf_static-1.1.2/lib/ +shelf_web_socket +2.17 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/shelf_web_socket-1.0.4/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/shelf_web_socket-1.0.4/lib/ +source_gen +3.0 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_gen-1.5.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_gen-1.5.0/lib/ +source_helper +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_helper-1.3.4/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_helper-1.3.4/lib/ +source_map_stack_trace +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_map_stack_trace-2.1.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_map_stack_trace-2.1.1/lib/ +source_maps +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_maps-0.10.12/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_maps-0.10.12/lib/ +source_span +2.14 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_span-1.9.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/source_span-1.9.1/lib/ +stack_trace +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/stack_trace-1.11.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/stack_trace-1.11.0/lib/ +stream_channel +2.14 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/stream_channel-2.1.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/stream_channel-2.1.1/lib/ +stream_transform +2.14 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/stream_transform-2.1.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/stream_transform-2.1.0/lib/ +string_scanner +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/string_scanner-1.2.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/string_scanner-1.2.0/lib/ +term_glyph +2.12 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/term_glyph-1.2.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/term_glyph-1.2.1/lib/ +test +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/test-1.24.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/test-1.24.1/lib/ +test_api +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/test_api-0.5.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/test_api-0.5.1/lib/ +test_core +2.18 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/test_core-0.5.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/test_core-0.5.1/lib/ +timing +2.14 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/timing-1.0.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/timing-1.0.1/lib/ +typed_data +2.17 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/typed_data-1.3.2/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/typed_data-1.3.2/lib/ +vector_math +2.14 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/vector_math-2.1.4/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/vector_math-2.1.4/lib/ +vm_service +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/vm_service-11.10.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/vm_service-11.10.0/lib/ +watcher +3.0 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/watcher-1.1.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/watcher-1.1.0/lib/ +web_socket_channel +2.15 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/web_socket_channel-2.4.0/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/web_socket_channel-2.4.0/lib/ +webkit_inspection_protocol +3.0 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/webkit_inspection_protocol-1.2.1/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/webkit_inspection_protocol-1.2.1/lib/ +yaml +2.19 +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/yaml-3.1.2/ +file:///home/naveen-gloify/.pub-cache/hosted/pub.dev/yaml-3.1.2/lib/ +digit_components +2.19 +file:///home/naveen-gloify/Documents/GitHub/egov-rnd/vehicle-tracker/vehicle_tracker_app/packages/digit_components/ +file:///home/naveen-gloify/Documents/GitHub/egov-rnd/vehicle-tracker/vehicle_tracker_app/packages/digit_components/lib/ +sky_engine +3.0 +file:///home/naveen-gloify/flutter/bin/cache/pkg/sky_engine/ +file:///home/naveen-gloify/flutter/bin/cache/pkg/sky_engine/lib/ +flutter +3.0 +file:///home/naveen-gloify/flutter/packages/flutter/ +file:///home/naveen-gloify/flutter/packages/flutter/lib/ +flutter_localizations +3.0 +file:///home/naveen-gloify/flutter/packages/flutter_localizations/ +file:///home/naveen-gloify/flutter/packages/flutter_localizations/lib/ +flutter_test +3.0 +file:///home/naveen-gloify/flutter/packages/flutter_test/ +file:///home/naveen-gloify/flutter/packages/flutter_test/lib/ +flutter_web_plugins +3.0 +file:///home/naveen-gloify/flutter/packages/flutter_web_plugins/ +file:///home/naveen-gloify/flutter/packages/flutter_web_plugins/lib/ +2 diff --git a/vehicle-tracker/packages/digit_components/.dart_tool/version b/vehicle-tracker/packages/digit_components/.dart_tool/version new file mode 100644 index 00000000..e06d07af --- /dev/null +++ b/vehicle-tracker/packages/digit_components/.dart_tool/version @@ -0,0 +1 @@ +3.10.0 \ No newline at end of file diff --git a/vehicle-tracker/packages/digit_components/.flutter-plugins b/vehicle-tracker/packages/digit_components/.flutter-plugins new file mode 100644 index 00000000..b1d391a2 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/.flutter-plugins @@ -0,0 +1,9 @@ +# This is a generated file; do not edit or check into version control. +flutter_keyboard_visibility=/home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility-5.4.1/ +flutter_keyboard_visibility_linux=/home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_linux-1.0.0/ +flutter_keyboard_visibility_macos=/home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_macos-1.0.0/ +flutter_keyboard_visibility_web=/home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_web-2.0.0/ +flutter_keyboard_visibility_windows=/home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_windows-1.0.0/ +fluttertoast=/home/naveen-gloify/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4/ +location=/home/naveen-gloify/.pub-cache/hosted/pub.dev/location-5.0.3/ +location_web=/home/naveen-gloify/.pub-cache/hosted/pub.dev/location_web-4.2.0/ diff --git a/vehicle-tracker/packages/digit_components/.flutter-plugins-dependencies b/vehicle-tracker/packages/digit_components/.flutter-plugins-dependencies new file mode 100644 index 00000000..04b61cf0 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/.flutter-plugins-dependencies @@ -0,0 +1 @@ +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_keyboard_visibility","path":"/home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility-5.4.1/","native_build":true,"dependencies":[]},{"name":"fluttertoast","path":"/home/naveen-gloify/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4/","native_build":true,"dependencies":[]},{"name":"location","path":"/home/naveen-gloify/.pub-cache/hosted/pub.dev/location-5.0.3/","native_build":true,"dependencies":[]}],"android":[{"name":"flutter_keyboard_visibility","path":"/home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility-5.4.1/","native_build":true,"dependencies":[]},{"name":"fluttertoast","path":"/home/naveen-gloify/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4/","native_build":true,"dependencies":[]},{"name":"location","path":"/home/naveen-gloify/.pub-cache/hosted/pub.dev/location-5.0.3/","native_build":true,"dependencies":[]}],"macos":[{"name":"flutter_keyboard_visibility_macos","path":"/home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_macos-1.0.0/","native_build":false,"dependencies":[]},{"name":"location","path":"/home/naveen-gloify/.pub-cache/hosted/pub.dev/location-5.0.3/","native_build":true,"dependencies":[]}],"linux":[{"name":"flutter_keyboard_visibility_linux","path":"/home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_linux-1.0.0/","native_build":false,"dependencies":[]}],"windows":[{"name":"flutter_keyboard_visibility_windows","path":"/home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_windows-1.0.0/","native_build":false,"dependencies":[]}],"web":[{"name":"flutter_keyboard_visibility_web","path":"/home/naveen-gloify/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_web-2.0.0/","dependencies":[]},{"name":"fluttertoast","path":"/home/naveen-gloify/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4/","dependencies":[]},{"name":"location_web","path":"/home/naveen-gloify/.pub-cache/hosted/pub.dev/location_web-4.2.0/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_keyboard_visibility","dependencies":["flutter_keyboard_visibility_linux","flutter_keyboard_visibility_macos","flutter_keyboard_visibility_web","flutter_keyboard_visibility_windows"]},{"name":"flutter_keyboard_visibility_linux","dependencies":[]},{"name":"flutter_keyboard_visibility_macos","dependencies":[]},{"name":"flutter_keyboard_visibility_web","dependencies":[]},{"name":"flutter_keyboard_visibility_windows","dependencies":[]},{"name":"fluttertoast","dependencies":[]},{"name":"location","dependencies":["location_web"]},{"name":"location_web","dependencies":[]}],"date_created":"2024-03-21 12:13:24.771360","version":"3.10.0"} \ No newline at end of file diff --git a/vehicle-tracker/packages/digit_components/CHANGELOG.md b/vehicle-tracker/packages/digit_components/CHANGELOG.md new file mode 100644 index 00000000..d306fc0b --- /dev/null +++ b/vehicle-tracker/packages/digit_components/CHANGELOG.md @@ -0,0 +1,31 @@ +## 0.0.1 + +* Initial Releaase + +## 0.0.1+1 + +* Read Me file added + +## 0.0.1+2 + +* Read Me file modified with Components example + +## 0.0.1+3 + +* example file added + +## 0.0.1+4 + +* dart doc added and auto generated files added + +## 0.0.1+5 + +* Example file with Reactive Forms + +## 0.0.1+6 + +* Updated Components behaviour in ReadMe File + +## 0.0.1+8 + +* Updated Images in ReadMe File \ No newline at end of file diff --git a/vehicle-tracker/packages/digit_components/LICENSE b/vehicle-tracker/packages/digit_components/LICENSE new file mode 100644 index 00000000..331d2b43 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 eGovernments Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vehicle-tracker/packages/digit_components/README.md b/vehicle-tracker/packages/digit_components/README.md new file mode 100644 index 00000000..c192395a --- /dev/null +++ b/vehicle-tracker/packages/digit_components/README.md @@ -0,0 +1,465 @@ +# **DIGIT Components** + +**DigitActionDialog** : + A customizable dialog with multiple action buttons / widgets. + + Usage: + onPressed : () => DigitActionDialog.show( + context, + widget: your_widget() + ) + Digit Action Dialog + + +**DigitCheckBox** : + A single checkbox component. + + Usage: + DigitCheckbox( + label: “your_label”, + value: boolean_value, + ), + +![CheckBox](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/e1c9a6d1-cb0c-4b95-9dea-dddd6ff98f17) + +**DigitDateFormPicker** : + A Reactive Date Picker widget with custom label header. The formControlName is required to bind this ReactiveDatePicker to a FormControl. + + Usage: + DigitDateFormPicker( + label: 'Date of Birth', + padding: const EdgeInsets.only(top: 32.0), + isRequired: true, + cancelText: 'Cancel', + fieldHintText: 'dd/mm/yyyy', + confirmText: 'OK', + icon: Icons.info_outline_rounded, + toolTipMsg: 'Age should not be less than 18 years', + formControlName: ’dob_key’, + autoValidation: AutovalidateMode.always, + requiredMessage: 'Date of birth is required', + validationMessages: { + 'required': (_) => ‘Date of birth is required’, + 'max': (_) => ‘Age cannot be greater than 18 years’ + },) + +Date Picker ![Date Form Picker](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/93f326aa-df4e-40a6-af5b-34155760c01b) + + + **DigitDivider** : + A simple divider widget + + Usage: + DigitDivider() + +![Divider](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/e953c1bc-8513-4370-a0f1-aaa8e914a7c0) + +**DigitDropdown** : + A custom dropdown component with label header. + + Usage: + DigitDropdown( + value: state.selectedBoundaryMap.entries + .firstWhereOrNull( + (element) => element.key == label, + ) + ?.value, + label: label, + menuItems: your_item_list, + onChanged: (value) { + if (value == null) return; + //Any functions to perform on change or on select of the dropdown + }, + valueMapper: (value) { + return value.name ?? value.code ?? 'No Value'; + },) +Dropdown Field Digit Dropdown + +**DigitIconButton** : + A custom icon widget with customizable icon, icon Text, icon color, icon Text Color + + Usage: + DigitIconButton( + icon: Icons.check_circle, + iconText: 'delivered', + iconTextColor: Colors.white, + iconColor: Colors.orange, + ) +![DigitIcon Button](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/03cb82f3-500e-41c9-bdb4-f0bfb9b8b7ae) + +**DigitIntegerFormPicker** : + An Integer Picker with option to select any number by increasing or decreasing the using + and - end buttons + + + + Usage: + DigitIntegerFormPicker( + form: form, + minimum: 0, + formControlName: _quantityDistributedKey, + label: ‘Number of members’, + incrementer: true, + ), + +![Digit Integer Form Picker](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/78a2e080-799c-4146-8e10-0eaea6f732f9) + +**DigitOutlineIconButton** : + An outlined button with a leading icon based on DIGIT figma. + + Usage: + DigitOutlineIconButton( + icon: Icons.warning, + label:’Decline’, + onPressed: () => call_your_on_pressed_function(), + ) + +DigitOutlineIcon Button + + +**DigitReactiveDropdown** : + A reactive dropdown form component. The formControlName is required to bind this ReactiveDropdownField to a FormControl + + Usage: + DigitReactiveDropdown( + label: ‘relationship’, + menuItems: + relationship.map((e) => e.toString()).toList(), + isRequired: true, + formControlName: relationshipKey, + valueMapper: (value) => + t.translate('CORE_COMMON_$value'), + onChanged: (value) {}, + validationMessages: { + 'required': (_) => t.translate( + i18.wageSeeker.relationshipRequired, + ), + }, + ) +![DigitReactive Type ahead](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/ff5ea5c4-2c9b-4340-a03e-456b4b762894) + +**DigitTextFormField** : + A reactive form reactive dropdown component. The formControlName is required to bind this ReactiveTextField to a FormControl + + Usage: + DigitTextFormField( + formControlName: fatherNameKey, + isRequired: true, + label: t.translate(i18.common.guardianName), + inputFormatter: [ + FilteringTextInputFormatter.allow(RegExp("[A-Za-z ]")) + ], + validationMessages: { + 'required': (_) => t.translate( + i18.wageSeeker.fatherNameRequired, + ), + 'minLength': (_) => t.translate( + i18.wageSeeker.minFatherNameCharacters, + ), + 'maxLength': (_) => t.translate( + i18.wageSeeker.maxFatherNameCharacters, + ), + }, + ) + +Digit Text Form Field + + +**DigitToast** : + To show a toast message based on completion of user actions + + Usage: + DigitToast.show( + context, + options: DigitToastOptions( + message ?? 'Unable to login', + true, + theme, + ), + ); + +![Digit Toast](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/4c29786d-51e9-4583-9ea5-73e4a6b829df) + + +**DigitCard** : + A Card component with onPressed functions + + Usage: + DigitCard( + child: Text(‘Card Details’), + onPressed: null) + +![Digit Card](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/92a201dc-47a0-42e4-a085-e5faec0d6de5) + + +**DigitCheckBoxTile** : + It is a List of checkbox widgets, with label heading + + + Usage: + DigitCheckboxTile( + margin: const EdgeInsets.only(top: 16), + padding: const EdgeInsets.fromLTRB(0, 8, 8, 8), + label: hint ?? 'Some', + value: (control.value ?? false) as bool, + onChanged: (value) => control.value = value, + ) + +![CheckBox List Tile](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/e6132fb8-00fb-49e9-91c6-20d2555211c8) + + +**DigitDialog** : + A customizable dialog with options to add a custom title for the dialog , subtitle for the dialog and action buttons. It can be used on any on Pressed buttons to show this dialog + + + Usage: + () => DigitDialog.show(context, + options: DigitDialogOptions( + titleIcon: const Icon( + Icons.warning, + color: Colors.red, + ), + titleText: ‘Warning’ + contentText: ‘Are you sure to decline ?’, + primaryAction: DigitDialogActions( + label: ‘Confirm’, + action: (BuildContext context) { + //your_primary_action(); + }, + ), + secondaryAction: DigitDialogActions( + label: ‘Cancel’, + action: (BuildContext context) => + //your_secondary_action(), + ))); + +Digit Dialog + + +**DigitDobPicker** : + It is an enhanced component of DigitDateFormPicker. Here we have an additional Text field component which will be displaying the age based on the selected date and validate the age. + + Usage: + DigitDobPicker( + datePickerFormControl: _dobKey, + datePickerLabel: localizations.translate( + i18.individualDetails.dobLabelText, + ), + ageFieldLabel: localizations.translate( + i18.individualDetails.ageLabelText, + ), + separatorLabel: localizations.translate( + i18.individualDetails.separatorLabelText, + ), + ), +![DOB Picker](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/d1955dac-fba1-443f-bdb9-19c79f81f3e8) + + +**DigitElevatedButton** : + It is an elevated button with label widget options and onPressed functions based on DIGIT Figma + + Usage: + DigitElevatedButton( + onPressed: ()=> your_on_Pressed_function(), + child: Center( + child: Text( + ‘Manage wage seekers’, + style: Theme.of(context) + .textTheme + .titleMedium! + .apply(color: Colors.white)), + ),); + +Digit Elevated Button + + +**DigitIconTile** : + A custom list tile widget with options to add leading icon and onPressed function. Mostly it is used in Sidebar tiles. + + Usage: + DigitIconTile( + title: ‘View Profile’, + selected: context.router.currentPath.contains('orgProfile'), + icon: Icons.perm_contact_cal_sharp, + onPressed: () => your_on_pressed_function()) + +DigitIconTile + + +**DigitInfoCard** : + A custom information card based on DIGIT Figma. Here we have options to add the desired icon, background color, icon color, description and heading title of the information card. + + Usage: + DigitInfoCard( + icon: Icons.info, + backgroundColor: theme.colorScheme.tertiaryContainer, + iconColor: theme.colorScheme.surfaceTint, + description: localizations + .translate(i18.home.dataSyncInfoContent) + .replaceAll('{}', count.toString()), + title: localizations.translate( + i18.home.dataSyncInfoLabel, + ), + ), + +![Digit Info Card](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/104d3f92-73c3-4800-b6ac-b1cd22af1ad4) + +**DigitOutlineButton** : + An outlined button based on DIGIT figma. + + Usage: + DigitOutLineButton( + label: localizations.translate( + i18.memberCard.deliverDetailsUpdateLabel, + ), + onPressed: () => your_on_pressed_function(), + ) +DigitOutline button + +**DigitReactiveTypeAhead** : +A TypeAhead (autocomplete) widget , where you can show suggestions to users as they type + + Usage: + DigitReactiveTypeAhead( + formControlName: formControlName, + stringify: valueMapper, + initialValue: initialValue, + initialValueText: initialValueText, + onSuggestionSelected: onSuggestionSelected, + debounceDuration: const Duration(milliseconds: 100), + suggestionsCallback: (pattern) => suggestionsCallback( + menuItems, + pattern, + ), + itemBuilder: (context, item) { + return Padding( + padding: const EdgeInsets.all(kPadding * 2), + child: Text( + valueMapper(item), + style: Theme.of(context).textTheme.bodyLarge, + ), + ); + }, + ) +![DigitReactive Type ahead](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/ed1426eb-d0ce-4b72-9391-5c51a8ca566c) + +**DigitSearchBar** : + A search bar based on DIGIT figma. It has on change functionality to perform actions on text change. A hint text can also be added on the search bar + + Usage: + DigitSearchBar( + controller: searchController, + hintText: localizations.translate( + i18.searchBeneficiary.beneficiarySearchHintText, + ), + textCapitalization: TextCapitalization.words, + onChanged: (value) => your_on_change_function() + ), + +![Digit Search Bar](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/6f5bb44f-49f4-4710-9349-a794294d46f5) + +**DigitSearchDropdown** : + A searchable drop down that wraps DigitReactiveTypeAhead and has a custom label widget. + + Usage: + DigitSearchDropdown( + label: ‘City’ + formControlName: formControlName, + stringify: valueMapper, + initialValue: initialValue, + initialValueText: initialValueText, + onSuggestionSelected: onSuggestionSelected, + debounceDuration: const Duration(milliseconds: 100), + suggestionsCallback: (pattern) => suggestionsCallback( + menuItems, + pattern, + ), + itemBuilder: (context, item) { + return Padding( + padding: const EdgeInsets.all(kPadding * 2), + child: Text( + valueMapper(item), + style: Theme.of(context).textTheme.bodyLarge, + ), + ); + }, + ) + +![Digit Search Dropdown](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/ec616ced-5b7b-4f9c-86f7-e054c358bc80) + + +**DigitSyncDialogContent** : + A sync dialog with options to add a custom label for the dialog , and type of the dialog. There are 3 types of sync dialog : + **In Progress** + **Completed** + **Failed** + + Usage: + () => DigitSyncDialogContent.show( + context, + type: DigitSyncDialogType.complete, + label: 'Data Synced', + primaryAction: DigitDialogActions( + label: 'Close', + action: (act) { + Navigator.pop(act); + }, + ), + ); + +![Digit SyncDialog](https://github.com/egovernments/health-campaign-field-worker-app/assets/85437265/7e6a400b-1417-4310-85fb-2c4a38af505f) + + +**DigitTextField** : + A text field component similar to DigitTextFormField. It can be used without wrapping under reactive form + + Usage: + DigitTextField( + readOnly: true, + label: localizations.translate( + i18.householdLocation.administrationAreaFormLabel, + ), + controller: TextEditingController( + text: context.boundary.code, + ), + ), + +Digit Text Form Field + +**LabeledField** : + A labeled widget which has a child widget. If any field need to have a label on its top, then that widget can be wrapped with this LabeledField. + + Usage: + LabeledField( + label: '$label ${isRequired ? '*' : ''}', + padding: padding, + labelStyle: Theme.of(context).textTheme.bodyLarge, + icon: icon, + toolTipMsg: toolTipMsg, + child: ReactiveDatePicker()) + +Digit Text Form Field + + +**PoweredByDigit** : + Generic Digit Footer. + + Usage: + PoweredByDigit( + isWhiteLogo: true, + ) +Powered By Digit Colored Powered By Digit White + + +**ScrollableContent** : + A Scrollable wrapper widget. All children widgets can be wrapped inside a single scroll card. + + Usage: + ScrollableContent( + header: Column(children: const [ + Back(), + DigitCard(), + ]), + footer: PoweredByDigit() + ) +Scrollable Content + diff --git a/vehicle-tracker/packages/digit_components/analysis_options.yaml b/vehicle-tracker/packages/digit_components/analysis_options.yaml new file mode 100644 index 00000000..9d8e06d9 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/analysis_options.yaml @@ -0,0 +1,6 @@ +include: package:flutter_lints/flutter.yaml + +analyzer: + exclude: + - "**/*.g.dart" + - "**/*.freezed.dart" \ No newline at end of file diff --git a/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/LICENSE.txt b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/LICENSE.txt new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Black.ttf b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Black.ttf new file mode 100644 index 00000000..0112e7da Binary files /dev/null and b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Black.ttf differ diff --git a/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-BlackItalic.ttf b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-BlackItalic.ttf new file mode 100644 index 00000000..b2c6aca5 Binary files /dev/null and b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-BlackItalic.ttf differ diff --git a/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Bold.ttf b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Bold.ttf new file mode 100644 index 00000000..43da14d8 Binary files /dev/null and b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Bold.ttf differ diff --git a/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-BoldItalic.ttf b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-BoldItalic.ttf new file mode 100644 index 00000000..bcfdab43 Binary files /dev/null and b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-BoldItalic.ttf differ diff --git a/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Italic.ttf b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Italic.ttf new file mode 100644 index 00000000..1b5eaa36 Binary files /dev/null and b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Italic.ttf differ diff --git a/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Light.ttf b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Light.ttf new file mode 100644 index 00000000..e7307e72 Binary files /dev/null and b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Light.ttf differ diff --git a/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-LightItalic.ttf b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-LightItalic.ttf new file mode 100644 index 00000000..2d277afb Binary files /dev/null and b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-LightItalic.ttf differ diff --git a/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Medium.ttf b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Medium.ttf new file mode 100644 index 00000000..ac0f908b Binary files /dev/null and b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Medium.ttf differ diff --git a/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-MediumItalic.ttf b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-MediumItalic.ttf new file mode 100644 index 00000000..fc36a478 Binary files /dev/null and b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-MediumItalic.ttf differ diff --git a/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Regular.ttf b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Regular.ttf new file mode 100644 index 00000000..ddf4bfac Binary files /dev/null and b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Regular.ttf differ diff --git a/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Thin.ttf b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Thin.ttf new file mode 100644 index 00000000..2e0dee6a Binary files /dev/null and b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/Roboto-Thin.ttf differ diff --git a/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/RobotoCondensed-Regular.ttf b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/RobotoCondensed-Regular.ttf new file mode 100644 index 00000000..17e8ea57 Binary files /dev/null and b/vehicle-tracker/packages/digit_components/assets/fonts/Roboto/RobotoCondensed-Regular.ttf differ diff --git a/vehicle-tracker/packages/digit_components/assets/images/powered_by_digit.png b/vehicle-tracker/packages/digit_components/assets/images/powered_by_digit.png new file mode 100644 index 00000000..f83334fd Binary files /dev/null and b/vehicle-tracker/packages/digit_components/assets/images/powered_by_digit.png differ diff --git a/vehicle-tracker/packages/digit_components/lib/blocs/location/location.dart b/vehicle-tracker/packages/digit_components/lib/blocs/location/location.dart new file mode 100644 index 00000000..0e4096ba --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/blocs/location/location.dart @@ -0,0 +1,189 @@ +import 'dart:async'; + +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:location/location.dart'; + +part 'location.freezed.dart'; + +typedef LocationStateEmitter = Emitter; + +/// LocationBLoC +/// +/// Follow setup instructions for appropriate platform +/// Android - +/// iOS - +/// macOS - +class LocationBloc extends Bloc { + final Location location; + + LocationBloc({required this.location}) : super(const LocationState()) { + on(_handleLoadLocation); + on(_handleRequestPermission); + on(_handleRequestService); + on(_handleSetLatLng); + on(_handleListenLocation); + } + + FutureOr _handleRequestPermission( + RequestLocationPermissionEvent event, + LocationStateEmitter emit, + ) async { + emit(state.copyWith(loading: true)); + try { + final permissions = await location.hasPermission(); + final hasPermissions = [ + PermissionStatus.granted, + PermissionStatus.grantedLimited, + ].contains(permissions); + emit(state.copyWith(hasPermissions: hasPermissions)); + if (!hasPermissions) { + if (event.retry > 0) { + await location.requestPermission(); + add(RequestLocationPermissionEvent(retry: event.retry - 1)); + } else { + throw Exception('Location permission request rejected'); + } + } else { + add(const LoadLocationEvent()); + } + } catch (error) { + rethrow; + } finally { + emit(state.copyWith(loading: false)); + } + } + + FutureOr _handleRequestService( + RequestLocationServiceEvent event, + LocationStateEmitter emit, + ) async { + emit(state.copyWith(loading: true)); + try { + final serviceEnabled = await location.serviceEnabled(); + emit(state.copyWith(serviceEnabled: serviceEnabled)); + if (!serviceEnabled) { + if (event.retry > 0) { + await location.requestService(); + add(RequestLocationServiceEvent(retry: event.retry - 1)); + } else { + throw Exception('Location service request rejected'); + } + } else { + add(const LoadLocationEvent()); + } + } catch (error) { + rethrow; + } finally { + emit(state.copyWith(loading: false)); + } + } + + FutureOr _handleListenLocation( + ListenLocationEvent event, + LocationStateEmitter emit, + ) async { + location.onLocationChanged.listen((locationData) { + add(LocationSetLatLngEvent(locationData: locationData)); + }); + } + + FutureOr _handleLoadLocation( + LoadLocationEvent event, + LocationStateEmitter emit, + ) async { + emit(state.copyWith(loading: true)); + try { + final permissions = await location.hasPermission(); + + if (![ + PermissionStatus.granted, + PermissionStatus.grantedLimited, + ].contains(permissions)) { + emit(state.copyWith(hasPermissions: false)); + add(const RequestLocationPermissionEvent()); + return; + } else { + emit(state.copyWith(hasPermissions: true)); + } + + final serviceEnabled = await location.serviceEnabled(); + emit(state.copyWith(serviceEnabled: serviceEnabled)); + + if (!serviceEnabled) { + add(const RequestLocationServiceEvent()); + return; + } + + add(const ListenLocationEvent()); + final locationData = await location.getLocation(); + add(LocationSetLatLngEvent(locationData: locationData)); + } catch (error) { + rethrow; + } finally { + emit(state.copyWith(loading: false)); + } + } + + void _handleSetLatLng( + LocationSetLatLngEvent event, + LocationStateEmitter emit, + ) { + final locationData = event.locationData; + + if ([ + locationData.latitude, + locationData.longitude, + ].any((element) => element == null)) { + throw Exception('Could not fetch location data'); + } + + emit(state.copyWith( + latitude: locationData.latitude, + longitude: locationData.longitude, + accuracy: locationData.accuracy, + )); + } +} + +@freezed +class LocationEvent with _$LocationEvent { + const factory LocationEvent.load({ + @Default(5) int retry, + }) = LoadLocationEvent; + + const factory LocationEvent.listen({ + @Default(5) int retry, + }) = ListenLocationEvent; + + const factory LocationEvent.requestService({ + @Default(5) int retry, + }) = RequestLocationServiceEvent; + + const factory LocationEvent.requestPermission({ + @Default(1) int retry, + }) = RequestLocationPermissionEvent; + + const factory LocationEvent.setLatLng({ + required LocationData locationData, + }) = LocationSetLatLngEvent; +} + +@freezed +class LocationState with _$LocationState { + const LocationState._(); + + const factory LocationState({ + double? latitude, + double? longitude, + double? accuracy, + @Default(false) hasPermissions, + @Default(false) bool serviceEnabled, + @Default(false) bool loading, + }) = _LocationState; + + String get latLngString { + if (latitude == null || longitude == null) return 'Undefined'; + return [latitude, longitude].join(', '); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/blocs/location/location.freezed.dart b/vehicle-tracker/packages/digit_components/lib/blocs/location/location.freezed.dart new file mode 100644 index 00000000..895d57b4 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/blocs/location/location.freezed.dart @@ -0,0 +1,1107 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'location.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +/// @nodoc +mixin _$LocationEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(int retry) load, + required TResult Function(int retry) listen, + required TResult Function(int retry) requestService, + required TResult Function(int retry) requestPermission, + required TResult Function(LocationData locationData) setLatLng, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(int retry)? load, + TResult? Function(int retry)? listen, + TResult? Function(int retry)? requestService, + TResult? Function(int retry)? requestPermission, + TResult? Function(LocationData locationData)? setLatLng, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(int retry)? load, + TResult Function(int retry)? listen, + TResult Function(int retry)? requestService, + TResult Function(int retry)? requestPermission, + TResult Function(LocationData locationData)? setLatLng, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(LoadLocationEvent value) load, + required TResult Function(ListenLocationEvent value) listen, + required TResult Function(RequestLocationServiceEvent value) requestService, + required TResult Function(RequestLocationPermissionEvent value) + requestPermission, + required TResult Function(LocationSetLatLngEvent value) setLatLng, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(LoadLocationEvent value)? load, + TResult? Function(ListenLocationEvent value)? listen, + TResult? Function(RequestLocationServiceEvent value)? requestService, + TResult? Function(RequestLocationPermissionEvent value)? requestPermission, + TResult? Function(LocationSetLatLngEvent value)? setLatLng, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(LoadLocationEvent value)? load, + TResult Function(ListenLocationEvent value)? listen, + TResult Function(RequestLocationServiceEvent value)? requestService, + TResult Function(RequestLocationPermissionEvent value)? requestPermission, + TResult Function(LocationSetLatLngEvent value)? setLatLng, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LocationEventCopyWith<$Res> { + factory $LocationEventCopyWith( + LocationEvent value, $Res Function(LocationEvent) then) = + _$LocationEventCopyWithImpl<$Res, LocationEvent>; +} + +/// @nodoc +class _$LocationEventCopyWithImpl<$Res, $Val extends LocationEvent> + implements $LocationEventCopyWith<$Res> { + _$LocationEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; +} + +/// @nodoc +abstract class _$$LoadLocationEventCopyWith<$Res> { + factory _$$LoadLocationEventCopyWith( + _$LoadLocationEvent value, $Res Function(_$LoadLocationEvent) then) = + __$$LoadLocationEventCopyWithImpl<$Res>; + @useResult + $Res call({int retry}); +} + +/// @nodoc +class __$$LoadLocationEventCopyWithImpl<$Res> + extends _$LocationEventCopyWithImpl<$Res, _$LoadLocationEvent> + implements _$$LoadLocationEventCopyWith<$Res> { + __$$LoadLocationEventCopyWithImpl( + _$LoadLocationEvent _value, $Res Function(_$LoadLocationEvent) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? retry = null, + }) { + return _then(_$LoadLocationEvent( + retry: null == retry + ? _value.retry + : retry // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc + +class _$LoadLocationEvent implements LoadLocationEvent { + const _$LoadLocationEvent({this.retry = 5}); + + @override + @JsonKey() + final int retry; + + @override + String toString() { + return 'LocationEvent.load(retry: $retry)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$LoadLocationEvent && + (identical(other.retry, retry) || other.retry == retry)); + } + + @override + int get hashCode => Object.hash(runtimeType, retry); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$LoadLocationEventCopyWith<_$LoadLocationEvent> get copyWith => + __$$LoadLocationEventCopyWithImpl<_$LoadLocationEvent>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(int retry) load, + required TResult Function(int retry) listen, + required TResult Function(int retry) requestService, + required TResult Function(int retry) requestPermission, + required TResult Function(LocationData locationData) setLatLng, + }) { + return load(retry); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(int retry)? load, + TResult? Function(int retry)? listen, + TResult? Function(int retry)? requestService, + TResult? Function(int retry)? requestPermission, + TResult? Function(LocationData locationData)? setLatLng, + }) { + return load?.call(retry); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(int retry)? load, + TResult Function(int retry)? listen, + TResult Function(int retry)? requestService, + TResult Function(int retry)? requestPermission, + TResult Function(LocationData locationData)? setLatLng, + required TResult orElse(), + }) { + if (load != null) { + return load(retry); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(LoadLocationEvent value) load, + required TResult Function(ListenLocationEvent value) listen, + required TResult Function(RequestLocationServiceEvent value) requestService, + required TResult Function(RequestLocationPermissionEvent value) + requestPermission, + required TResult Function(LocationSetLatLngEvent value) setLatLng, + }) { + return load(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(LoadLocationEvent value)? load, + TResult? Function(ListenLocationEvent value)? listen, + TResult? Function(RequestLocationServiceEvent value)? requestService, + TResult? Function(RequestLocationPermissionEvent value)? requestPermission, + TResult? Function(LocationSetLatLngEvent value)? setLatLng, + }) { + return load?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(LoadLocationEvent value)? load, + TResult Function(ListenLocationEvent value)? listen, + TResult Function(RequestLocationServiceEvent value)? requestService, + TResult Function(RequestLocationPermissionEvent value)? requestPermission, + TResult Function(LocationSetLatLngEvent value)? setLatLng, + required TResult orElse(), + }) { + if (load != null) { + return load(this); + } + return orElse(); + } +} + +abstract class LoadLocationEvent implements LocationEvent { + const factory LoadLocationEvent({final int retry}) = _$LoadLocationEvent; + + int get retry; + @JsonKey(ignore: true) + _$$LoadLocationEventCopyWith<_$LoadLocationEvent> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$ListenLocationEventCopyWith<$Res> { + factory _$$ListenLocationEventCopyWith(_$ListenLocationEvent value, + $Res Function(_$ListenLocationEvent) then) = + __$$ListenLocationEventCopyWithImpl<$Res>; + @useResult + $Res call({int retry}); +} + +/// @nodoc +class __$$ListenLocationEventCopyWithImpl<$Res> + extends _$LocationEventCopyWithImpl<$Res, _$ListenLocationEvent> + implements _$$ListenLocationEventCopyWith<$Res> { + __$$ListenLocationEventCopyWithImpl( + _$ListenLocationEvent _value, $Res Function(_$ListenLocationEvent) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? retry = null, + }) { + return _then(_$ListenLocationEvent( + retry: null == retry + ? _value.retry + : retry // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc + +class _$ListenLocationEvent implements ListenLocationEvent { + const _$ListenLocationEvent({this.retry = 5}); + + @override + @JsonKey() + final int retry; + + @override + String toString() { + return 'LocationEvent.listen(retry: $retry)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ListenLocationEvent && + (identical(other.retry, retry) || other.retry == retry)); + } + + @override + int get hashCode => Object.hash(runtimeType, retry); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$ListenLocationEventCopyWith<_$ListenLocationEvent> get copyWith => + __$$ListenLocationEventCopyWithImpl<_$ListenLocationEvent>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(int retry) load, + required TResult Function(int retry) listen, + required TResult Function(int retry) requestService, + required TResult Function(int retry) requestPermission, + required TResult Function(LocationData locationData) setLatLng, + }) { + return listen(retry); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(int retry)? load, + TResult? Function(int retry)? listen, + TResult? Function(int retry)? requestService, + TResult? Function(int retry)? requestPermission, + TResult? Function(LocationData locationData)? setLatLng, + }) { + return listen?.call(retry); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(int retry)? load, + TResult Function(int retry)? listen, + TResult Function(int retry)? requestService, + TResult Function(int retry)? requestPermission, + TResult Function(LocationData locationData)? setLatLng, + required TResult orElse(), + }) { + if (listen != null) { + return listen(retry); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(LoadLocationEvent value) load, + required TResult Function(ListenLocationEvent value) listen, + required TResult Function(RequestLocationServiceEvent value) requestService, + required TResult Function(RequestLocationPermissionEvent value) + requestPermission, + required TResult Function(LocationSetLatLngEvent value) setLatLng, + }) { + return listen(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(LoadLocationEvent value)? load, + TResult? Function(ListenLocationEvent value)? listen, + TResult? Function(RequestLocationServiceEvent value)? requestService, + TResult? Function(RequestLocationPermissionEvent value)? requestPermission, + TResult? Function(LocationSetLatLngEvent value)? setLatLng, + }) { + return listen?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(LoadLocationEvent value)? load, + TResult Function(ListenLocationEvent value)? listen, + TResult Function(RequestLocationServiceEvent value)? requestService, + TResult Function(RequestLocationPermissionEvent value)? requestPermission, + TResult Function(LocationSetLatLngEvent value)? setLatLng, + required TResult orElse(), + }) { + if (listen != null) { + return listen(this); + } + return orElse(); + } +} + +abstract class ListenLocationEvent implements LocationEvent { + const factory ListenLocationEvent({final int retry}) = _$ListenLocationEvent; + + int get retry; + @JsonKey(ignore: true) + _$$ListenLocationEventCopyWith<_$ListenLocationEvent> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$RequestLocationServiceEventCopyWith<$Res> { + factory _$$RequestLocationServiceEventCopyWith( + _$RequestLocationServiceEvent value, + $Res Function(_$RequestLocationServiceEvent) then) = + __$$RequestLocationServiceEventCopyWithImpl<$Res>; + @useResult + $Res call({int retry}); +} + +/// @nodoc +class __$$RequestLocationServiceEventCopyWithImpl<$Res> + extends _$LocationEventCopyWithImpl<$Res, _$RequestLocationServiceEvent> + implements _$$RequestLocationServiceEventCopyWith<$Res> { + __$$RequestLocationServiceEventCopyWithImpl( + _$RequestLocationServiceEvent _value, + $Res Function(_$RequestLocationServiceEvent) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? retry = null, + }) { + return _then(_$RequestLocationServiceEvent( + retry: null == retry + ? _value.retry + : retry // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc + +class _$RequestLocationServiceEvent implements RequestLocationServiceEvent { + const _$RequestLocationServiceEvent({this.retry = 5}); + + @override + @JsonKey() + final int retry; + + @override + String toString() { + return 'LocationEvent.requestService(retry: $retry)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$RequestLocationServiceEvent && + (identical(other.retry, retry) || other.retry == retry)); + } + + @override + int get hashCode => Object.hash(runtimeType, retry); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$RequestLocationServiceEventCopyWith<_$RequestLocationServiceEvent> + get copyWith => __$$RequestLocationServiceEventCopyWithImpl< + _$RequestLocationServiceEvent>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(int retry) load, + required TResult Function(int retry) listen, + required TResult Function(int retry) requestService, + required TResult Function(int retry) requestPermission, + required TResult Function(LocationData locationData) setLatLng, + }) { + return requestService(retry); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(int retry)? load, + TResult? Function(int retry)? listen, + TResult? Function(int retry)? requestService, + TResult? Function(int retry)? requestPermission, + TResult? Function(LocationData locationData)? setLatLng, + }) { + return requestService?.call(retry); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(int retry)? load, + TResult Function(int retry)? listen, + TResult Function(int retry)? requestService, + TResult Function(int retry)? requestPermission, + TResult Function(LocationData locationData)? setLatLng, + required TResult orElse(), + }) { + if (requestService != null) { + return requestService(retry); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(LoadLocationEvent value) load, + required TResult Function(ListenLocationEvent value) listen, + required TResult Function(RequestLocationServiceEvent value) requestService, + required TResult Function(RequestLocationPermissionEvent value) + requestPermission, + required TResult Function(LocationSetLatLngEvent value) setLatLng, + }) { + return requestService(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(LoadLocationEvent value)? load, + TResult? Function(ListenLocationEvent value)? listen, + TResult? Function(RequestLocationServiceEvent value)? requestService, + TResult? Function(RequestLocationPermissionEvent value)? requestPermission, + TResult? Function(LocationSetLatLngEvent value)? setLatLng, + }) { + return requestService?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(LoadLocationEvent value)? load, + TResult Function(ListenLocationEvent value)? listen, + TResult Function(RequestLocationServiceEvent value)? requestService, + TResult Function(RequestLocationPermissionEvent value)? requestPermission, + TResult Function(LocationSetLatLngEvent value)? setLatLng, + required TResult orElse(), + }) { + if (requestService != null) { + return requestService(this); + } + return orElse(); + } +} + +abstract class RequestLocationServiceEvent implements LocationEvent { + const factory RequestLocationServiceEvent({final int retry}) = + _$RequestLocationServiceEvent; + + int get retry; + @JsonKey(ignore: true) + _$$RequestLocationServiceEventCopyWith<_$RequestLocationServiceEvent> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$RequestLocationPermissionEventCopyWith<$Res> { + factory _$$RequestLocationPermissionEventCopyWith( + _$RequestLocationPermissionEvent value, + $Res Function(_$RequestLocationPermissionEvent) then) = + __$$RequestLocationPermissionEventCopyWithImpl<$Res>; + @useResult + $Res call({int retry}); +} + +/// @nodoc +class __$$RequestLocationPermissionEventCopyWithImpl<$Res> + extends _$LocationEventCopyWithImpl<$Res, _$RequestLocationPermissionEvent> + implements _$$RequestLocationPermissionEventCopyWith<$Res> { + __$$RequestLocationPermissionEventCopyWithImpl( + _$RequestLocationPermissionEvent _value, + $Res Function(_$RequestLocationPermissionEvent) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? retry = null, + }) { + return _then(_$RequestLocationPermissionEvent( + retry: null == retry + ? _value.retry + : retry // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc + +class _$RequestLocationPermissionEvent + implements RequestLocationPermissionEvent { + const _$RequestLocationPermissionEvent({this.retry = 1}); + + @override + @JsonKey() + final int retry; + + @override + String toString() { + return 'LocationEvent.requestPermission(retry: $retry)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$RequestLocationPermissionEvent && + (identical(other.retry, retry) || other.retry == retry)); + } + + @override + int get hashCode => Object.hash(runtimeType, retry); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$RequestLocationPermissionEventCopyWith<_$RequestLocationPermissionEvent> + get copyWith => __$$RequestLocationPermissionEventCopyWithImpl< + _$RequestLocationPermissionEvent>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(int retry) load, + required TResult Function(int retry) listen, + required TResult Function(int retry) requestService, + required TResult Function(int retry) requestPermission, + required TResult Function(LocationData locationData) setLatLng, + }) { + return requestPermission(retry); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(int retry)? load, + TResult? Function(int retry)? listen, + TResult? Function(int retry)? requestService, + TResult? Function(int retry)? requestPermission, + TResult? Function(LocationData locationData)? setLatLng, + }) { + return requestPermission?.call(retry); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(int retry)? load, + TResult Function(int retry)? listen, + TResult Function(int retry)? requestService, + TResult Function(int retry)? requestPermission, + TResult Function(LocationData locationData)? setLatLng, + required TResult orElse(), + }) { + if (requestPermission != null) { + return requestPermission(retry); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(LoadLocationEvent value) load, + required TResult Function(ListenLocationEvent value) listen, + required TResult Function(RequestLocationServiceEvent value) requestService, + required TResult Function(RequestLocationPermissionEvent value) + requestPermission, + required TResult Function(LocationSetLatLngEvent value) setLatLng, + }) { + return requestPermission(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(LoadLocationEvent value)? load, + TResult? Function(ListenLocationEvent value)? listen, + TResult? Function(RequestLocationServiceEvent value)? requestService, + TResult? Function(RequestLocationPermissionEvent value)? requestPermission, + TResult? Function(LocationSetLatLngEvent value)? setLatLng, + }) { + return requestPermission?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(LoadLocationEvent value)? load, + TResult Function(ListenLocationEvent value)? listen, + TResult Function(RequestLocationServiceEvent value)? requestService, + TResult Function(RequestLocationPermissionEvent value)? requestPermission, + TResult Function(LocationSetLatLngEvent value)? setLatLng, + required TResult orElse(), + }) { + if (requestPermission != null) { + return requestPermission(this); + } + return orElse(); + } +} + +abstract class RequestLocationPermissionEvent implements LocationEvent { + const factory RequestLocationPermissionEvent({final int retry}) = + _$RequestLocationPermissionEvent; + + int get retry; + @JsonKey(ignore: true) + _$$RequestLocationPermissionEventCopyWith<_$RequestLocationPermissionEvent> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$LocationSetLatLngEventCopyWith<$Res> { + factory _$$LocationSetLatLngEventCopyWith(_$LocationSetLatLngEvent value, + $Res Function(_$LocationSetLatLngEvent) then) = + __$$LocationSetLatLngEventCopyWithImpl<$Res>; + @useResult + $Res call({LocationData locationData}); +} + +/// @nodoc +class __$$LocationSetLatLngEventCopyWithImpl<$Res> + extends _$LocationEventCopyWithImpl<$Res, _$LocationSetLatLngEvent> + implements _$$LocationSetLatLngEventCopyWith<$Res> { + __$$LocationSetLatLngEventCopyWithImpl(_$LocationSetLatLngEvent _value, + $Res Function(_$LocationSetLatLngEvent) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? locationData = null, + }) { + return _then(_$LocationSetLatLngEvent( + locationData: null == locationData + ? _value.locationData + : locationData // ignore: cast_nullable_to_non_nullable + as LocationData, + )); + } +} + +/// @nodoc + +class _$LocationSetLatLngEvent implements LocationSetLatLngEvent { + const _$LocationSetLatLngEvent({required this.locationData}); + + @override + final LocationData locationData; + + @override + String toString() { + return 'LocationEvent.setLatLng(locationData: $locationData)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$LocationSetLatLngEvent && + (identical(other.locationData, locationData) || + other.locationData == locationData)); + } + + @override + int get hashCode => Object.hash(runtimeType, locationData); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$LocationSetLatLngEventCopyWith<_$LocationSetLatLngEvent> get copyWith => + __$$LocationSetLatLngEventCopyWithImpl<_$LocationSetLatLngEvent>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(int retry) load, + required TResult Function(int retry) listen, + required TResult Function(int retry) requestService, + required TResult Function(int retry) requestPermission, + required TResult Function(LocationData locationData) setLatLng, + }) { + return setLatLng(locationData); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(int retry)? load, + TResult? Function(int retry)? listen, + TResult? Function(int retry)? requestService, + TResult? Function(int retry)? requestPermission, + TResult? Function(LocationData locationData)? setLatLng, + }) { + return setLatLng?.call(locationData); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(int retry)? load, + TResult Function(int retry)? listen, + TResult Function(int retry)? requestService, + TResult Function(int retry)? requestPermission, + TResult Function(LocationData locationData)? setLatLng, + required TResult orElse(), + }) { + if (setLatLng != null) { + return setLatLng(locationData); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(LoadLocationEvent value) load, + required TResult Function(ListenLocationEvent value) listen, + required TResult Function(RequestLocationServiceEvent value) requestService, + required TResult Function(RequestLocationPermissionEvent value) + requestPermission, + required TResult Function(LocationSetLatLngEvent value) setLatLng, + }) { + return setLatLng(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(LoadLocationEvent value)? load, + TResult? Function(ListenLocationEvent value)? listen, + TResult? Function(RequestLocationServiceEvent value)? requestService, + TResult? Function(RequestLocationPermissionEvent value)? requestPermission, + TResult? Function(LocationSetLatLngEvent value)? setLatLng, + }) { + return setLatLng?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(LoadLocationEvent value)? load, + TResult Function(ListenLocationEvent value)? listen, + TResult Function(RequestLocationServiceEvent value)? requestService, + TResult Function(RequestLocationPermissionEvent value)? requestPermission, + TResult Function(LocationSetLatLngEvent value)? setLatLng, + required TResult orElse(), + }) { + if (setLatLng != null) { + return setLatLng(this); + } + return orElse(); + } +} + +abstract class LocationSetLatLngEvent implements LocationEvent { + const factory LocationSetLatLngEvent( + {required final LocationData locationData}) = _$LocationSetLatLngEvent; + + LocationData get locationData; + @JsonKey(ignore: true) + _$$LocationSetLatLngEventCopyWith<_$LocationSetLatLngEvent> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$LocationState { + double? get latitude => throw _privateConstructorUsedError; + double? get longitude => throw _privateConstructorUsedError; + double? get accuracy => throw _privateConstructorUsedError; + dynamic get hasPermissions => throw _privateConstructorUsedError; + bool get serviceEnabled => throw _privateConstructorUsedError; + bool get loading => throw _privateConstructorUsedError; + + @JsonKey(ignore: true) + $LocationStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LocationStateCopyWith<$Res> { + factory $LocationStateCopyWith( + LocationState value, $Res Function(LocationState) then) = + _$LocationStateCopyWithImpl<$Res, LocationState>; + @useResult + $Res call( + {double? latitude, + double? longitude, + double? accuracy, + dynamic hasPermissions, + bool serviceEnabled, + bool loading}); +} + +/// @nodoc +class _$LocationStateCopyWithImpl<$Res, $Val extends LocationState> + implements $LocationStateCopyWith<$Res> { + _$LocationStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? latitude = freezed, + Object? longitude = freezed, + Object? accuracy = freezed, + Object? hasPermissions = freezed, + Object? serviceEnabled = null, + Object? loading = null, + }) { + return _then(_value.copyWith( + latitude: freezed == latitude + ? _value.latitude + : latitude // ignore: cast_nullable_to_non_nullable + as double?, + longitude: freezed == longitude + ? _value.longitude + : longitude // ignore: cast_nullable_to_non_nullable + as double?, + accuracy: freezed == accuracy + ? _value.accuracy + : accuracy // ignore: cast_nullable_to_non_nullable + as double?, + hasPermissions: freezed == hasPermissions + ? _value.hasPermissions + : hasPermissions // ignore: cast_nullable_to_non_nullable + as dynamic, + serviceEnabled: null == serviceEnabled + ? _value.serviceEnabled + : serviceEnabled // ignore: cast_nullable_to_non_nullable + as bool, + loading: null == loading + ? _value.loading + : loading // ignore: cast_nullable_to_non_nullable + as bool, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_LocationStateCopyWith<$Res> + implements $LocationStateCopyWith<$Res> { + factory _$$_LocationStateCopyWith( + _$_LocationState value, $Res Function(_$_LocationState) then) = + __$$_LocationStateCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {double? latitude, + double? longitude, + double? accuracy, + dynamic hasPermissions, + bool serviceEnabled, + bool loading}); +} + +/// @nodoc +class __$$_LocationStateCopyWithImpl<$Res> + extends _$LocationStateCopyWithImpl<$Res, _$_LocationState> + implements _$$_LocationStateCopyWith<$Res> { + __$$_LocationStateCopyWithImpl( + _$_LocationState _value, $Res Function(_$_LocationState) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? latitude = freezed, + Object? longitude = freezed, + Object? accuracy = freezed, + Object? hasPermissions = freezed, + Object? serviceEnabled = null, + Object? loading = null, + }) { + return _then(_$_LocationState( + latitude: freezed == latitude + ? _value.latitude + : latitude // ignore: cast_nullable_to_non_nullable + as double?, + longitude: freezed == longitude + ? _value.longitude + : longitude // ignore: cast_nullable_to_non_nullable + as double?, + accuracy: freezed == accuracy + ? _value.accuracy + : accuracy // ignore: cast_nullable_to_non_nullable + as double?, + hasPermissions: + freezed == hasPermissions ? _value.hasPermissions! : hasPermissions, + serviceEnabled: null == serviceEnabled + ? _value.serviceEnabled + : serviceEnabled // ignore: cast_nullable_to_non_nullable + as bool, + loading: null == loading + ? _value.loading + : loading // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc + +class _$_LocationState extends _LocationState { + const _$_LocationState( + {this.latitude, + this.longitude, + this.accuracy, + this.hasPermissions = false, + this.serviceEnabled = false, + this.loading = false}) + : super._(); + + @override + final double? latitude; + @override + final double? longitude; + @override + final double? accuracy; + @override + @JsonKey() + final dynamic hasPermissions; + @override + @JsonKey() + final bool serviceEnabled; + @override + @JsonKey() + final bool loading; + + @override + String toString() { + return 'LocationState(latitude: $latitude, longitude: $longitude, accuracy: $accuracy, hasPermissions: $hasPermissions, serviceEnabled: $serviceEnabled, loading: $loading)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_LocationState && + (identical(other.latitude, latitude) || + other.latitude == latitude) && + (identical(other.longitude, longitude) || + other.longitude == longitude) && + (identical(other.accuracy, accuracy) || + other.accuracy == accuracy) && + const DeepCollectionEquality() + .equals(other.hasPermissions, hasPermissions) && + (identical(other.serviceEnabled, serviceEnabled) || + other.serviceEnabled == serviceEnabled) && + (identical(other.loading, loading) || other.loading == loading)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + latitude, + longitude, + accuracy, + const DeepCollectionEquality().hash(hasPermissions), + serviceEnabled, + loading); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_LocationStateCopyWith<_$_LocationState> get copyWith => + __$$_LocationStateCopyWithImpl<_$_LocationState>(this, _$identity); +} + +abstract class _LocationState extends LocationState { + const factory _LocationState( + {final double? latitude, + final double? longitude, + final double? accuracy, + final dynamic hasPermissions, + final bool serviceEnabled, + final bool loading}) = _$_LocationState; + const _LocationState._() : super._(); + + @override + double? get latitude; + @override + double? get longitude; + @override + double? get accuracy; + @override + dynamic get hasPermissions; + @override + bool get serviceEnabled; + @override + bool get loading; + @override + @JsonKey(ignore: true) + _$$_LocationStateCopyWith<_$_LocationState> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/vehicle-tracker/packages/digit_components/lib/digit_components.dart b/vehicle-tracker/packages/digit_components/lib/digit_components.dart new file mode 100644 index 00000000..57976831 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/digit_components.dart @@ -0,0 +1,15 @@ +library digit_components; + +export 'blocs/location/location.dart'; +export 'theme/theme.dart'; +export 'utils/app_logger.dart'; +export 'widgets/widgets.dart'; + +class DigitUi { + static const DigitUi _instance = DigitUi._internal(); + static DigitUi get instance => _instance; + + const DigitUi._internal(); + + Future initThemeComponents() async {} +} diff --git a/vehicle-tracker/packages/digit_components/lib/models/digit_row_card/digit_row_card_model.dart b/vehicle-tracker/packages/digit_components/lib/models/digit_row_card/digit_row_card_model.dart new file mode 100644 index 00000000..0fb63b1d --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/models/digit_row_card/digit_row_card_model.dart @@ -0,0 +1,17 @@ +// ignore_for_file: invalid_annotation_target +import 'package:freezed_annotation/freezed_annotation.dart'; +part 'digit_row_card_model.g.dart'; +part 'digit_row_card_model.freezed.dart'; + +@freezed +class DigitRowCardModel with _$DigitRowCardModel { + @JsonSerializable(explicitToJson: true) + const factory DigitRowCardModel({ + required String label, + required String value, + @Default(false) bool isSelected, + }) = _DigitRowCardModel; + + factory DigitRowCardModel.fromJson(Map json) => + _$DigitRowCardModelFromJson(json); +} diff --git a/vehicle-tracker/packages/digit_components/lib/models/digit_row_card/digit_row_card_model.freezed.dart b/vehicle-tracker/packages/digit_components/lib/models/digit_row_card/digit_row_card_model.freezed.dart new file mode 100644 index 00000000..c31f3df0 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/models/digit_row_card/digit_row_card_model.freezed.dart @@ -0,0 +1,191 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'digit_row_card_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +DigitRowCardModel _$DigitRowCardModelFromJson(Map json) { + return _DigitRowCardModel.fromJson(json); +} + +/// @nodoc +mixin _$DigitRowCardModel { + String get label => throw _privateConstructorUsedError; + String get value => throw _privateConstructorUsedError; + bool get isSelected => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $DigitRowCardModelCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DigitRowCardModelCopyWith<$Res> { + factory $DigitRowCardModelCopyWith( + DigitRowCardModel value, $Res Function(DigitRowCardModel) then) = + _$DigitRowCardModelCopyWithImpl<$Res, DigitRowCardModel>; + @useResult + $Res call({String label, String value, bool isSelected}); +} + +/// @nodoc +class _$DigitRowCardModelCopyWithImpl<$Res, $Val extends DigitRowCardModel> + implements $DigitRowCardModelCopyWith<$Res> { + _$DigitRowCardModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? label = null, + Object? value = null, + Object? isSelected = null, + }) { + return _then(_value.copyWith( + label: null == label + ? _value.label + : label // ignore: cast_nullable_to_non_nullable + as String, + value: null == value + ? _value.value + : value // ignore: cast_nullable_to_non_nullable + as String, + isSelected: null == isSelected + ? _value.isSelected + : isSelected // ignore: cast_nullable_to_non_nullable + as bool, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_DigitRowCardModelCopyWith<$Res> + implements $DigitRowCardModelCopyWith<$Res> { + factory _$$_DigitRowCardModelCopyWith(_$_DigitRowCardModel value, + $Res Function(_$_DigitRowCardModel) then) = + __$$_DigitRowCardModelCopyWithImpl<$Res>; + @override + @useResult + $Res call({String label, String value, bool isSelected}); +} + +/// @nodoc +class __$$_DigitRowCardModelCopyWithImpl<$Res> + extends _$DigitRowCardModelCopyWithImpl<$Res, _$_DigitRowCardModel> + implements _$$_DigitRowCardModelCopyWith<$Res> { + __$$_DigitRowCardModelCopyWithImpl( + _$_DigitRowCardModel _value, $Res Function(_$_DigitRowCardModel) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? label = null, + Object? value = null, + Object? isSelected = null, + }) { + return _then(_$_DigitRowCardModel( + label: null == label + ? _value.label + : label // ignore: cast_nullable_to_non_nullable + as String, + value: null == value + ? _value.value + : value // ignore: cast_nullable_to_non_nullable + as String, + isSelected: null == isSelected + ? _value.isSelected + : isSelected // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc + +@JsonSerializable(explicitToJson: true) +class _$_DigitRowCardModel implements _DigitRowCardModel { + const _$_DigitRowCardModel( + {required this.label, required this.value, this.isSelected = false}); + + factory _$_DigitRowCardModel.fromJson(Map json) => + _$$_DigitRowCardModelFromJson(json); + + @override + final String label; + @override + final String value; + @override + @JsonKey() + final bool isSelected; + + @override + String toString() { + return 'DigitRowCardModel(label: $label, value: $value, isSelected: $isSelected)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_DigitRowCardModel && + (identical(other.label, label) || other.label == label) && + (identical(other.value, value) || other.value == value) && + (identical(other.isSelected, isSelected) || + other.isSelected == isSelected)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, label, value, isSelected); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_DigitRowCardModelCopyWith<_$_DigitRowCardModel> get copyWith => + __$$_DigitRowCardModelCopyWithImpl<_$_DigitRowCardModel>( + this, _$identity); + + @override + Map toJson() { + return _$$_DigitRowCardModelToJson( + this, + ); + } +} + +abstract class _DigitRowCardModel implements DigitRowCardModel { + const factory _DigitRowCardModel( + {required final String label, + required final String value, + final bool isSelected}) = _$_DigitRowCardModel; + + factory _DigitRowCardModel.fromJson(Map json) = + _$_DigitRowCardModel.fromJson; + + @override + String get label; + @override + String get value; + @override + bool get isSelected; + @override + @JsonKey(ignore: true) + _$$_DigitRowCardModelCopyWith<_$_DigitRowCardModel> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/vehicle-tracker/packages/digit_components/lib/models/digit_row_card/digit_row_card_model.g.dart b/vehicle-tracker/packages/digit_components/lib/models/digit_row_card/digit_row_card_model.g.dart new file mode 100644 index 00000000..a23a338a --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/models/digit_row_card/digit_row_card_model.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'digit_row_card_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_DigitRowCardModel _$$_DigitRowCardModelFromJson(Map json) => + _$_DigitRowCardModel( + label: json['label'] as String, + value: json['value'] as String, + isSelected: json['isSelected'] as bool? ?? false, + ); + +Map _$$_DigitRowCardModelToJson( + _$_DigitRowCardModel instance) => + { + 'label': instance.label, + 'value': instance.value, + 'isSelected': instance.isSelected, + }; diff --git a/vehicle-tracker/packages/digit_components/lib/models/digit_table_model.dart b/vehicle-tracker/packages/digit_components/lib/models/digit_table_model.dart new file mode 100644 index 00000000..d0aff146 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/models/digit_table_model.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; + +class TableHeader { + final String label; + final ValueChanged? callBack; + bool? isSortingRequired = false; + bool? isAscendingOrder; + String? cellKey; + TableHeader( + this.label, { + this.callBack, + this.isSortingRequired, + this.isAscendingOrder, + this.cellKey, + }); +} + +class TableDataRow { + final List tableRow; + TableDataRow(this.tableRow); +} + +class TableData { + final String label; + final TextStyle? style; + final String? cellKey; + ValueChanged? callBack; + TableData(this.label, {this.style, this.callBack, this.cellKey}); +} diff --git a/vehicle-tracker/packages/digit_components/lib/theme/colors.dart b/vehicle-tracker/packages/digit_components/lib/theme/colors.dart new file mode 100644 index 00000000..b5159031 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/theme/colors.dart @@ -0,0 +1,28 @@ +import 'dart:ui'; + +class DigitColors { + const DigitColors(); + + Color get burningOrange => const Color(0xFFF47738); + Color get regalBlue => const Color(0xFF0B4B66); + Color get woodsmokeBlack => const Color(0xFF0B0C0C); + Color get black => const Color(0xFF000000); + Color get davyGray => const Color(0xFF505A5F); + Color get cloudGray => const Color(0xFFB1B4B6); + Color get seaShellGray => const Color(0xFFEEEEEE); + Color get white => const Color(0xFFFFFFFF); + Color get alabasterWhite => const Color(0xFFFAFAFA); + Color get quillGray => const Color(0xFFD6D5D4); + Color get paleRose => const Color(0xFFEFC7C1); + Color get paleLeafGreen => const Color(0xFFBAD6C9); + Color get tropicalBlue => const Color(0xFFC7E0F1); + Color get bonePink => const Color(0xFFE6D7D0); + Color get lavaRed => const Color(0xFFD4351C); + Color get darkSpringGreen => const Color(0xFF00703C); + Color get curiousBlue => const Color(0xFF3498DB); + Color get waterBlue => const Color(0xFF048BD0); + Color get sunGlowYellow => const Color(0xFFFBC02D); + Color get darkOrchid => const Color(0xFF8E29BF); + Color get mangoOrange => const Color(0xFFEA8A3B); + Color get pacificBlue => const Color(0xFF0BABDE); +} diff --git a/vehicle-tracker/packages/digit_components/lib/theme/digit_theme.dart b/vehicle-tracker/packages/digit_components/lib/theme/digit_theme.dart new file mode 100644 index 00000000..a9dda5bb --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/theme/digit_theme.dart @@ -0,0 +1,202 @@ +library digit_theme; + +import 'package:digit_components/theme/colors.dart'; +import 'package:digit_components/theme/typography.dart'; +import 'package:flutter/material.dart'; + +const kPadding = 8.0; + +class DigitTheme { + static const DigitTheme _instance = DigitTheme._internal(); + + static DigitTheme get instance => _instance; + + DigitColors get colors => const DigitColors(); + + DigitMobileTypography get mobileTypography => DigitMobileTypography( + normalBase: const TextStyle( + fontFamily: 'Roboto', + ), + displayBase: const TextStyle( + fontFamily: 'Roboto', + ), + light: colors.davyGray, + normal: colors.woodsmokeBlack, + ); + + const DigitTheme._internal(); + + ThemeData get mobileTheme { + const Border(top: BorderSide()); + + return ThemeData( + colorScheme: colorScheme, + scaffoldBackgroundColor: colorScheme.background, + textTheme: mobileTypography.textTheme, + appBarTheme: const AppBarTheme(elevation: 0), + elevatedButtonTheme: elevatedButtonTheme, + outlinedButtonTheme: outlinedButtonTheme, + textButtonTheme: textButtonTheme, + cardTheme: cardTheme, + inputDecorationTheme: inputDecorationTheme, + dialogTheme: dialogTheme, + ); + } + + ColorScheme get colorScheme => ColorScheme( + brightness: Brightness.light, + primary: colors.regalBlue, + onPrimary: colors.white, + secondary: colors.burningOrange, + onSecondary: colors.white, + error: colors.lavaRed, + onError: colors.white, + background: colors.seaShellGray, + onBackground: colors.woodsmokeBlack, + surface: colors.alabasterWhite, + onSurface: colors.woodsmokeBlack, + onSurfaceVariant: colors.darkSpringGreen, + tertiaryContainer: colors.tropicalBlue, + inversePrimary: colors.paleLeafGreen, + surfaceTint: colors.waterBlue, + outline: colors.quillGray, + shadow: colors.davyGray, + tertiary: colors.paleRose, + onTertiaryContainer: colors.curiousBlue, + ); + + EdgeInsets get buttonPadding => const EdgeInsets.symmetric( + vertical: kPadding, + horizontal: kPadding * 2, + ); + + EdgeInsets get containerMargin => const EdgeInsets.all(kPadding); + + EdgeInsets get verticalMargin => const EdgeInsets.symmetric( + vertical: kPadding, + ); + + Duration get toastDuration => const Duration(seconds: 2); + + OutlinedBorder get buttonBorder => const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.zero), + ); + + ElevatedButtonThemeData get elevatedButtonTheme => ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + shape: buttonBorder, + padding: buttonPadding, + backgroundColor: colorScheme.secondary, + foregroundColor: colorScheme.onSecondary, + disabledBackgroundColor: colorScheme.secondary.withOpacity( + 0.5, + ), + disabledForegroundColor: colorScheme.onSecondary, + elevation: 0, + ), + ); + + OutlinedButtonThemeData get outlinedButtonTheme => OutlinedButtonThemeData( + style: OutlinedButton.styleFrom( + foregroundColor: colorScheme.secondary, + // side: BorderSide(color: colorScheme.secondary), + padding: buttonPadding, + ), + ); + + TextButtonThemeData get textButtonTheme => TextButtonThemeData( + style: TextButton.styleFrom( + shape: buttonBorder, + padding: buttonPadding, + textStyle: const TextStyle(fontSize: 16), + foregroundColor: colorScheme.secondary, + ), + ); + + CardTheme get cardTheme => const CardTheme( + margin: EdgeInsets.fromLTRB(kPadding, kPadding * 2, kPadding, 0), + elevation: 1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(4), + ), + ), + ); + + InputDecorationTheme get inputDecorationTheme => InputDecorationTheme( + enabledBorder: OutlineInputBorder( + borderRadius: const BorderRadius.all( + Radius.circular( + 0, + ), + ), + borderSide: BorderSide( + color: colors.davyGray, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: const BorderRadius.all( + Radius.circular( + 0, + ), + ), + borderSide: BorderSide( + color: colors.burningOrange, + width: 2, + ), + ), + disabledBorder: OutlineInputBorder( + borderRadius: const BorderRadius.all( + Radius.circular( + 0, + ), + ), + borderSide: BorderSide(color: colors.cloudGray, width: 2), + ), + contentPadding: const EdgeInsets.all(12), + isDense: true, + isCollapsed: true, + floatingLabelBehavior: FloatingLabelBehavior.never, + errorBorder: OutlineInputBorder( + borderRadius: const BorderRadius.all( + Radius.circular( + 0, + ), + ), + borderSide: BorderSide( + color: colors.lavaRed, + ), + ), + focusedErrorBorder: OutlineInputBorder( + borderRadius: const BorderRadius.all( + Radius.circular( + 0, + ), + ), + borderSide: BorderSide(color: colors.lavaRed, width: 2), + ), + ); + + DialogTheme get dialogTheme => DialogTheme( + titleTextStyle: mobileTypography.headingL, + contentTextStyle: mobileTypography.bodyL, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular( + 4, + ), + ), + ), + actionsPadding: const EdgeInsets.all(kPadding), + ); + + BorderSide get tableCellBorder => BorderSide( + color: colorScheme.outline, + width: 0.5, + ); + + BorderSide get tableCellStrongBorder => BorderSide( + color: colorScheme.outline, + width: 2, + ); +} diff --git a/vehicle-tracker/packages/digit_components/lib/theme/theme.dart b/vehicle-tracker/packages/digit_components/lib/theme/theme.dart new file mode 100644 index 00000000..e69bdb61 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/theme/theme.dart @@ -0,0 +1,3 @@ +export './typography.dart'; +export './digit_theme.dart'; +export './colors.dart'; diff --git a/vehicle-tracker/packages/digit_components/lib/theme/typography.dart b/vehicle-tracker/packages/digit_components/lib/theme/typography.dart new file mode 100644 index 00000000..d87a7f51 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/theme/typography.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; + +abstract class DigitTypography { + final Color? _textColorNormal; + final Color? _textColorLight; + final TextStyle _normalBase; + final TextStyle _displayBase; + + const DigitTypography({ + required TextStyle normalBase, + required TextStyle displayBase, + Color? normal, + Color? light, + }) : _normalBase = normalBase, + _displayBase = displayBase, + _textColorLight = light, + _textColorNormal = normal; + + TextStyle get _normal => + _normalBase.copyWith(color: _textColorNormal, fontFamily: 'Roboto'); + TextStyle get _light => + _normalBase.copyWith(color: _textColorLight, fontFamily: 'Roboto'); + TextStyle get _big => + _displayBase.copyWith(color: _textColorNormal, fontFamily: 'Roboto'); + + /// Follows Digit Typography standards + /// + /// + TextTheme get textTheme; + + /// Heading styles + TextStyle get headingXl => textTheme.displayMedium!; + TextStyle get headingL => textTheme.headlineLarge!; + TextStyle get headingM => textTheme.headlineMedium!; + TextStyle get headingS => textTheme.headlineSmall!; + + /// Caption styles + TextStyle get captionXL => textTheme.labelLarge!; + TextStyle get captionL => textTheme.labelMedium!; + TextStyle get captionM => textTheme.labelSmall!; + + /// Body styles + TextStyle get bodyL => textTheme.bodyLarge!; + TextStyle get bodyM => textTheme.bodyMedium!; + TextStyle get bodyS => textTheme.bodySmall!; + + /// Miscellaneous styles + TextStyle get label => textTheme.bodyLarge!; + TextStyle get link => textTheme.bodyLarge!; +} + +class DigitMobileTypography extends DigitTypography { + const DigitMobileTypography({ + required TextStyle normalBase, + required TextStyle displayBase, + Color? normal, + Color? light, + }) : super( + normal: normal, + light: light, + displayBase: displayBase, + normalBase: normalBase, + ); + + @override + TextTheme get textTheme { + return TextTheme( + displayMedium: _big.copyWith( + fontSize: 32, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto Condensed', + ), + headlineLarge: _normal.copyWith( + fontSize: 24, + fontWeight: FontWeight.w700, + ), + headlineMedium: _normal.copyWith( + fontSize: 18, + fontWeight: FontWeight.w700, + ), + headlineSmall: _normal.copyWith( + fontSize: 16, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + ), + bodyLarge: _normal.copyWith( + fontSize: 16, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + ), + bodyMedium: _normal.copyWith( + fontSize: 14, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + ), + bodySmall: _normal.copyWith( + fontSize: 12, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + ), + labelLarge: _normal.copyWith( + fontSize: 19, + fontWeight: FontWeight.w500, + ), + labelMedium: _light.copyWith( + fontSize: 18, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + ), + labelSmall: _normal.copyWith( + fontSize: 16, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/utils/app_logger.dart b/vehicle-tracker/packages/digit_components/lib/utils/app_logger.dart new file mode 100644 index 00000000..80ab8e35 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/utils/app_logger.dart @@ -0,0 +1,59 @@ +import 'package:flutter/foundation.dart'; +import 'package:logging/logging.dart'; + +class AppLogger { + static AppLogger get instance => _instance; + static const _instance = AppLogger._(); + + const AppLogger._(); + + void debug(dynamic input, {String? title}) => + _printMessage(input, title: title, level: Level.CONFIG); + + void info(dynamic input, {String? title}) => + _printMessage(input, title: title, level: Level.INFO); + + void error({ + required String title, + String? message, + StackTrace? stackTrace, + }) => + _printError( + message: message, + title: title, + stackTrace: stackTrace, + ); + + void _printError({ + required String title, + String? message, + StackTrace? stackTrace, + }) { + if (stackTrace != null) { + debugPrintStack( + label: title, + stackTrace: stackTrace, + ); + } else { + _printMessage( + message, + title: title, + level: Level.SEVERE, + ); + } + } + + void _printMessage( + dynamic input, { + String? title, + required Level level, + }) => + debugPrint( + [ + '[${level.name.padRight(4, ' ').substring(0, 4)}] ', + '${(title ?? runtimeType.toString())}\n', + '${input.toString()}\n', + ].join(''), + wrapWidth: 120, + ); +} diff --git a/vehicle-tracker/packages/digit_components/lib/utils/constants.dart b/vehicle-tracker/packages/digit_components/lib/utils/constants.dart new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/utils/constants.dart @@ -0,0 +1 @@ + diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/anchor_overlay.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/anchor_overlay.dart new file mode 100644 index 00000000..5051ade1 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/anchor_overlay.dart @@ -0,0 +1,115 @@ +import 'package:flutter/material.dart'; +import './triangularpointer.dart'; +import 'package:digit_components/digit_components.dart'; +import 'package:overlay_builder/overlay_builder.dart'; + +class AnchoredOverlay extends StatelessWidget { + final bool showOverlay; + final Widget child; + final String description; + final GlobalKey paramKey; + final VoidCallback onTap; + final Offset position; + final double childHeight; + + const AnchoredOverlay( + {super.key, + required this.showOverlay, + required this.child, + required this.description, + required this.paramKey, + required this.onTap, + required this.position, + required this.childHeight}); + + @override + Widget build(BuildContext context) { + return OverlayBuilder( + type: OverlayType.fullscreen, + opaque: false, + key: paramKey, + overlayChild: GestureDetector( + onTap: onTap, + child: Stack(children: [ + Positioned( + top: position.dy + childHeight - 20, + left: 100, + child: const TriangularShape(), + ), + Positioned( + top: position.dy + childHeight, + child: Card( + elevation: 10, + margin: DigitTheme.instance.containerMargin, + child: Padding( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + const SizedBox( + height: 8, + ), + Text( + description, + style: Theme.of(context).textTheme.bodyMedium, + ), + const SizedBox( + height: 8, + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + height: 30, //height of button + child: TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text( + 'Skip', + style: TextStyle(fontSize: 10), + ), + )), + SizedBox( + height: 30, //height of button + child: ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 3, //elevation of button + shape: RoundedRectangleBorder( + //to set border radius to button + borderRadius: + BorderRadius.circular(10)), + //content padding inside button + ), + onPressed: onTap, + child: const Text( + 'Next', + style: TextStyle(fontSize: 10), + ), + )) + ]) + ], + )))) + ])), + child: showOverlay + ? Scaffold( + body: GestureDetector( + onTap: onTap, + child: Card( + margin: EdgeInsets.zero, + elevation: 10, + child: Material( + elevation: 6, + type: MaterialType.transparency, + child: child, + ), + ), + )) + : GestureDetector( + onTap: onTap, + child: SizedBox( + height: childHeight, + child: child, + )), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_action_dialog.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_action_dialog.dart new file mode 100644 index 00000000..70aa738d --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_action_dialog.dart @@ -0,0 +1,21 @@ +import 'package:digit_components/theme/digit_theme.dart'; +import 'package:flutter/material.dart'; + +class DigitActionDialog extends StatelessWidget { + final Widget widget; + + const DigitActionDialog({super.key, required this.widget}); + + static Future show(BuildContext context, + {required final Widget widget}) => + showDialog( + context: context, + barrierColor: DigitTheme.instance.colors.black.withOpacity(0.7), + builder: (context) => DigitActionDialog(widget: widget)); + + @override + Widget build(BuildContext context) => AlertDialog( + insetPadding: EdgeInsets.zero, + content: widget, + ); +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_checkbox.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_checkbox.dart new file mode 100644 index 00000000..1c7e1202 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_checkbox.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; + +class DigitCheckbox extends StatelessWidget { + final bool value; + final String label; + final ValueChanged? onChanged; + + const DigitCheckbox({ + super.key, + required this.label, + this.onChanged, + this.value = false, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Padding( + padding: const EdgeInsets.only(top: 4), + child: InkWell( + onTap: () => onChanged?.call(!value), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox( + height: 24, + width: 24, + child: Checkbox( + value: value, + side: MaterialStateBorderSide.resolveWith((states) { + if (states.contains(MaterialState.selected)) { + return BorderSide( + width: 2.0, + color: theme.colorScheme.secondary, + ); + } + return const BorderSide(width: 1.0); + }), + fillColor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.selected)) { + return theme.colorScheme.surface; + } + return theme.colorScheme.secondary; + }), + checkColor: theme.colorScheme.secondary, + onChanged: onChanged, + ), + ), + const SizedBox(width: 16), + Text( + label, + style: Theme.of(context).textTheme.bodyLarge, + ), + ], + ), + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_date_form_picker.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_date_form_picker.dart new file mode 100644 index 00000000..cad2b8a1 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_date_form_picker.dart @@ -0,0 +1,85 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:reactive_forms/reactive_forms.dart'; + +class DigitDateFormPicker extends StatelessWidget { + final String label; + final bool isRequired; + final DateTime? firstDate; + final DateTime? lastDate; + final DateTime? initialDate; + + final ValueChanged? onChangeOfDate; + final String formControlName; + final bool? isEnabled; + final String? requiredMessage; + final String? Function(DateTime?)? validator; + final AutovalidateMode? autoValidation; + final EdgeInsets? margin; + final DateTime? start; + final DateTime? end; + final String? hint; + final IconData? icon; + final String? tooltipMessage; + + const DigitDateFormPicker({ + super.key, + required this.label, + this.isRequired = false, + this.firstDate, + this.lastDate, + this.initialDate, + this.onChangeOfDate, + required this.formControlName, + this.isEnabled = true, + this.requiredMessage, + this.validator, + this.autoValidation, + this.margin, + this.end, + this.start, + this.hint, + this.icon, + this.tooltipMessage, + }); + + @override + Widget build(BuildContext context) { + return LabeledField( + label: '$label ${isRequired ? '*' : ''}', + icon: icon, + tooltipMessage: tooltipMessage, + child: ReactiveDatePicker( + formControlName: formControlName, + firstDate: start ?? DateTime(1900), + lastDate: end ?? DateTime.now(), + builder: (context, picker, child) { + return ReactiveTextField( + style: TextStyle( + color: isEnabled == true + ? DigitTheme.instance.colorScheme.onBackground + : DigitTheme.instance.colorScheme.shadow, + ), + formControlName: formControlName, + readOnly: true, + valueAccessor: DateTimeValueAccessor( + dateTimeFormat: DateFormat('dd MMM yyyy'), + ), + decoration: InputDecoration( + contentPadding: const EdgeInsets.fromLTRB(16, 12, 0, 12), + suffixIcon: const Icon(Icons.date_range), + label: hint == null ? null : Text(hint!), + ), + enableInteractiveSelection: isEnabled!, + onTap: isEnabled == true + ? (control) { + picker.showPicker(); + } + : null, + ); + }, + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_divider.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_divider.dart new file mode 100644 index 00000000..4d9d2f5f --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_divider.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; + +class DigitDivider extends StatelessWidget { + const DigitDivider({super.key}); + + @override + Widget build(BuildContext context) { + return Divider( + key: const ValueKey('neo_divider'), + color: Theme.of(context).colorScheme.outline, + height: 1.0, + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_dropdown.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_dropdown.dart new file mode 100644 index 00000000..01aeaab6 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_dropdown.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; + +class DigitDropdown extends StatelessWidget { + final String label; + final T? value; + final List menuItems; + final bool isRequired; + final ValueChanged? onChanged; + final String Function(T value) valueMapper; + + const DigitDropdown({ + super.key, + required this.value, + required this.label, + required this.menuItems, + this.isRequired = false, + required this.valueMapper, + this.onChanged, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(top: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '$label${isRequired ? ' *' : ''}', + style: Theme.of(context).textTheme.bodyLarge, + ), + const SizedBox(height: 8), + DropdownButtonFormField( + value: value, + onChanged: onChanged, + decoration: const InputDecoration( + contentPadding: EdgeInsets.fromLTRB(16, 12, 0, 12), + ), + items: menuItems + .map( + (e) => DropdownMenuItem( + value: e, + child: Text(valueMapper(e)), + ), + ) + .toList(), + ), + ], + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_icon_button.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_icon_button.dart new file mode 100644 index 00000000..0bf643f6 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_icon_button.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; + +class DigitIconButton extends StatelessWidget { + final VoidCallback? onPressed; + final String? iconText; + final IconData? icon; + final Color? iconColor; + final Color? iconTextColor; + final TextDecoration? textDecoration; + + const DigitIconButton({ + super.key, + this.onPressed, + this.iconText, + this.icon, + this.iconColor, + this.iconTextColor, + this.textDecoration, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return TextButton( + style: TextButton.styleFrom( + foregroundColor: theme.colorScheme.onBackground, + padding: EdgeInsets.zero, + ), + onPressed: onPressed, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Icon( + icon, + color: iconColor ?? theme.colorScheme.secondary, + ), + ), + const SizedBox( + width: 4, + ), + if (iconText != null) + Flexible( + child: Text( + iconText!, + style: TextStyle( + color: iconTextColor ?? theme.colorScheme.secondary, + decoration: textDecoration ?? TextDecoration.none, + fontSize: 16), + )), + ], + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_integer_form_picker.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_integer_form_picker.dart new file mode 100644 index 00000000..ae6fad2d --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_integer_form_picker.dart @@ -0,0 +1,94 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; +import 'package:reactive_forms/reactive_forms.dart'; + +class DigitIntegerFormPicker extends StatelessWidget { + final int? minimum; + final int? maximum; + final bool incrementer; + final String? hint; + final String label; + final FormGroup form; + final String formControlName; + const DigitIntegerFormPicker({ + super.key, + this.minimum, + this.maximum, + required this.incrementer, + required this.formControlName, + this.hint, + required this.form, + required this.label, + }); + + @override + Widget build(BuildContext context) { + if (!incrementer) { + return LabeledField( + label: label, + child: ReactiveTextField( + formControlName: formControlName, + decoration: InputDecoration(labelText: hint), + keyboardType: TextInputType.number, + )); + } + + return LabeledField( + label: label, + child: IntrinsicHeight( + child: Row( + children: [ + _buildButton( + context, + border: Border( + left: _borderSide, + bottom: _borderSide, + top: _borderSide, + ), + icon: Icons.remove, + onPressed: () => minimum != null + ? form.control(formControlName).value > minimum || + form.control(formControlName).value == null + ? form.control(formControlName).value -= 1 + : 1 + : form.control(formControlName).value -= 1, + ), + Expanded( + child: ReactiveTextField( + readOnly: true, + textAlign: TextAlign.center, + formControlName: formControlName, + decoration: InputDecoration(labelText: hint), + keyboardType: TextInputType.number, + ), + ), + _buildButton(context, + border: Border( + right: _borderSide, + bottom: _borderSide, + top: _borderSide, + ), + icon: Icons.add, + onPressed: () => form.control(formControlName).value += 1), + ], + ), + )); + } + + Widget _buildButton( + BuildContext context, { + required Border border, + required IconData icon, + VoidCallback? onPressed, + }) => + AspectRatio( + aspectRatio: 1, + child: Material( + shape: border, + color: Theme.of(context).colorScheme.background, + child: InkWell(onTap: onPressed, child: Icon(icon)), + ), + ); + + BorderSide get _borderSide => const BorderSide(width: 1); +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_outline_icon_button.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_outline_icon_button.dart new file mode 100644 index 00000000..294bc2fb --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_outline_icon_button.dart @@ -0,0 +1,32 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; + +class DigitOutlineIconButton extends StatelessWidget { + final String label; + final IconData icon; + final VoidCallback? onPressed; + final Color? iconColor; + + const DigitOutlineIconButton({ + super.key, + this.iconColor, + required this.label, + required this.icon, + required this.onPressed, + }); + + @override + Widget build(BuildContext context) { + return OutlinedButton( + onPressed: onPressed, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible(child: Icon(icon)), + const SizedBox(width: kPadding), + Text(label), + ], + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_reactive_dropdown.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_reactive_dropdown.dart new file mode 100644 index 00000000..b309452f --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_reactive_dropdown.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; +import 'package:reactive_forms/reactive_forms.dart'; + +class DigitReactiveDropdown extends StatelessWidget { + final String label; + final T? initialValue; + final List menuItems; + final String formControlName; + final bool isRequired; + final ValueChanged? onChanged; + final String Function(T value) valueMapper; + final Map? validationMessages; + + const DigitReactiveDropdown({ + super.key, + required this.label, + required this.menuItems, + required this.formControlName, + this.isRequired = false, + required this.valueMapper, + this.initialValue, + this.onChanged, + this.validationMessages, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(top: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '$label${isRequired ? ' *' : ''}', + style: Theme.of(context).textTheme.bodyLarge, + ), + const SizedBox(height: 8), + ReactiveDropdownField( + onChanged: (control) { + final value = control.value; + if (value == null) return; + onChanged?.call(value); + }, + validationMessages: validationMessages, + formControlName: formControlName, + decoration: const InputDecoration( + contentPadding: EdgeInsets.fromLTRB(16, 12, 0, 12), + ), + items: menuItems + .map( + (e) => DropdownMenuItem( + value: e, + child: Text(valueMapper(e)), + ), + ) + .toList(), + ), + ], + ), + ); + } +} + +class MenuItemModel { + final String name; + final String code; + + const MenuItemModel({ + required this.name, + required this.code, + }); +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_table_item.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_table_item.dart new file mode 100644 index 00000000..d078efb3 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_table_item.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; + +class DigitTableItem extends StatelessWidget { + final double? width; + final double? height; + final String content; + final int index; + final Widget? child; + final bool? isColored; + + const DigitTableItem({ + super.key, + this.width, + this.height, + required this.content, + required this.index, + this.child, + this.isColored, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Container( + color: isColored != null + ? index % 2 == 0 + ? theme.scaffoldBackgroundColor + : theme.cardColor + : null, + width: width ?? 100, + height: height ?? 50, + padding: const EdgeInsets.fromLTRB(10, 0, 0, 0), + alignment: Alignment.centerLeft, + child: child ?? Text(content), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_table_item_title.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_table_item_title.dart new file mode 100644 index 00000000..bffb7259 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_table_item_title.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; + +class DigitTableItemTitle extends StatelessWidget { + final double? width; + final String label; + final double? height; + final EdgeInsets? padding; + + const DigitTableItemTitle({ + super.key, + this.width, + required this.label, + this.height, + this.padding, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Container( + width: width, + height: height, + padding: padding ?? const EdgeInsets.fromLTRB(5, 0, 0, 0), + alignment: Alignment.centerLeft, + child: Text( + label, + style: theme.textTheme.bodyMedium, + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_text_form_field.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_text_form_field.dart new file mode 100644 index 00000000..73114e26 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_text_form_field.dart @@ -0,0 +1,96 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; +import 'package:reactive_forms/reactive_forms.dart'; + +class DigitTextFormField extends StatelessWidget { + final bool readOnly; + final String formControlName; + final String? hint; + final Widget? suffix; + final bool isRequired; + final int minLines; + final int maxLines; + final int? maxLength; + final TextInputType keyboardType; + final FocusNode? focusNode; + final VoidCallback? onTap; + final bool obscureText; + final String label; + final int? minLength; + final Widget? suffixIcon; + final void Function(FormControl)? onChanged; + final TextCapitalization textCapitalization; + final ControlValueAccessor? valueAccessor; + final Map? validationMessages; + + const DigitTextFormField({ + super.key, + required this.label, + required this.formControlName, + this.hint, + this.suffix, + this.minLines = 1, + this.maxLines = 1, + this.valueAccessor, + this.maxLength, + this.onTap, + this.focusNode, + this.validationMessages, + this.suffixIcon, + this.keyboardType = TextInputType.text, + this.textCapitalization = TextCapitalization.sentences, + this.obscureText = false, + this.isRequired = false, + this.readOnly = false, + this.onChanged, + this.minLength, + }); + + @override + Widget build(BuildContext context) => LabeledField( + label: '$label ${isRequired ? '*' : ''}', + child: ReactiveTextField( + onChanged: onChanged, + readOnly: readOnly, + formControlName: formControlName, + maxLength: maxLength, + validationMessages: validationMessages, + autofocus: false, + textCapitalization: textCapitalization, + minLines: minLines, + maxLines: maxLines, + obscureText: obscureText, + focusNode: focusNode, + keyboardType: keyboardType, + valueAccessor: valueAccessor, + decoration: readOnly == true + ? InputDecoration( + enabledBorder: + DigitTheme.instance.inputDecorationTheme.disabledBorder, + fillColor: DigitTheme.instance.colors.cloudGray, + focusedBorder: + DigitTheme.instance.inputDecorationTheme.disabledBorder, + focusColor: DigitTheme.instance.colors.cloudGray, + suffixIcon: suffix == null + ? null + : InkWell( + onTap: onTap, + child: suffix, + ), + ) + : InputDecoration( + labelText: hint, + contentPadding: const EdgeInsets.fromLTRB(16, 12, 0, 12), + suffixIconConstraints: const BoxConstraints( + maxHeight: 40, + maxWidth: 40, + ), + suffixIcon: suffix == null + ? null + : InkWell( + onTap: onTap, + child: suffix, + ), + )), + ); +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_toast_helper.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_toast_helper.dart new file mode 100644 index 00000000..9d971271 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_toast_helper.dart @@ -0,0 +1,36 @@ +import 'package:digit_components/widgets/atoms/digit_toaster.dart'; +import 'package:flutter/material.dart'; + +class ToastHelper extends StatefulWidget { + final String message; + + const ToastHelper({ + super.key, + required this.message, + }); + + @override + State createState() { + return ToastHelperState(); + } +} + +class ToastHelperState extends State { + @override + void initState() { + super.initState(); + + WidgetsBinding.instance.addPostFrameCallback((_) { + final theme = Theme.of(context); + DigitToast.show( + context, + options: DigitToastOptions(widget.message, true, theme), + ); + }); + } + + @override + Widget build(BuildContext context) { + return Container(); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_toaster.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_toaster.dart new file mode 100644 index 00000000..2c6d8b69 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/digit_toaster.dart @@ -0,0 +1,57 @@ +import 'package:digit_components/theme/digit_theme.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +class DigitToast { + final DigitToastOptions options; + + static FToast ftoast = FToast(); + + @visibleForTesting + DigitToast({ + required this.options, + }); + + static show( + BuildContext context, { + required DigitToastOptions options, + }) { + ftoast.init(context); + + return ftoast.showToast( + child: Container( + color: options.isError + ? options.theme.colorScheme.error + : options.theme.colorScheme.surfaceVariant, + padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + options.isError ? Icons.info_outline_rounded : Icons.check, + color: Colors.white, + ), + const SizedBox( + width: 12.0, + ), + Expanded( + child: Text( + options.message, + style: const TextStyle(color: Colors.white), + )), + ], + ), + ), + gravity: ToastGravity.BOTTOM, + toastDuration: DigitTheme.instance.toastDuration, + ); + } +} + +class DigitToastOptions { + final String message; + final bool isError; + ThemeData theme; + + DigitToastOptions(this.message, this.isError, this.theme); +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/atoms/triangularpointer.dart b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/triangularpointer.dart new file mode 100644 index 00000000..b9b1b4db --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/atoms/triangularpointer.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; + +class TriangularShape extends StatelessWidget { + const TriangularShape({super.key}); + + @override + Widget build(BuildContext context) { + return Material( + elevation: 4, + shape: TriangularBorder(), + child: ClipPath( + clipper: TriangularClipper(), + child: Container( + margin: EdgeInsets.zero, + padding: EdgeInsets.zero, + height: 40, + width: 30, + color: Colors.white, + ), + ), + ); + } +} + +class TriangularClipper extends CustomClipper { + @override + Path getClip(Size size) { + var path = Path(); + path.moveTo(size.width / 2, 0); + path.lineTo(0, size.height); + path.lineTo(size.width, size.height); + path.close(); + + return path; + } + + @override + bool shouldReclip(CustomClipper oldClipper) => false; +} + +class TriangularBorder extends ShapeBorder { + @override + EdgeInsetsGeometry get dimensions => const EdgeInsets.only(); + + @override + Path getInnerPath(Rect rect, {TextDirection? textDirection}) => Path(); + + @override + Path getOuterPath(Rect rect, {TextDirection? textDirection}) { + var path = Path(); + path.moveTo(rect.width / 2, 0); + path.lineTo(0, rect.height); + path.lineTo(rect.width, rect.height); + path.close(); + + return path; + } + + @override + void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {} + @override + ShapeBorder scale(double t) => TriangularBorder(); +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_banner.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_banner.dart new file mode 100644 index 00000000..c5db11fc --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_banner.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; + +class DigitBanner extends StatelessWidget { + final Widget child; + final Color color; + final String imageUrl; + final double height; + + const DigitBanner({ + super.key, + required this.child, + required this.color, + required this.imageUrl, + required this.height, + }); + + @override + Widget build(BuildContext context) { + return Container( + height: height, + decoration: BoxDecoration( + color: color, + image: DecorationImage( + image: NetworkImage( + imageUrl, + ), + fit: BoxFit.cover, + opacity: .2, + ), + ), + child: child, + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_card.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_card.dart new file mode 100644 index 00000000..5400ece2 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_card.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; + +class DigitCard extends StatelessWidget { + final Widget child; + final EdgeInsets? padding; + final EdgeInsets? margin; + final VoidCallback? onPressed; + + const DigitCard({ + required this.child, + super.key, + this.padding, + this.margin, + this.onPressed, + }); + + @override + Widget build(BuildContext context) => Card( + margin: margin, + child: InkWell( + borderRadius: BorderRadius.circular(4), + onTap: onPressed, + child: Padding( + padding: padding ?? + const EdgeInsets.symmetric( + vertical: 16, + horizontal: 8, + ), + child: child, + ), + ), + ); +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_checkbox_tile.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_checkbox_tile.dart new file mode 100644 index 00000000..6d965343 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_checkbox_tile.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; + +class DigitCheckboxTile extends StatelessWidget { + final bool value; + final String label; + final ValueChanged? onChanged; + final EdgeInsets? margin; + final EdgeInsets? padding; + + const DigitCheckboxTile({ + this.value = false, + required this.label, + this.onChanged, + this.padding, + this.margin, + super.key, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Padding( + padding: margin ?? const EdgeInsets.all(8.0), + child: Material( + child: InkWell( + onTap: () => onChanged?.call(!value), + child: Padding( + padding: padding ?? + const EdgeInsets.symmetric( + horizontal: 8, + vertical: 8, + ), + child: Row( + children: [ + Icon( + value + ? Icons.check_box_outline_blank_sharp + : Icons.check_box_outlined, + color: theme.colorScheme.secondary, + ), + const SizedBox(width: 16), + Expanded( + child: Text( + label, + style: Theme.of(context).textTheme.bodyLarge, + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_dialog.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_dialog.dart new file mode 100644 index 00000000..eb47b676 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_dialog.dart @@ -0,0 +1,121 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; + +class DigitDialog extends StatelessWidget { + final DigitDialogOptions options; + + const DigitDialog({ + super.key, + required this.options, + }); + + static Future show( + BuildContext context, { + required DigitDialogOptions options, + }) { + return showDialog( + context: context, + barrierDismissible: options.barrierDismissible, + barrierColor: options.barrierColor ?? + DigitTheme.instance.colors.black.withOpacity(0.7), + builder: (context) => DigitDialog( + key: options.key, + options: options, + ), + ); + } + + @override + Widget build(BuildContext context) => AlertDialog( + title: options.title, + content: options.content, + actionsAlignment: MainAxisAlignment.spaceBetween, + actions: [ + if (options.primaryAction != null) + DigitElevatedButton( + onPressed: () => options.primaryAction!.action?.call(context), + child: Center(child: Text(options.primaryAction!.label)), + ), + if (options.secondaryAction != null) + TextButton( + onPressed: () => options.secondaryAction!.action?.call(context), + child: Center(child: Text(options.secondaryAction!.label)), + ), + ], + titlePadding: options.titlePadding, + contentPadding: options.contentPadding, + ); +} + +class DigitDialogOptions { + final Icon? titleIcon; + final EdgeInsets titlePadding; + final EdgeInsets contentPadding; + final String? titleText; + final String? contentText; + final Widget? _titleWidget; + final Widget? _contentWidget; + final DigitDialogActions? primaryAction; + final DigitDialogActions? secondaryAction; + final bool barrierDismissible; + final Color? barrierColor; + final Key? key; + + const DigitDialogOptions({ + this.titleText, + this.contentText, + this.titleIcon, + Widget? title, + Widget? content, + this.primaryAction, + this.secondaryAction, + this.barrierDismissible = false, + this.titlePadding = const EdgeInsets.all(kPadding), + this.contentPadding = const EdgeInsets.all(kPadding), + this.barrierColor, + this.key, + }) : _titleWidget = title, + _contentWidget = content; + + Widget? get title { + if (_titleWidget != null) return _titleWidget; + if (titleText != null) { + return Row( + children: [ + if (titleIcon != null) ...[ + titleIcon!, + const SizedBox(width: 8), + ], + Expanded( + child: Text( + titleText!, + textAlign: TextAlign.left, + ), + ), + ], + ); + } + return null; + } + + Widget? get content { + if (_contentWidget != null) return _contentWidget; + if (contentText != null) { + return Text( + contentText!, + textAlign: TextAlign.left, + ); + } + return null; + } +} + +class DigitDialogActions { + final String label; + final T Function(BuildContext context)? action; + + const DigitDialogActions({ + required this.label, + this.action, + }); +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_dob_picker.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_dob_picker.dart new file mode 100644 index 00000000..a30c5dc8 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_dob_picker.dart @@ -0,0 +1,102 @@ +import 'package:digit_components/widgets/atoms/digit_date_form_picker.dart'; +import 'package:digit_components/widgets/atoms/digit_text_form_field.dart'; +import 'package:flutter/material.dart'; +import 'package:reactive_forms/reactive_forms.dart'; + +class DigitDobPicker extends StatelessWidget { + final String datePickerFormControl; + + final bool isVerified; + + final ControlValueAccessor? valueAccessor; + final String datePickerLabel; + final String ageFieldLabel; + final String separatorLabel; + + const DigitDobPicker({ + super.key, + required this.datePickerFormControl, + this.isVerified = false, + this.valueAccessor, + required this.datePickerLabel, + required this.ageFieldLabel, + required this.separatorLabel, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Padding( + padding: const EdgeInsets.only(top: 16), + child: Container( + padding: const EdgeInsets.only(left: 8, right: 8, bottom: 16), + decoration: BoxDecoration( + color: theme.colorScheme.surface, + borderRadius: BorderRadius.circular(4), + border: Border.all( + color: Colors.grey, style: BorderStyle.solid, width: 1.0), + ), + child: Column( + children: [ + DigitDateFormPicker( + label: datePickerLabel, + formControlName: datePickerFormControl, + ), + const SizedBox(height: 16), + Text( + separatorLabel, + style: theme.textTheme.bodyLarge, + ), + DigitTextFormField( + maxLength: 3, + valueAccessor: DobValueAccessor(), + formControlName: datePickerFormControl, + label: ageFieldLabel, + keyboardType: TextInputType.number, + readOnly: isVerified, + onChanged: (formControl) { + /// Validates that control's value must be `true` + Map? requiredTrue( + AbstractControl control) { + String value = + (DateTime.now().difference(formControl.value).inDays / + 365) + .round() + .toStringAsFixed(0); + return int.parse(value) <= 150 + ? null + : {'Age Shoud be less than 150': true}; + } + + formControl.setValidators([requiredTrue]); + }, + ) + ], + ), + ), + ); + } +} + +class DobValueAccessor extends ControlValueAccessor { + @override + String? modelToViewValue(DateTime? modelValue) { + if (modelValue == null) return null; + return (DateTime.now().difference(modelValue).inDays / 365) + .round() + .toStringAsFixed(0); + } + + @override + DateTime? viewToModelValue(String? viewValue) { + if (viewValue == null) return null; + final value = int.tryParse(viewValue); + if (value == null) return null; + return DateTime( + DateTime.now().subtract(Duration(days: value * 365)).year, + 1, + 1, + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_elevated_button.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_elevated_button.dart new file mode 100644 index 00000000..9e4381e1 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_elevated_button.dart @@ -0,0 +1,34 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; + +class DigitElevatedButton extends StatelessWidget { + final Widget child; + final VoidCallback? onPressed; + + const DigitElevatedButton({ + super.key, + required this.child, + required this.onPressed, + }); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: DigitTheme.instance.colors.woodsmokeBlack, + width: 2, + ), + ), + ), + child: ElevatedButton( + style: ElevatedButton.styleFrom( + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + onPressed: onPressed, + child: Center(child: child), + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_icon_tile.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_icon_tile.dart new file mode 100644 index 00000000..967457a5 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_icon_tile.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +class DigitIconTile extends StatelessWidget { + final String title; + final Widget? content; + final IconData? icon; + final VoidCallback onPressed; + + const DigitIconTile({ + super.key, + required this.title, + this.content, + this.icon, + required this.onPressed, + }); + + @override + Widget build(BuildContext context) { + return ListTile( + minVerticalPadding: 16, + leading: Icon( + icon, + color: Theme.of(context).colorScheme.shadow, + ), + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + textAlign: TextAlign.start, + ), + content ?? const Offstage() + ], + ), + onTap: onPressed, + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_info_card.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_info_card.dart new file mode 100644 index 00000000..4ee189d8 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_info_card.dart @@ -0,0 +1,70 @@ +import 'package:digit_components/theme/digit_theme.dart'; +import 'package:flutter/material.dart'; + +class DigitInfoCard extends StatelessWidget { + final String title; + final String description; + final Color? backgroundColor; + final IconData? icon; + final Color? iconColor; + final EdgeInsets? padding; + final EdgeInsets? margin; + + const DigitInfoCard({ + super.key, + required this.title, + required this.description, + this.backgroundColor, + this.iconColor, + this.icon, + this.padding, + this.margin, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Container( + margin: margin ?? DigitTheme.instance.containerMargin, + padding: padding ?? const EdgeInsets.all(8), + decoration: ShapeDecoration( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(4)), + ), + color: backgroundColor ?? theme.colorScheme.tertiaryContainer, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: padding ?? const EdgeInsets.all(8), + child: Icon( + icon ?? Icons.info, + color: iconColor ?? theme.colorScheme.surfaceTint, + ), + ), + Expanded( + child: Text( + title, + style: theme.textTheme.headlineMedium, + ), + ) + ], + ), + Padding( + padding: const EdgeInsets.all(kPadding), + child: Text( + description, + style: theme.textTheme.bodyLarge, + textAlign: TextAlign.start, + ), + ) + ], + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_outline_button.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_outline_button.dart new file mode 100644 index 00000000..6aaaa557 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_outline_button.dart @@ -0,0 +1,51 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +class DigitOutLineButton extends StatelessWidget { + final String label; + final VoidCallback? onPressed; + + const DigitOutLineButton({ + super.key, + required this.label, + this.onPressed, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return OutlinedButton( + onPressed: onPressed, + style: OutlinedButton.styleFrom( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.zero, + ), + backgroundColor: Colors.white, + side: BorderSide( + width: 1.0, + color: onPressed != null + ? theme.colorScheme.secondary + : theme.colorScheme.outline, + ), + minimumSize: kIsWeb + ? Size( + MediaQuery.of(context).size.width / 11.25, + 40, + ) + : Size( + MediaQuery.of(context).size.width / 1.25, + 50, + ), + ), + child: Padding( + padding: const EdgeInsets.only(left: 15, right: 15), + child: Text( + label, + style: TextStyle( + color: theme.colorScheme.secondary, + ), + ), + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_project_cell.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_project_cell.dart new file mode 100644 index 00000000..30719286 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_project_cell.dart @@ -0,0 +1,72 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; + +class DigitProjectCell extends StatelessWidget { + final VoidCallback onTap; + final String projectText; + + const DigitProjectCell({ + super.key, + required this.projectText, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + child: DigitCard( + margin: const EdgeInsets.only( + left: 16, + right: 16, + ), + child: Padding( + padding: + const EdgeInsets.only(left: 16, right: 16, top: 12, bottom: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Icon( + Icons.article, + size: 30, + color: Theme.of(context).colorScheme.secondary, + ), + const SizedBox( + width: 14, + ), + SizedBox( + width: MediaQuery.of(context).size.width / 1.8, + child: Row( + children: [ + Flexible( + child: Text( + projectText, + style: Theme.of(context).textTheme.headlineLarge, + ), + ) + ], + ), + ), + ], + ), + Container( + height: 32, + width: 32, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.secondary, + shape: BoxShape.circle), + child: Icon( + Icons.arrow_forward, + color: Theme.of(context).colorScheme.onPrimary, + ), + ) + ], + ), + ), + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_reactive_type_ahead.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_reactive_type_ahead.dart new file mode 100644 index 00000000..d91b9cb8 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_reactive_type_ahead.dart @@ -0,0 +1,211 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_typeahead/flutter_typeahead.dart'; +import 'package:reactive_forms/reactive_forms.dart'; + +/// A [ReactiveForm] ancestor is required. +/// +class DigitReactiveTypeAhead extends ReactiveFormField { + DigitReactiveTypeAhead({ + Key? key, + String? formControlName, + FormControl? formControl, + Map? validationMessages, + ControlValueAccessor? valueAccessor, + ShowErrorsFunction? showErrors, + SuggestionSelectionCallback? onSuggestionSelected, + required this.stringify, + V Function(String)? viewDataTypeFromTextEditingValue, + required SuggestionsCallback suggestionsCallback, + required ItemBuilder itemBuilder, + SuggestionsBoxDecoration suggestionsBoxDecoration = + const SuggestionsBoxDecoration(), + Duration debounceDuration = const Duration(milliseconds: 300), + WidgetBuilder? loadingBuilder, + WidgetBuilder? noItemsFoundBuilder, + ErrorBuilder? errorBuilder, + AnimationTransitionBuilder? transitionBuilder, + double animationStart = 0.25, + Duration animationDuration = const Duration(milliseconds: 500), + bool getImmediateSuggestions = false, + double suggestionsBoxVerticalOffset = 5.0, + AxisDirection direction = AxisDirection.down, + bool hideOnLoading = false, + bool hideOnEmpty = false, + bool hideOnError = false, + bool hideSuggestionsOnKeyboardHide = true, + bool keepSuggestionsOnLoading = true, + bool keepSuggestionsOnSuggestionSelected = false, + bool autoFlipDirection = false, + bool hideKeyboard = false, + TextFieldConfiguration textFieldConfiguration = + const TextFieldConfiguration(), + SuggestionsBoxController? suggestionsBoxController, + InputDecoration decoration = const InputDecoration(), + TextInputType? keyboardType, + TextCapitalization textCapitalization = TextCapitalization.none, + TextInputAction? textInputAction, + TextStyle? style, + StrutStyle? strutStyle, + TextDirection? textDirection, + TextAlign textAlign = TextAlign.start, + TextAlignVertical? textAlignVertical, + bool autofocus = false, + bool readOnly = false, + bool? showCursor, + bool obscureText = false, + String obscuringCharacter = '•', + bool autocorrect = true, + V? initialValue, + String? initialValueText, + }) : super( + key: key, + formControl: formControl, + formControlName: formControlName, + valueAccessor: valueAccessor, + validationMessages: validationMessages, + showErrors: showErrors, + builder: (field) { + final state = field as _ReactiveTypeaheadState; + final effectiveDecoration = textFieldConfiguration.decoration + .applyDefaults(Theme.of(state.context).inputDecorationTheme); + + state._setFocusNode(textFieldConfiguration.focusNode); + final controller = + textFieldConfiguration.controller ?? state._textController; + if (initialValue != null && initialValueText != null) { + controller.text = initialValueText; + field.didChange(initialValue); + onSuggestionSelected?.call(initialValue); + } + + return TypeAheadField( + suggestionsCallback: suggestionsCallback, + itemBuilder: itemBuilder, + autoFlipListDirection: true, + onSuggestionSelected: (value) { + controller.text = stringify(value); + field.didChange(value); + + onSuggestionSelected?.call(value); + }, + textFieldConfiguration: textFieldConfiguration.copyWith( + focusNode: textFieldConfiguration.focusNode ?? state.focusNode, + controller: controller, + decoration: effectiveDecoration.copyWith( + errorText: state.errorText, + ), + onChanged: (value) { + if (viewDataTypeFromTextEditingValue != null) { + field.didChange( + viewDataTypeFromTextEditingValue.call(value)); + } + }, + ), + suggestionsBoxDecoration: suggestionsBoxDecoration, + debounceDuration: debounceDuration, + suggestionsBoxController: suggestionsBoxController, + loadingBuilder: loadingBuilder, + noItemsFoundBuilder: noItemsFoundBuilder, + errorBuilder: errorBuilder, + transitionBuilder: transitionBuilder, + animationStart: animationStart, + animationDuration: animationDuration, + getImmediateSuggestions: getImmediateSuggestions, + suggestionsBoxVerticalOffset: suggestionsBoxVerticalOffset, + direction: direction, + hideOnLoading: hideOnLoading, + hideOnEmpty: hideOnEmpty, + hideOnError: hideOnError, + hideSuggestionsOnKeyboardHide: hideSuggestionsOnKeyboardHide, + keepSuggestionsOnLoading: keepSuggestionsOnLoading, + keepSuggestionsOnSuggestionSelected: + keepSuggestionsOnSuggestionSelected, + autoFlipDirection: autoFlipDirection, + hideKeyboard: hideKeyboard, + ); + }, + ); + + final String Function(V value) stringify; + + @override + ReactiveFormFieldState createState() => _ReactiveTypeaheadState(); +} + +class _ReactiveTypeaheadState extends ReactiveFormFieldState { + late TextEditingController _textController; + FocusNode? _focusNode; + late FocusController _focusController; + + @override + FocusNode get focusNode => _focusNode ?? _focusController.focusNode; + + @override + void initState() { + super.initState(); + + final initialValue = value; + _textController = TextEditingController( + text: initialValue == null + ? '' + : (widget as DigitReactiveTypeAhead).stringify(initialValue), + ); + } + + @override + void subscribeControl() { + _registerFocusController(FocusController()); + super.subscribeControl(); + } + + @override + void unsubscribeControl() { + _unregisterFocusController(); + super.unsubscribeControl(); + } + + @override + void onControlValueChanged(dynamic value) { + final effectiveValue = (value == null) ? '' : value.toString(); + _textController.value = _textController.value.copyWith( + text: effectiveValue, + selection: TextSelection.collapsed(offset: effectiveValue.length), + composing: TextRange.empty, + ); + + super.onControlValueChanged(value); + } + + // @override + // ControlValueAccessor selectValueAccessor() { + // if (control is FormControl) { + // return IntValueAccessor() as ControlValueAccessor; + // } else if (control is FormControl) { + // return DoubleValueAccessor() as ControlValueAccessor; + // } else if (control is FormControl) { + // return DateTimeValueAccessor() as ControlValueAccessor; + // } else if (control is FormControl) { + // return TimeOfDayValueAccessor() as ControlValueAccessor; + // } + // + // return super.selectValueAccessor(); + // } + + void _registerFocusController(FocusController focusController) { + _focusController = focusController; + control.registerFocusController(focusController); + } + + void _unregisterFocusController() { + control.unregisterFocusController(_focusController); + _focusController.dispose(); + } + + void _setFocusNode(FocusNode? focusNode) { + if (_focusNode != focusNode) { + _focusNode = focusNode; + _unregisterFocusController(); + _registerFocusController(FocusController(focusNode: _focusNode)); + } + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_row_card/digit_row_card.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_row_card/digit_row_card.dart new file mode 100644 index 00000000..8a38f2a2 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_row_card/digit_row_card.dart @@ -0,0 +1,58 @@ +import 'package:digit_components/models/digit_row_card/digit_row_card_model.dart'; +import 'package:flutter/material.dart'; + +class DigitRowCard extends StatelessWidget { + final List rowItems; + final ValueChanged? onChanged; + final double width; + + const DigitRowCard({ + super.key, + this.onChanged, + required this.rowItems, + required this.width, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: rowItems + .map( + (e) => SizedBox( + height: 38, + width: width, + child: GestureDetector( + onTap: () => onChanged?.call(e), + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: e.isSelected + ? theme.colorScheme.secondary + : theme.colorScheme.onBackground, + ), + color: e.isSelected + ? theme.colorScheme.secondary + : theme.colorScheme.onSecondary, + ), + child: Center( + child: Text( + e.label, + style: TextStyle( + fontWeight: FontWeight.w400, + color: e.isSelected + ? theme.colorScheme.onSecondary + : theme.colorScheme.onBackground, + ), + ), + ), + ), + ), + ), + ) + .toList(), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_search_bar.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_search_bar.dart new file mode 100644 index 00000000..bfd6fc02 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_search_bar.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; + +class DigitSearchBar extends StatelessWidget { + final TextEditingController? controller; + final EdgeInsets? padding; + final EdgeInsets? margin; + final String? hintText; + final EdgeInsets? contentPadding; + final double? borderRadius; + final ValueChanged? onChanged; + final TextCapitalization textCapitalization; + + const DigitSearchBar({ + super.key, + this.controller, + this.padding, + this.margin, + this.hintText, + this.contentPadding, + this.borderRadius, + this.onChanged, + this.textCapitalization = TextCapitalization.none, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Card( + shape: RoundedRectangleBorder( + side: BorderSide(color: theme.scaffoldBackgroundColor, width: 1), + borderRadius: BorderRadius.circular( + borderRadius != null ? (borderRadius! * 3) : 30), + ), + margin: margin, + child: Padding( + padding: const EdgeInsets.all(10), + child: TextField( + controller: controller, + onChanged: onChanged, + textCapitalization: textCapitalization, + decoration: InputDecoration( + border: InputBorder.none, + hintText: hintText ?? 'Enter the field details', + filled: true, + fillColor: theme.cardColor, + contentPadding: contentPadding ?? + const EdgeInsets.only( + left: 14.0, + bottom: 6.0, + top: 8.0, + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(borderRadius ?? 10.0), + borderSide: BorderSide(color: theme.cardColor), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide(color: theme.scaffoldBackgroundColor), + borderRadius: BorderRadius.circular(borderRadius ?? 10.0), + ), + ), + ), + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_search_dropdown.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_search_dropdown.dart new file mode 100644 index 00000000..04aab65c --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_search_dropdown.dart @@ -0,0 +1,73 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; +import 'package:reactive_flutter_typeahead/reactive_flutter_typeahead.dart'; + +import 'digit_reactive_type_ahead.dart'; + +class DigitSearchDropdown extends StatelessWidget { + final Iterable Function(Iterable items, String pattern) + suggestionsCallback; + final SuggestionSelectionCallback? onSuggestionSelected; + final String label; + final T? initialValue; + final String? initialValueText; + final Iterable menuItems; + final String formControlName; + final bool isRequired; + final VoidCallback? onChanged; + final String Function(T value) valueMapper; + final Map? validationMessages; + + const DigitSearchDropdown({ + Key? key, + required this.suggestionsCallback, + this.onSuggestionSelected, + required this.label, + required this.menuItems, + required this.formControlName, + this.isRequired = false, + required this.valueMapper, + this.initialValue, + this.onChanged, + this.validationMessages, + this.initialValueText, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(top: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '$label${isRequired ? ' *' : ''}', + style: Theme.of(context).textTheme.bodyLarge, + ), + const SizedBox(height: 8), + DigitReactiveTypeAhead( + formControlName: formControlName, + stringify: valueMapper, + initialValue: initialValue, + initialValueText: initialValueText, + onSuggestionSelected: onSuggestionSelected, + debounceDuration: const Duration(milliseconds: 100), + suggestionsCallback: (pattern) => suggestionsCallback( + menuItems, + pattern, + ), + itemBuilder: (context, item) { + return Padding( + padding: const EdgeInsets.all(kPadding * 2), + child: Text( + valueMapper(item), + style: Theme.of(context).textTheme.bodyLarge, + ), + ); + }, + ), + ], + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_sync_dialog.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_sync_dialog.dart new file mode 100644 index 00000000..be56bde4 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_sync_dialog.dart @@ -0,0 +1,131 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; + +class DigitSyncDialog { + static Future show( + BuildContext context, { + Key? key, + bool barrierDismissible = false, + required DigitSyncDialogType type, + required String label, + DigitDialogActions? primaryAction, + DigitDialogActions? secondaryAction, + }) async { + return await DigitDialog.show( + context, + options: getDigitDialog( + type: type, + label: label, + barrierDismissible: barrierDismissible, + key: key, + primaryAction: primaryAction, + secondaryAction: secondaryAction, + ), + ); + } + + static DigitDialogOptions getDigitDialog({ + Key? key, + bool barrierDismissible = false, + required DigitSyncDialogType type, + required String label, + DigitDialogActions? primaryAction, + DigitDialogActions? secondaryAction, + }) { + final content = DigitSyncDialogContent( + label: label, + type: type, + key: key, + ); + + switch (type) { + case DigitSyncDialogType.inProgress: + break; + case DigitSyncDialogType.complete: + assert( + primaryAction != null, + 'Primary Action cannot be null for sync complete dialog', + ); + + break; + case DigitSyncDialogType.failed: + assert( + primaryAction != null, + 'Primary Action cannot be null for sync failed dialog', + ); + assert( + secondaryAction != null, + 'Secondary Action cannot be null for sync failed dialog', + ); + + break; + } + + return DigitDialogOptions( + content: content, + primaryAction: primaryAction, + secondaryAction: secondaryAction, + barrierDismissible: barrierDismissible, + contentPadding: const EdgeInsets.fromLTRB( + kPadding, + kPadding * 3, + kPadding, + kPadding * 2, + ), + key: key, + ); + } +} + +class DigitSyncDialogContent extends StatelessWidget { + final String label; + final DigitSyncDialogType type; + + final DigitDialogActions? primaryAction; + final DigitDialogActions? secondaryAction; + + const DigitSyncDialogContent({ + super.key, + required this.label, + required this.type, + this.primaryAction, + this.secondaryAction, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + IconData icon; + Color color; + TextStyle? labelStyle; + + switch (type) { + case DigitSyncDialogType.inProgress: + icon = Icons.autorenew; + color = theme.colorScheme.secondary; + labelStyle = theme.textTheme.headlineSmall; + break; + case DigitSyncDialogType.complete: + icon = Icons.check_circle_outline; + color = theme.colorScheme.onSurfaceVariant; + labelStyle = theme.textTheme.headlineLarge; + break; + case DigitSyncDialogType.failed: + icon = Icons.error_outline; + color = theme.colorScheme.error; + labelStyle = theme.textTheme.headlineLarge; + break; + } + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon, size: 32, color: color), + const SizedBox(height: kPadding * 2), + Text(label, style: labelStyle?.copyWith(color: color)), + ], + ); + } +} + +enum DigitSyncDialogType { inProgress, complete, failed } diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/digit_text_field.dart b/vehicle-tracker/packages/digit_components/lib/widgets/digit_text_field.dart new file mode 100644 index 00000000..a0a07f3c --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/digit_text_field.dart @@ -0,0 +1,85 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class DigitTextField extends StatelessWidget { + final String label; + final TextEditingController? controller; + final String prefixText; + final int? maxLength; + final int? maxLines; + final bool isRequired; + final ValueChanged? onChange; + final List? inputFormatter; + final FocusNode? focusNode; + final TextInputType? textInputType; + final String? pattern; + final String? message; + final String? Function(String? value)? validator; + final TextCapitalization? textCapitalization; + final AutovalidateMode? autoValidation; + final bool obscureText; + final bool isDisabled; + final bool readOnly; + final bool? isFilled; + final Widget? suffixIcon; + + const DigitTextField({ + super.key, + required this.label, + this.prefixText = '', + this.maxLength, + this.controller, + this.isRequired = false, + this.textInputType, + this.inputFormatter, + this.pattern, + this.validator, + this.message, + this.focusNode, + this.textCapitalization, + this.onChange, + this.maxLines, + this.autoValidation, + this.obscureText = false, + this.isDisabled = false, + this.readOnly = false, + this.isFilled, + this.suffixIcon, + }); + + @override + Widget build(BuildContext context) { + return LabeledField( + label: isRequired ? "$label *" : label, + child: TextFormField( + style: TextStyle( + color: readOnly == true + ? DigitTheme.instance.colorScheme.shadow + : DigitTheme.instance.colorScheme.onSurface), + controller: controller, + enabled: !isDisabled, + maxLength: maxLength, + keyboardType: textInputType ?? TextInputType.text, + autofocus: false, + inputFormatters: inputFormatter, + textCapitalization: textCapitalization ?? TextCapitalization.none, + onChanged: onChange, + maxLines: maxLines, + focusNode: focusNode, + obscureText: obscureText, + autovalidateMode: autoValidation, + readOnly: readOnly, + validator: (value) => validator?.call(value), + decoration: InputDecoration( + suffixIconConstraints: const BoxConstraints( + maxHeight: 48, + maxWidth: 48, + ), + //maxLines = 1 if suffixIcon != null + suffixIcon: suffixIcon, + ), + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/labeled_field.dart b/vehicle-tracker/packages/digit_components/lib/widgets/labeled_field.dart new file mode 100644 index 00000000..7f63468d --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/labeled_field.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; + +class LabeledField extends StatelessWidget { + final Widget child; + final String label; + final IconData? icon; + final String? tooltipMessage; + + const LabeledField( + {super.key, + required this.child, + required this.label, + this.icon, + this.tooltipMessage}); + + @override + Widget build(BuildContext context) => Padding( + padding: const EdgeInsets.only(top: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + Flexible( + child: Text( + label, + style: Theme.of(context).textTheme.labelSmall, + ), + ), + icon != null + ? Tooltip( + message: tooltipMessage ?? '', + preferBelow: false, + triggerMode: TooltipTriggerMode.tap, + child: Icon(icon ?? Icons.info_outline)) + : const SizedBox.shrink() + ], + ), + const SizedBox(height: 8), + child, + ], + ), + ); +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_acknowledgement.dart b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_acknowledgement.dart new file mode 100644 index 00000000..22e6311b --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_acknowledgement.dart @@ -0,0 +1,118 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; + +class DigitAcknowledgement extends StatelessWidget { + final String label; + final String? subLabel; + final String description; + final IconData icon; + final VoidCallback action; + final String actionLabel; + final Color color; + + DigitAcknowledgement.success({ + super.key, + required this.label, + this.subLabel, + required this.description, + required this.action, + required this.actionLabel, + IconData? icon, + Color? color, + }) : color = color ?? DigitTheme.instance.colors.darkSpringGreen, + icon = icon ?? Icons.check_circle; + + DigitAcknowledgement.error({ + super.key, + required this.label, + this.subLabel, + required this.description, + required this.action, + required this.actionLabel, + IconData? icon, + Color? color, + }) : color = color ?? DigitTheme.instance.colors.lavaRed, + icon = icon ?? Icons.error; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return ScrollableContent( + children: [ + DigitCard( + padding: EdgeInsets.zero, + child: Column( + children: [ + Container( + padding: const EdgeInsets.symmetric( + horizontal: kPadding * 2, + vertical: kPadding * 4, + ), + constraints: BoxConstraints( + minHeight: MediaQuery.of(context).size.height / 3, + ), + color: color, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + textAlign: TextAlign.center, + label, + style: TextStyle( + fontSize: 32, + fontWeight: FontWeight.w400, + color: theme.colorScheme.onPrimary, + ), + ), + Padding( + padding: DigitTheme.instance.containerMargin, + child: Icon( + icon, + size: 32, + color: theme.colorScheme.onPrimary, + ), + ), + if (subLabel != null) ...[ + Text( + textAlign: TextAlign.center, + subLabel!, + style: TextStyle( + fontSize: 26, + fontWeight: FontWeight.w700, + color: theme.colorScheme.onPrimary, + ), + ) + ], + ], + ), + ), + Padding( + padding: DigitTheme.instance.containerMargin, + child: Align( + alignment: Alignment.centerLeft, + child: Text( + description, + style: theme.textTheme.bodyMedium, + ), + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB( + kPadding, + kPadding, + kPadding, + kPadding * 2, + ), + child: DigitElevatedButton( + onPressed: action, + child: Text(actionLabel), + ), + ) + ], + ), + ), + ], + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_language_card.dart b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_language_card.dart new file mode 100644 index 00000000..cb72a54f --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_language_card.dart @@ -0,0 +1,46 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; +import '../../models/digit_row_card/digit_row_card_model.dart'; + +class DigitLanguageCard extends StatelessWidget { + final List digitRowCardItems; + final ValueChanged? onLanguageChange; + final VoidCallback onLanguageSubmit; + final String languageSubmitLabel; + + const DigitLanguageCard({ + super.key, + required this.digitRowCardItems, + this.onLanguageChange, + required this.onLanguageSubmit, + required this.languageSubmitLabel, + }); + + @override + Widget build(BuildContext context) { + return DigitCard( + margin: const EdgeInsets.all(8), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DigitRowCard( + onChanged: onLanguageChange, + rowItems: digitRowCardItems, + width: + (MediaQuery.of(context).size.width / digitRowCardItems.length) - + 16 * digitRowCardItems.length, + ), + const SizedBox( + height: 24, + width: 0, + ), + DigitElevatedButton( + onPressed: onLanguageSubmit, + child: Center(child: Text(languageSubmitLabel)), + ), + ], + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_list_view.dart b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_list_view.dart new file mode 100644 index 00000000..1e64d9b6 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_list_view.dart @@ -0,0 +1,62 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; + +class DigitListView extends StatelessWidget { + final IconData? prefixIcon; + final String title; + final String? description; + final IconData? sufixIcon; + final VoidCallback? onPressed; + + const DigitListView( + {super.key, + this.prefixIcon, + required this.title, + this.description, + this.sufixIcon, + this.onPressed}); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return DigitCard( + onPressed: onPressed, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + width: MediaQuery.of(context).size.width - 100, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Icon( + prefixIcon, + color: theme.colorScheme.secondary, + size: 24, + ), + const SizedBox( + width: 14, + ), + Text( + title, + style: theme.textTheme.headlineMedium, + ), + ], + ), + Offstage( + offstage: description == null, + child: Text(description!), + ), + ], + )), + Icon( + sufixIcon, + color: theme.colorScheme.secondary, + size: 36, + ), + ], + )); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_loader.dart b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_loader.dart new file mode 100644 index 00000000..8af8995f --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_loader.dart @@ -0,0 +1,141 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; + +class Loaders { + static circularLoader(BuildContext context) { + return WillPopScope( + onWillPop: () async => false, + child: SizedBox( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: SimpleDialog( + elevation: 0.0, + backgroundColor: Colors.transparent, + children: [ + Center( + child: Column(children: [ + CircularProgressIndicator( + color: Theme.of(context).colorScheme.secondary, + ), + const SizedBox( + height: 10, + ), + const Text( + 'Loading...', + style: TextStyle( + color: Color.fromRGBO(0, 0, 0, 1), + fontFamily: 'Roboto', + fontSize: 16, + fontWeight: FontWeight.w700), + ) + ]), + ) + ]), + )); + } + + static Future showLoadingDialog( + BuildContext context, { + String? label, + }) async { + return showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return WillPopScope( + onWillPop: () async => false, + child: SizedBox( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: SimpleDialog( + elevation: 0.0, + backgroundColor: Colors.transparent, + children: [ + Center( + child: Column(children: [ + CircularProgressIndicator( + color: Theme.of(context).colorScheme.secondary, + ), + const SizedBox( + height: 10, + ), + Text( + label ?? 'Loading...', + style: const TextStyle( + color: Color(0xffFFFFFF), + fontFamily: 'Roboto', + fontSize: 16, + fontWeight: FontWeight.w700), + ) + ]), + ) + ]), + )); + }); + } + + static void showLoader(BuildContext context, {String? text}) { + showDialog( + context: context, + barrierColor: Colors.transparent, + barrierDismissible: false, + builder: (BuildContext context) { + return WillPopScope( + onWillPop: () async => false, + child: Dialog( + // backgroundColor:CustomColors.BLACK, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15)), + child: WillPopScope( + onWillPop: () async { + return true; + }, + child: Container( + padding: const EdgeInsets.symmetric( + vertical: 10, horizontal: 10), + child: Wrap( + runSpacing: 15, + alignment: WrapAlignment.center, + children: [ + const SpinKitCircle( + color: Colors.white, + size: 50.0, + ), + Text( + text ?? + ' Getting image data \n Please check the values once done. ', + textAlign: TextAlign.center, + style: const TextStyle(color: Colors.white), + ), + ], + )), + ), + ), + ); + }); + } +} + +class DigitLoader extends StatefulWidget { + const DigitLoader({super.key}); + + @override + State createState() { + return DigitLoaderState(); + } +} + +class DigitLoaderState extends State { + @override + void initState() { + WidgetsBinding.instance.addPostFrameCallback((_) { + Loaders.showLoadingDialog(context); + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Container(); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_table.dart b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_table.dart new file mode 100644 index 00000000..0df29e96 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_table.dart @@ -0,0 +1,188 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:digit_components/models/digit_table_model.dart'; +import 'package:digit_components/theme/digit_theme.dart'; +import 'package:flutter/material.dart'; +import 'package:horizontal_data_table/horizontal_data_table.dart'; + +class DigitTable extends StatelessWidget { + final double columnRowFixedHeight = 52.0; + final List headerList; + final List tableData; + final double leftColumnWidth; + final double rightColumnWidth; + final double? height; + + const DigitTable({ + Key? key, + required this.headerList, + required this.tableData, + required this.leftColumnWidth, + required this.rightColumnWidth, + this.height, + }) : super(key: key); + + List? _getTitleWidget(ThemeData theme) { + var index = 0; + return headerList.map((e) { + index++; + + if (e.isSortingRequired ?? false) { + return TextButton( + style: TextButton.styleFrom( + padding: EdgeInsets.zero, + ), + onPressed: e.callBack == null ? null : () => e.callBack!(e), + child: _getTitleItemWidget((e.label), theme, + isAscending: e.isAscendingOrder, + isBorderRequired: (index - 1) == 0)); + } else { + return _getTitleItemWidget(e.label, theme, + isBorderRequired: (index - 1) == 0); + } + }).toList(); + } + + Widget _getTitleItemWidget(String label, ThemeData theme, + {bool? isAscending, bool isBorderRequired = false}) { + var textWidget = Text((label), style: theme.textTheme.headlineSmall); + final tableCellBorder = DigitTheme.instance.tableCellBorder; + final tableCellStrongBorder = DigitTheme.instance.tableCellStrongBorder; + final surfaceColor = DigitTheme.instance.colorScheme.surface; + + return Container( + decoration: isBorderRequired + ? BoxDecoration( + border: Border( + left: tableCellBorder, + bottom: tableCellBorder, + right: tableCellStrongBorder, + ), + color: surfaceColor) + : null, + width: leftColumnWidth, + height: 56, + color: !isBorderRequired ? surfaceColor : null, + padding: const EdgeInsets.only(left: 17, right: 5, top: 6, bottom: 6), + alignment: Alignment.centerLeft, + child: isAscending != null + ? Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + spacing: 5, + children: [ + textWidget, + Icon(isAscending + ? Icons.arrow_upward + : Icons.arrow_downward_sharp) + ], + ) + : textWidget, + ); + } + + double columnRowIncreasedHeight(int index) { + return (50 + + tableData[index].tableRow.first.label.substring(28).length.toDouble()); + //if greater than 28 characters + } + + Widget _generateColumnRow(BuildContext context, int index, String input, + {TextStyle? style}) { + return Container( + width: leftColumnWidth, + height: tableData[index].tableRow.first.label.length > 28 + ? columnRowIncreasedHeight(index) + : columnRowFixedHeight, + padding: const EdgeInsets.only(left: 17, right: 5, top: 6, bottom: 6), + alignment: Alignment.centerLeft, + color: index % 2 == 0 + ? DigitTheme.instance.colorScheme.background + : DigitTheme.instance.colorScheme.surface, + child: Row( + children: [ + Expanded( + child: Text( + (input), + style: style, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ) + ], + ), + ); + } + + Widget _generateRightHandSideColumnRow(BuildContext context, int index) { + final theme = Theme.of(context); + var data = tableData[index]; + var list = []; + for (int i = 1; i < data.tableRow.length; i++) { + list.add(_generateColumnRow(context, index, data.tableRow[i].label, + style: data.tableRow[i].style)); + } + + return Container( + color: index % 2 == 0 ? theme.scaffoldBackgroundColor : theme.cardColor, + child: Row(children: list)); + } + + Widget _generateFirstColumnRow(BuildContext context, int index) { + var data = tableData[index].tableRow.first; + final tableCellBorder = DigitTheme.instance.tableCellBorder; + final tableCellStrongBorder = DigitTheme.instance.tableCellStrongBorder; + return InkWell( + onTap: () { + if (data.callBack != null) { + data.callBack!(data); + } + }, + child: Container( + decoration: BoxDecoration( + color: DigitTheme.instance.colorScheme.surface, + border: Border( + left: tableCellBorder, + right: tableCellStrongBorder, + )), + width: leftColumnWidth, + height: tableData[index].tableRow.first.label.length > 28 + ? columnRowIncreasedHeight(index) + : columnRowFixedHeight, + padding: const EdgeInsets.only(left: 17, right: 5, top: 6, bottom: 6), + alignment: Alignment.centerLeft, + child: Text(tableData[index].tableRow.first.label, + style: tableData[index].tableRow.first.style), + ), + ); + } + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return SizedBox( + height: height, + child: Container( + margin: const EdgeInsets.fromLTRB(0, 16, 0, 0), + decoration: BoxDecoration( + border: Border.all(color: DigitTheme.instance.colorScheme.outline), + borderRadius: const BorderRadius.all(Radius.circular(4.0)), + ), + child: HorizontalDataTable( + leftHandSideColumnWidth: leftColumnWidth, + rightHandSideColumnWidth: rightColumnWidth, + isFixedHeader: true, + headerWidgets: _getTitleWidget(theme), + leftSideItemBuilder: _generateFirstColumnRow, + rightSideItemBuilder: _generateRightHandSideColumnRow, + itemCount: tableData.length, + rowSeparatorWidget: const Divider( + color: Colors.black54, + height: 1.0, + thickness: 0.0, + ), + ), + ), + ); + } + +//Need to move this to theme +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_table_card.dart b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_table_card.dart new file mode 100644 index 00000000..67c698d2 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_table_card.dart @@ -0,0 +1,64 @@ +import 'package:digit_components/theme/digit_theme.dart'; +import 'package:flutter/material.dart'; + +class DigitTableCard extends StatelessWidget { + final Map element; + final Border? border; + final Color? color; + final EdgeInsetsGeometry? padding; + final double gap; + final num fraction; + + const DigitTableCard({ + super.key, + required this.element, + this.border, + this.color, + this.padding, + this.gap = 0, + this.fraction = 2, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Padding( + padding: const EdgeInsets.only(top: 16), + child: Container( + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(4), + border: border), + child: Padding( + padding: padding ?? const EdgeInsets.only(right: 8, bottom: 16), + child: Column( + children: element.keys + .map((e) => Container( + margin: DigitTheme.instance.verticalMargin, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: MediaQuery.of(context).size.width / fraction, + child: Text( + e, + style: theme.textTheme.headlineSmall, + textAlign: TextAlign.start, + ), + ), + SizedBox(width: gap), + Flexible( + child: Padding( + padding: const EdgeInsets.only(top: 1.4), + child: Text(element[e].toString()), + )), + ], + ), + )) + .toList(), + ), + ), + ), + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_walkthrough.dart b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_walkthrough.dart new file mode 100644 index 00000000..2346c7b0 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/molecules/digit_walkthrough.dart @@ -0,0 +1,75 @@ +import 'package:digit_components/widgets/atoms/anchor_overlay.dart'; +import 'package:flutter/material.dart'; +import 'package:overlay_builder/overlay_builder.dart'; + +class DigitWalkthrough extends StatefulWidget { + final Widget child; + final String? title; + final GlobalKey overlayWidget; + final TextAlign titleAlignment; + final String description; + + const DigitWalkthrough( + {super.key, + required this.child, + required this.overlayWidget, + this.title, + required this.titleAlignment, + required this.description}); + + @override + State createState() => _DigitWalkthroughState(); +} + +class _DigitWalkthroughState extends State { + final _overlayFullscreen = GlobalKey(); + bool showOverlay = false; + late double childHeight; + late Offset position; + + _DigitWalkthroughState(); + OverlayWidgetState? get overlayWidgetController { + return widget.overlayWidget.currentState; + } + + OverlayWidgetState? get overlayFullscreenController { + return _overlayFullscreen.currentState; + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + initOffsetsPositions(); + }); + } + + void initOffsetsPositions() { + Offset position = ((widget.child.key as GlobalKey) + .currentContext + ?.findRenderObject() as RenderBox) + .localToGlobal(Offset.zero); + childHeight = (widget.child.key as GlobalKey).currentContext!.size!.height; + this.position = position; + } + + void onTap() { + setState(() { + showOverlay = !showOverlay; + }); + overlayWidgetController?.toggle(); + overlayFullscreenController?.toggle(); + } + + @override + Widget build(BuildContext context) { + return AnchoredOverlay( + showOverlay: showOverlay, + description: widget.description, + paramKey: widget.overlayWidget, + onTap: onTap, + position: position, + childHeight: childHeight, + child: widget.child); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/powered_by_digit.dart b/vehicle-tracker/packages/digit_components/lib/widgets/powered_by_digit.dart new file mode 100644 index 00000000..1496c5da --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/powered_by_digit.dart @@ -0,0 +1,35 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; + +class PoweredByDigit extends StatefulWidget { + final Size? size; + final EdgeInsets? padding; + final bool isWhiteLogo; + + const PoweredByDigit( + {super.key, this.size, this.padding, this.isWhiteLogo = false}); + + @override + State createState() => _PoweredByDigitState(); +} + +class _PoweredByDigitState extends State { + @override + Widget build(BuildContext context) => SafeArea( + child: Center( + child: Container( + height: 24, + padding: widget.padding ?? const EdgeInsets.all(4), + alignment: Alignment.center, + child: Image.asset( + 'assets/images/powered_by_digit.png', + package: 'digit_components', + fit: BoxFit.contain, + color: widget.isWhiteLogo + ? DigitTheme.instance.colorScheme.onPrimary + : null + ), + ), + ), + ); +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/scrollable_content.dart b/vehicle-tracker/packages/digit_components/lib/widgets/scrollable_content.dart new file mode 100644 index 00000000..70527bcf --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/scrollable_content.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; + +class ScrollableContent extends StatelessWidget { + final Widget? header; + final Widget? footer; + final List slivers; + final bool? primary; + final ScrollController? controller; + final MainAxisAlignment mainAxisAlignment; + final CrossAxisAlignment crossAxisAlignment; + final List children; + + const ScrollableContent({ + super.key, + this.footer, + this.header, + this.primary, + this.controller, + this.mainAxisAlignment = MainAxisAlignment.start, + this.crossAxisAlignment = CrossAxisAlignment.start, + this.children = const [], + this.slivers = const [], + }); + + @override + Widget build(BuildContext context) { + return CustomScrollView( + controller: controller, + primary: primary, + slivers: [ + if (header != null) SliverToBoxAdapter(child: header), + ...slivers, + SliverFillRemaining( + hasScrollBody: false, + child: Center( + child: Column( + crossAxisAlignment: crossAxisAlignment, + children: [ + Expanded( + child: Column( + mainAxisAlignment: mainAxisAlignment, + children: children, + ), + ), + if (footer != null) ...[ + const SizedBox(height: 16), + footer!, + ], + ], + ), + ), + ), + ], + ); + } +} diff --git a/vehicle-tracker/packages/digit_components/lib/widgets/widgets.dart b/vehicle-tracker/packages/digit_components/lib/widgets/widgets.dart new file mode 100644 index 00000000..642bf385 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/lib/widgets/widgets.dart @@ -0,0 +1,32 @@ +export './atoms//digit_icon_button.dart'; +export './atoms/digit_action_dialog.dart'; +export './atoms/digit_date_form_picker.dart'; +export './atoms/digit_dropdown.dart'; +export './atoms/digit_integer_form_picker.dart'; +export './atoms/digit_outline_icon_button.dart'; +export './atoms/digit_reactive_dropdown.dart'; +export './atoms/digit_table_item.dart'; +export './atoms/digit_table_item_title.dart'; +export './atoms/digit_text_form_field.dart'; +export './digit_banner.dart'; +export './digit_card.dart'; +export './digit_checkbox_tile.dart'; +export './digit_dialog.dart'; +export './digit_elevated_button.dart'; +export './digit_icon_tile.dart'; +export './digit_info_card.dart'; +export './digit_outline_button.dart'; +export './digit_search_bar.dart'; +export './digit_text_field.dart'; +export './labeled_field.dart'; +export './molecules/digit_acknowledgement.dart'; +export './molecules/digit_language_card.dart'; +export './molecules/digit_list_view.dart'; +export './molecules/digit_loader.dart'; +export './molecules/digit_table.dart'; +export './molecules/digit_table_card.dart'; +export './powered_by_digit.dart'; +export './scrollable_content.dart'; +export 'atoms/digit_toast_helper.dart'; +export 'digit_row_card/digit_row_card.dart'; +export 'digit_search_dropdown.dart'; diff --git a/vehicle-tracker/packages/digit_components/pubspec.lock b/vehicle-tracker/packages/digit_components/pubspec.lock new file mode 100644 index 00000000..7eaba03f --- /dev/null +++ b/vehicle-tracker/packages/digit_components/pubspec.lock @@ -0,0 +1,831 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a + url: "https://pub.dev" + source: hosted + version: "61.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 + url: "https://pub.dev" + source: hosted + version: "5.13.0" + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + bloc: + dependency: transitive + description: + name: bloc + sha256: f53a110e3b48dcd78136c10daa5d51512443cea5e1348c9d80a320095fa2db9e + url: "https://pub.dev" + source: hosted + version: "8.1.3" + bloc_test: + dependency: "direct dev" + description: + name: bloc_test + sha256: "55a48f69e0d480717067c5377c8485a3fcd41f1701a820deef72fa0f4ee7215f" + url: "https://pub.dev" + source: hosted + version: "9.1.6" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + url: "https://pub.dev" + source: hosted + version: "4.0.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct main" + description: + name: build_runner + sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" + url: "https://pub.dev" + source: hosted + version: "2.4.8" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" + url: "https://pub.dev" + source: hosted + version: "7.3.0" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: fedde275e0a6b798c3296963c5cd224e3e1b55d0e478d5b7e65e6b540f363a0e + url: "https://pub.dev" + source: hosted + version: "8.9.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 + url: "https://pub.dev" + source: hosted + version: "4.10.0" + collection: + dependency: transitive + description: + name: collection + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" + source: hosted + version: "1.17.1" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + coverage: + dependency: transitive + description: + name: coverage + sha256: "595a29b55ce82d53398e1bcc2cba525d7bd7c59faeb2d2540e9d42c390cfeeeb" + url: "https://pub.dev" + source: hosted + version: "1.6.4" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + diff_match_patch: + dependency: transitive + description: + name: diff_match_patch + sha256: "2efc9e6e8f449d0abe15be240e2c2a3bcd977c8d126cfd70598aee60af35c0a4" + url: "https://pub.dev" + source: hosted + version: "0.4.1" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + sha256: "87325da1ac757fcc4813e6b34ed5dd61169973871fdf181d6c2109dd6935ece1" + url: "https://pub.dev" + source: hosted + version: "8.1.4" + flutter_keyboard_visibility: + dependency: transitive + description: + name: flutter_keyboard_visibility + sha256: "4983655c26ab5b959252ee204c2fffa4afeb4413cd030455194ec0caa3b8e7cb" + url: "https://pub.dev" + source: hosted + version: "5.4.1" + flutter_keyboard_visibility_linux: + dependency: transitive + description: + name: flutter_keyboard_visibility_linux + sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_keyboard_visibility_macos: + dependency: transitive + description: + name: flutter_keyboard_visibility_macos + sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_keyboard_visibility_platform_interface: + dependency: transitive + description: + name: flutter_keyboard_visibility_platform_interface + sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_keyboard_visibility_web: + dependency: transitive + description: + name: flutter_keyboard_visibility_web + sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_keyboard_visibility_windows: + dependency: transitive + description: + name: flutter_keyboard_visibility_windows + sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + url: "https://pub.dev" + source: hosted + version: "2.0.3" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_spinkit: + dependency: "direct main" + description: + name: flutter_spinkit + sha256: b39c753e909d4796906c5696a14daf33639a76e017136c8d82bf3e620ce5bb8e + url: "https://pub.dev" + source: hosted + version: "5.2.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_typeahead: + dependency: "direct main" + description: + name: flutter_typeahead + sha256: b9942bd5b7611a6ec3f0730c477146cffa4cd4b051077983ba67ddfc9e7ee818 + url: "https://pub.dev" + source: hosted + version: "4.8.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + sha256: dfdde255317af381bfc1c486ed968d5a43a2ded9c931e87cbecd88767d6a71c1 + url: "https://pub.dev" + source: hosted + version: "8.2.4" + freezed: + dependency: "direct dev" + description: + name: freezed + sha256: "57247f692f35f068cae297549a46a9a097100685c6780fe67177503eea5ed4e5" + url: "https://pub.dev" + source: hosted + version: "2.4.7" + freezed_annotation: + dependency: "direct main" + description: + name: freezed_annotation + sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d + url: "https://pub.dev" + source: hosted + version: "2.4.1" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" + source: hosted + version: "2.3.1" + horizontal_data_table: + dependency: "direct main" + description: + name: horizontal_data_table + sha256: c8ab5256bbced698a729f3e0ff2cb0e8e97416cdbb082860370eaf883badf722 + url: "https://pub.dev" + source: hosted + version: "4.3.1" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + intl: + dependency: "direct main" + description: + name: intl + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 + url: "https://pub.dev" + source: hosted + version: "0.18.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + json_annotation: + dependency: "direct main" + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969 + url: "https://pub.dev" + source: hosted + version: "6.7.1" + lints: + dependency: transitive + description: + name: lints + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + location: + dependency: "direct main" + description: + name: location + sha256: "06be54f682c9073cbfec3899eb9bc8ed90faa0e17735c9d9fa7fe426f5be1dd1" + url: "https://pub.dev" + source: hosted + version: "5.0.3" + location_platform_interface: + dependency: "direct main" + description: + name: location_platform_interface + sha256: "8aa1d34eeecc979d7c9fe372931d84f6d2ebbd52226a54fe1620de6fdc0753b1" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + location_web: + dependency: transitive + description: + name: location_web + sha256: ec484c66e8a4ff1ee5d044c203f4b6b71e3a0556a97b739a5bc9616de672412b + url: "https://pub.dev" + source: hosted + version: "4.2.0" + logging: + dependency: "direct main" + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" + source: hosted + version: "0.12.15" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" + mocktail: + dependency: "direct dev" + description: + name: mocktail + sha256: "80a996cd9a69284b3dc521ce185ffe9150cde69767c2d3a0720147d93c0cef53" + url: "https://pub.dev" + source: hosted + version: "0.3.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + overlay_builder: + dependency: "direct main" + description: + name: overlay_builder + sha256: "58b97bc5f67a2e2bb7006dd88e697ac757dfffc9dbd1e7dfc1917fb510a4b5c8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + plugin_platform_interface: + dependency: "direct main" + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pointer_interceptor: + dependency: transitive + description: + name: pointer_interceptor + sha256: acfcd63c00ec3d5a7894b0e2a875893716d31958fe03f064734dba7dfd9113d9 + url: "https://pub.dev" + source: hosted + version: "0.9.3+5" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + provider: + dependency: transitive + description: + name: provider + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c + url: "https://pub.dev" + source: hosted + version: "6.1.2" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + url: "https://pub.dev" + source: hosted + version: "1.2.3" + reactive_flutter_typeahead: + dependency: "direct main" + description: + name: reactive_flutter_typeahead + sha256: "8806c5c26cce77670daced798163ff758a8b98d25b9971ad32f1ed9cfc3c7546" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + reactive_forms: + dependency: "direct main" + description: + name: reactive_forms + sha256: "5aa9c48a0626c20d00a005e597cb10efbdebbfeecb9c4227b03a5945fbb91ec4" + url: "https://pub.dev" + source: hosted + version: "14.3.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e + url: "https://pub.dev" + source: hosted + version: "1.1.2" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" + url: "https://pub.dev" + source: hosted + version: "1.3.4" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" + source: hosted + version: "0.10.12" + source_span: + dependency: transitive + description: + name: source_span + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" + source: hosted + version: "1.9.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test: + dependency: transitive + description: + name: test + sha256: "3dac9aecf2c3991d09b9cdde4f98ded7b30804a88a0d7e4e7e1678e78d6b97f4" + url: "https://pub.dev" + source: hosted + version: "1.24.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" + source: hosted + version: "0.5.1" + test_core: + dependency: transitive + description: + name: test_core + sha256: "5138dbffb77b2289ecb12b81c11ba46036590b72a64a7a90d6ffb880f1a29e93" + url: "https://pub.dev" + source: hosted + version: "0.5.1" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 + url: "https://pub.dev" + source: hosted + version: "11.10.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" + source: hosted + version: "2.4.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.0.0 <4.0.0" + flutter: ">=3.7.0" diff --git a/vehicle-tracker/packages/digit_components/pubspec.yaml b/vehicle-tracker/packages/digit_components/pubspec.yaml new file mode 100644 index 00000000..c38f7205 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/pubspec.yaml @@ -0,0 +1,49 @@ +name: digit_components +description: Digit UI Design specification Flutter widgets. Import this package by adding digit_components in respective pubspec.yaml dependencies. +version: 0.0.1+8 +homepage: https://github.com/egovernments/health-campaign-field-worker-app/tree/pub.dev/packages/digit_components + +environment: + sdk: '>=2.19.0 <4.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + flutter_bloc: ^8.1.1 + intl: ^0.18.0 + freezed_annotation: ^2.2.0 + horizontal_data_table: ^4.1.3 + location: ^5.0.0 + location_platform_interface: ^3.0.0 + json_annotation: ^4.7.0 + logging: ^1.1.0 + build_runner: ^2.2.1 + reactive_forms: ^14.2.0 + plugin_platform_interface: ^2.1.3 + flutter_localizations: + sdk: flutter + fluttertoast: ^8.1.2 + flutter_spinkit: ^5.1.0 + reactive_flutter_typeahead: ^0.7.0 + flutter_typeahead: ^4.3.7 + overlay_builder: ^1.1.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 + json_serializable: ^6.4.0 + freezed: ^2.2.0 + bloc_test: ^9.1.0 + mocktail: ^0.3.0 + +flutter: + assets: + - assets/images/ + fonts: + - family: Roboto + fonts: + - asset: assets/fonts/Roboto/RobotoCondensed-Regular.ttf + - asset: assets/fonts/Roboto/Roboto-Regular.ttf + diff --git a/vehicle-tracker/packages/digit_components/test/bloc/location_test.dart b/vehicle-tracker/packages/digit_components/test/bloc/location_test.dart new file mode 100644 index 00000000..89290ef4 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/bloc/location_test.dart @@ -0,0 +1,99 @@ +import 'package:bloc_test/bloc_test.dart'; +import 'package:digit_components/blocs/location/location.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:location/location.dart'; +import 'package:location_platform_interface/location_platform_interface.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +class MockLocationPlatform extends Mock + with MockPlatformInterfaceMixin + implements LocationPlatform {} + +void main() { + const mockLat = -25.953724; + const mockLng = 32.588711; + + group('Location bloc', () { + blocTest( + 'throws if location permission is not granted', + build: () => LocationBloc(location: Location()), + setUp: () { + final mock = MockLocationPlatform(); + const denied = PermissionStatus.denied; + + when(() => mock.hasPermission()).thenAnswer((_) async => denied); + when(() => mock.requestPermission()).thenAnswer((_) async => denied); + + LocationPlatform.instance = mock; + }, + act: (bloc) => bloc.add(const RequestLocationPermissionEvent()), + errors: () => [isA()], + ); + }); + + blocTest( + 'throws if location services are not enabled', + build: () => LocationBloc(location: Location()), + setUp: () { + final mock = MockLocationPlatform(); + + const granted = PermissionStatus.granted; + when(() => mock.hasPermission()).thenAnswer((_) async => granted); + when(() => mock.serviceEnabled()).thenAnswer((_) async => false); + when(() => mock.requestService()).thenAnswer((_) async => false); + + LocationPlatform.instance = mock; + }, + act: (bloc) => bloc.add(const RequestLocationServiceEvent()), + errors: () => [isA()], + ); + + blocTest( + 'loads with mock latLng', + build: () => LocationBloc(location: Location()), + setUp: () { + final mock = MockLocationPlatform(); + when(() => mock.serviceEnabled()).thenAnswer((_) async => true); + when(() => mock.hasPermission()).thenAnswer( + (_) async => PermissionStatus.granted, + ); + + when(() => mock.getLocation()).thenAnswer( + (invocation) async => LocationData.fromMap({ + 'latitude': mockLat, + 'longitude': mockLng, + 'accuracy': 1.0, + }), + ); + + LocationPlatform.instance = mock; + }, + act: (bloc) => bloc.add(const LoadLocationEvent()), + expect: () => [ + isA().having( + (state) => state.loading, + 'will enter loading state', + true, + ), + isA().having( + (state) => state.hasPermissions, + 'has permission granted', + true, + ), + isA().having( + (state) => state.serviceEnabled, + 'has services enabled', + true, + ), + isA() + .having((state) => state.latitude, 'will fetch mocked lat', mockLat) + .having((state) => state.longitude, 'will fetch mocked lng', mockLng), + isA().having( + (state) => state.loading, + 'will enter loading state', + false, + ), + ], + ); +} diff --git a/vehicle-tracker/packages/digit_components/test/digit_ui_components_test.dart b/vehicle-tracker/packages/digit_components/test/digit_ui_components_test.dart new file mode 100644 index 00000000..ab73b3a2 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/digit_ui_components_test.dart @@ -0,0 +1 @@ +void main() {} diff --git a/vehicle-tracker/packages/digit_components/test/theme/theme_test.dart b/vehicle-tracker/packages/digit_components/test/theme/theme_test.dart new file mode 100644 index 00000000..7b0b08f3 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/theme/theme_test.dart @@ -0,0 +1,150 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + DigitUi.instance.initThemeComponents(); + + group('Digit theme', () { + group('Typography', () { + final digitTheme = DigitTheme.instance; + + final widget = MaterialApp( + theme: digitTheme.mobileTheme, + home: Scaffold( + body: Builder(builder: (context) { + final theme = Theme.of(context).textTheme; + return Column( + children: [ + Text('Headline XL', style: theme.displayMedium), + Text('Headline L', style: theme.headlineLarge), + Text('Headline M', style: theme.headlineMedium), + Text('Headline S', style: theme.headlineSmall), + Text('Caption XL', style: theme.labelLarge), + Text('Caption L', style: theme.labelMedium), + Text('Caption M', style: theme.labelSmall), + Text('Body L', style: theme.bodyLarge), + Text('Body S', style: theme.bodyMedium), + Text('Body XS', style: theme.bodySmall), + Text('Label', style: digitTheme.mobileTypography.label), + Text('Link', style: digitTheme.mobileTypography.link), + ], + ); + }), + ), + ); + + const normal = Color(0xFF0B0C0C); + const light = Color(0xFF505A5F); + + const designSpecifications = [ + _DesignSpecification( + title: 'Headline XL', + fontSize: 32, + color: normal, + fontWeight: FontWeight.w700, + ), + _DesignSpecification( + title: 'Headline L', + fontSize: 24, + color: normal, + fontWeight: FontWeight.w700, + ), + _DesignSpecification( + title: 'Headline M', + fontSize: 18, + color: normal, + fontWeight: FontWeight.w700, + ), + _DesignSpecification( + title: 'Body L', + fontSize: 16, + color: normal, + fontWeight: FontWeight.w400, + ), + _DesignSpecification( + title: 'Body S', + fontSize: 14, + color: normal, + fontWeight: FontWeight.w400, + ), + _DesignSpecification( + title: 'Caption XL', + fontSize: 19, + color: normal, + fontWeight: FontWeight.w500, + ), + _DesignSpecification( + title: 'Caption L', + fontSize: 18, + color: light, + fontWeight: FontWeight.w400, + ), + _DesignSpecification( + title: 'Caption M', + fontSize: 16, + color: light, + fontWeight: FontWeight.w400, + ), + _DesignSpecification( + title: 'Link', + fontSize: 16, + color: normal, + fontWeight: FontWeight.w400, + ), + _DesignSpecification( + title: 'Label', + fontSize: 16, + color: normal, + fontWeight: FontWeight.w400, + ), + ]; + + for (final element in designSpecifications) { + group(element.title, () { + testWidgets('matches title', (tester) async { + await tester.pumpWidget(widget); + final child = find.text(element.title); + expect(child, findsOneWidget); + }); + + testWidgets('matches font size', (tester) async { + await tester.pumpWidget(widget); + final child = find.text(element.title); + final textWidget = tester.firstWidget(child) as Text; + expect(textWidget.style?.fontSize, element.fontSize); + }); + + testWidgets('matches font weight', (tester) async { + await tester.pumpWidget(widget); + final child = find.text(element.title); + final textWidget = tester.firstWidget(child) as Text; + expect(textWidget.style?.fontWeight, element.fontWeight); + }); + + testWidgets('matches font color', (tester) async { + await tester.pumpWidget(widget); + final child = find.text(element.title); + final textWidget = tester.firstWidget(child) as Text; + expect(textWidget.style?.color, element.color); + }); + }); + } + }); + }); +} + +class _DesignSpecification { + final String title; + final double fontSize; + final FontWeight fontWeight; + final Color color; + + const _DesignSpecification({ + required this.title, + required this.fontSize, + required this.color, + required this.fontWeight, + }); +} diff --git a/vehicle-tracker/packages/digit_components/test/widgets/atoms/digit_table_item_test.dart b/vehicle-tracker/packages/digit_components/test/widgets/atoms/digit_table_item_test.dart new file mode 100644 index 00000000..ef0ac543 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/widgets/atoms/digit_table_item_test.dart @@ -0,0 +1,30 @@ +import 'package:digit_components/widgets/atoms/digit_table_item.dart'; +import 'package:flutter_test/flutter_test.dart'; +import '../widget_app.dart'; + +void main() { + group( + 'DigitTableItem Test', + () { + testWidgets( + 'Widget is created without errors', + (widgetTester) async { + await widgetTester.pumpWidget( + const WidgetApp( + child: DigitTableItem( + content: 'Male', + index: 0, + isColored: true, + width: 140, + ), + ), + ); + expect( + find.widgetWithText(DigitTableItem, 'Male'), + findsOneWidget, + ); + }, + ); + }, + ); +} diff --git a/vehicle-tracker/packages/digit_components/test/widgets/atoms/digit_table_item_titile.dart b/vehicle-tracker/packages/digit_components/test/widgets/atoms/digit_table_item_titile.dart new file mode 100644 index 00000000..a4a0e286 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/widgets/atoms/digit_table_item_titile.dart @@ -0,0 +1,27 @@ +import 'package:digit_components/widgets/atoms/digit_table_item_title.dart'; +import 'package:flutter_test/flutter_test.dart'; +import '../widget_app.dart'; + +void main() { + group( + 'DigitTableItemTitle Test', + () { + testWidgets( + 'Widget is created without errors', + (widgetTester) async { + await widgetTester.pumpWidget( + const WidgetApp( + child: DigitTableItemTitle( + label: 'Title', + ), + ), + ); + expect( + find.widgetWithText(DigitTableItemTitle, 'Title'), + findsOneWidget, + ); + }, + ); + }, + ); +} diff --git a/vehicle-tracker/packages/digit_components/test/widgets/digit_dialog_test.dart b/vehicle-tracker/packages/digit_components/test/widgets/digit_dialog_test.dart new file mode 100644 index 00000000..19e0964c --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/widgets/digit_dialog_test.dart @@ -0,0 +1,164 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; + +import 'widget_app.dart'; + +class MockNavigatorObserver extends Mock implements NavigatorObserver {} + +class FakeRoute extends Fake implements Route {} + +class FakeDialogRoute extends Fake implements DialogRoute {} + +void main() { + group('Digit Dialog', () { + const testButton = 'Test Button'; + const alertTitle = 'Test title'; + const content = 'Dialog content'; + const primaryActionLabel = 'Primary'; + const secondaryActionLabel = 'Secondary'; + + Future buildTester( + WidgetTester widgetTester, { + MockNavigatorObserver? mockObserver, + void Function(BuildContext context)? primaryAction, + void Function(BuildContext context)? secondaryAction, + }) async { + await widgetTester.pumpWidget( + WidgetApp( + navigatorObserver: mockObserver, + child: Builder( + builder: (context) => ElevatedButton( + child: const Text(testButton), + onPressed: () => showDialog( + context: context, + builder: (_) => DigitDialog( + options: DigitDialogOptions( + title: const Text(alertTitle), + content: const Text(content), + primaryAction: DigitDialogActions( + label: primaryActionLabel, + action: primaryAction, + ), + secondaryAction: DigitDialogActions( + label: secondaryActionLabel, + action: secondaryAction, + ), + ), + ), + ), + ), + ), + ), + ); + + await widgetTester.tap(find.widgetWithText(ElevatedButton, testButton)); + await widgetTester.pumpAndSettle(); + } + + setUpAll(() { + registerFallbackValue(FakeRoute()); + registerFallbackValue(FakeDialogRoute()); + registerFallbackValue(FakeDialogRoute()); + }); + + testWidgets('is pushed on router', (widgetTester) async { + final mockObserver = MockNavigatorObserver(); + + await buildTester(widgetTester, mockObserver: mockObserver); + + verify(() => mockObserver.didPush(any(), any())); + }); + + testWidgets('executes primary action', (widgetTester) async { + bool primary = false; + + await buildTester( + widgetTester, + primaryAction: (context) => primary = !primary, + ); + + await widgetTester.tap( + find.widgetWithText(DigitElevatedButton, primaryActionLabel), + ); + + expect(primary, true); + }); + + testWidgets('executes secondary action', (widgetTester) async { + bool secondary = false; + + await buildTester( + widgetTester, + secondaryAction: (context) => secondary = !secondary, + ); + + await widgetTester.tap( + find.widgetWithText(TextButton, secondaryActionLabel), + ); + + expect(secondary, true); + }); + + testWidgets('has UI components', (widgetTester) async { + await buildTester( + widgetTester, + primaryAction: (context) {}, + secondaryAction: (context) {}, + ); + + expect(find.text(alertTitle), findsOneWidget); + expect(find.text(content), findsOneWidget); + + expect( + find.widgetWithText(DigitElevatedButton, primaryActionLabel), + findsOneWidget, + ); + expect( + find.widgetWithText(TextButton, secondaryActionLabel), + findsOneWidget, + ); + }); + + testWidgets('context builder renders dialog', (widgetTester) async { + final mockObserver = MockNavigatorObserver(); + bool primary = false; + + await widgetTester.pumpWidget( + WidgetApp( + navigatorObserver: mockObserver, + child: Builder( + builder: (context) => ElevatedButton( + onPressed: () => DigitDialog.show( + context, + options: DigitDialogOptions( + titleText: alertTitle, + contentText: content, + primaryAction: DigitDialogActions( + label: primaryActionLabel, + action: (context) => Navigator.of(context).pop(!primary), + ), + ), + ).then((value) { + if (value == null) return; + primary = value; + }), + child: const Text(testButton), + ), + ), + ), + ); + + await widgetTester.tap(find.widgetWithText(ElevatedButton, testButton)); + await widgetTester.pumpAndSettle(); + + verify(() => mockObserver.didPush(any>(), any())); + + await widgetTester.tap( + find.widgetWithText(DigitElevatedButton, primaryActionLabel), + ); + expect(primary, true); + }); + }); +} diff --git a/vehicle-tracker/packages/digit_components/test/widgets/digit_info_card_test.dart b/vehicle-tracker/packages/digit_components/test/widgets/digit_info_card_test.dart new file mode 100644 index 00000000..188c66c4 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/widgets/digit_info_card_test.dart @@ -0,0 +1,34 @@ +import 'package:digit_components/widgets/digit_info_card.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'widget_app.dart'; + +void main() { + group( + 'DigitInfoCard Test', + () { + testWidgets( + 'Widget is created without errors', + (widgetTester) async { + await widgetTester.pumpWidget( + const WidgetApp( + child: DigitInfoCard( + icon: Icons.info, + backgroundColor: Colors.white, + iconColor: Colors.black, + description: + 'Click on Register New Household button to add details.', + title: 'Match not found!', + ), + ), + ); + expect( + find.widgetWithText(DigitInfoCard, 'Match not found!'), + findsOneWidget, + ); + }, + ); + }, + ); +} diff --git a/vehicle-tracker/packages/digit_components/test/widgets/digit_outline_button_test.dart b/vehicle-tracker/packages/digit_components/test/widgets/digit_outline_button_test.dart new file mode 100644 index 00000000..4396c3d0 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/widgets/digit_outline_button_test.dart @@ -0,0 +1,35 @@ +import 'package:digit_components/widgets/digit_outline_button.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'widget_app.dart'; + +void main() { + group( + 'DigitOutLineButton Test', + () { + testWidgets( + 'Widget is created without errors', + (widgetTester) async { + bool primary = false; + await widgetTester.pumpWidget( + WidgetApp( + child: DigitOutLineButton( + label: 'Button', + onPressed: () { + primary = !primary; + }), + ), + ); + expect( + find.widgetWithText(DigitOutLineButton, 'Button'), + findsOneWidget, + ); + await widgetTester + .tap(find.widgetWithText(DigitOutLineButton, 'Button')); + await widgetTester.pumpAndSettle(); + expect(primary, true); + }, + ); + }, + ); +} diff --git a/vehicle-tracker/packages/digit_components/test/widgets/digit_search_bar_test.dart b/vehicle-tracker/packages/digit_components/test/widgets/digit_search_bar_test.dart new file mode 100644 index 00000000..650a5e01 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/widgets/digit_search_bar_test.dart @@ -0,0 +1,29 @@ +import 'package:digit_components/widgets/digit_search_bar.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'widget_app.dart'; + +void main() { + group( + 'DigitSearchBar Test', + () { + testWidgets( + 'Widget is created without errors', + (widgetTester) async { + await widgetTester.pumpWidget( + const WidgetApp( + child: DigitSearchBar( + hintText: 'Enter the name of household head', + ), + ), + ); + expect( + find.widgetWithText( + DigitSearchBar, 'Enter the name of household head'), + findsOneWidget, + ); + }, + ); + }, + ); +} diff --git a/vehicle-tracker/packages/digit_components/test/widgets/digit_sync_dialog.dart b/vehicle-tracker/packages/digit_components/test/widgets/digit_sync_dialog.dart new file mode 100644 index 00000000..1a09e80b --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/widgets/digit_sync_dialog.dart @@ -0,0 +1,191 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:digit_components/widgets/digit_sync_dialog.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; + +import 'widget_app.dart'; + +class MockNavigatorObserver extends Mock implements NavigatorObserver {} + +class FakeRoute extends Fake implements Route {} + +class FakeDialogRoute extends Fake implements DialogRoute {} + +void main() { + group('Digit Sync Dialog - InProgress', () { + const syncInProgressTitleText = 'Sync In Progress'; + const testButton = 'Test Button'; + + Future buildTester( + WidgetTester widgetTester, { + MockNavigatorObserver? mockObserver, + }) async { + await widgetTester.pumpWidget( + WidgetApp( + navigatorObserver: mockObserver, + child: Builder( + builder: (context) => ElevatedButton( + child: const Text(testButton), + onPressed: () { + DigitSyncDialog.show( + context, + type: DigitSyncDialogType.inProgress, + label: syncInProgressTitleText, + ); + }, + ), + ), + ), + ); + + await widgetTester.tap(find.widgetWithText(ElevatedButton, testButton)); + await widgetTester.pumpAndSettle(); + } + + setUpAll(() { + registerFallbackValue(FakeRoute()); + registerFallbackValue(FakeDialogRoute()); + registerFallbackValue(FakeDialogRoute()); + }); + + testWidgets('is pushed on router', (widgetTester) async { + final mockObserver = MockNavigatorObserver(); + + await buildTester(widgetTester, mockObserver: mockObserver); + + verify(() => mockObserver.didPush(any(), any())); + }); + + testWidgets('has UI components', (widgetTester) async { + await buildTester( + widgetTester, + ); + expect(find.text(syncInProgressTitleText), findsOneWidget); + expect(find.byIcon(Icons.autorenew), findsOneWidget); + }); + }); + + group('Digit Sync Dialog - SyncComplete', () { + const syncCompleteTitleText = 'Sync Completed'; + const testButton = 'Test Button'; + const syncCompleteButtonText = 'Close'; + Future buildTester( + WidgetTester widgetTester, { + MockNavigatorObserver? mockObserver, + }) async { + await widgetTester.pumpWidget(WidgetApp( + navigatorObserver: mockObserver, + child: Builder( + builder: (context) => ElevatedButton( + child: const Text(testButton), + onPressed: () { + DigitSyncDialog.show( + context, + type: DigitSyncDialogType.complete, + label: syncCompleteTitleText, + primaryAction: DigitDialogActions( + label: syncCompleteButtonText, + action: (_) {}, + ), + ); + }, + )), + )); + + await widgetTester.tap(find.widgetWithText(ElevatedButton, testButton)); + await widgetTester.pumpAndSettle(); + } + + setUpAll(() { + registerFallbackValue(FakeRoute()); + registerFallbackValue(FakeDialogRoute()); + registerFallbackValue(FakeDialogRoute()); + }); + + testWidgets('is pushed on router', (widgetTester) async { + final mockObserver = MockNavigatorObserver(); + + await buildTester(widgetTester, mockObserver: mockObserver); + + verify(() => mockObserver.didPush(any(), any())); + }); + + testWidgets('has required UI components', (widgetTester) async { + await buildTester( + widgetTester, + ); + expect(find.text(syncCompleteTitleText), findsOneWidget); + expect(find.byIcon(Icons.check_circle_outline), findsOneWidget); + expect(find.byType(DigitElevatedButton), findsOneWidget); + expect(find.text(syncCompleteButtonText), findsOneWidget); + }); + }); + + group('Digit Sync Dialog - SyncFailed', () { + const syncFailedTitleText = 'Sync Failed'; + const retryButtonText = 'Retry'; + const dismissButtonText = 'Dismiss'; + const testButton = 'Test Button'; + + Future buildTester( + WidgetTester widgetTester, { + MockNavigatorObserver? mockObserver, + }) async { + await widgetTester.pumpWidget( + WidgetApp( + navigatorObserver: mockObserver, + child: Builder( + builder: (context) => ElevatedButton( + child: const Text(testButton), + onPressed: () { + DigitSyncDialog.show( + context, + type: DigitSyncDialogType.failed, + label: syncFailedTitleText, + primaryAction: DigitDialogActions( + label: retryButtonText, + action: (_) {}, + ), + secondaryAction: DigitDialogActions( + label: dismissButtonText, + action: (_) {}, + ), + ); + }, + ), + ), + ), + ); + + await widgetTester.tap(find.widgetWithText(ElevatedButton, testButton)); + await widgetTester.pumpAndSettle(); + } + + setUpAll(() { + registerFallbackValue(FakeRoute()); + registerFallbackValue(FakeDialogRoute()); + registerFallbackValue(FakeDialogRoute()); + }); + + testWidgets('is pushed on router', (widgetTester) async { + final mockObserver = MockNavigatorObserver(); + + await buildTester(widgetTester, mockObserver: mockObserver); + + verify(() => mockObserver.didPush(any(), any())); + }); + + testWidgets('has required UI components', (widgetTester) async { + await buildTester( + widgetTester, + ); + expect(find.text(syncFailedTitleText), findsOneWidget); + expect(find.byIcon(Icons.error_outline), findsOneWidget); + expect(find.byType(DigitElevatedButton), findsOneWidget); + expect(find.text(retryButtonText), findsOneWidget); + expect(find.byType(TextButton), findsOneWidget); + expect(find.text(dismissButtonText), findsOneWidget); + }); + }); +} diff --git a/vehicle-tracker/packages/digit_components/test/widgets/molecules/digit_acknowledgement_test.dart b/vehicle-tracker/packages/digit_components/test/widgets/molecules/digit_acknowledgement_test.dart new file mode 100644 index 00000000..f33c9f8c --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/widgets/molecules/digit_acknowledgement_test.dart @@ -0,0 +1,101 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import '../widget_app.dart'; + +void main() { + group( + 'DigitAcknowledgement Test', + () { + late bool actionTriggered; + + setUp(() { + actionTriggered = false; + }); + + testWidgets( + 'Success Acknowledgement is created without errors', + (widgetTester) async { + await widgetTester.pumpWidget( + WidgetApp( + child: DigitAcknowledgement.success( + action: () => actionTriggered = !actionTriggered, + actionLabel: 'DIGIT_ACKNOWLEDGEMENT_ACTION_LABEL', + description: 'DIGIT_ACKNOWLEDGEMENT_DESCRIPTION', + label: 'DIGIT_ACKNOWLEDGEMENT_LABEL', + ), + ), + ); + + expect( + find.widgetWithText( + DigitAcknowledgement, + 'DIGIT_ACKNOWLEDGEMENT_LABEL', + ), + findsOneWidget, + ); + + expect( + find.widgetWithIcon( + DigitAcknowledgement, + Icons.check_circle, + ), + findsOneWidget, + ); + + expect(actionTriggered, false); + await widgetTester.tap( + find.widgetWithText( + DigitElevatedButton, + 'DIGIT_ACKNOWLEDGEMENT_ACTION_LABEL', + ), + ); + + expect(actionTriggered, true); + }, + ); + + testWidgets( + 'Error Acknowledgement is created without errors', + (widgetTester) async { + await widgetTester.pumpWidget( + WidgetApp( + child: DigitAcknowledgement.error( + action: () => actionTriggered = !actionTriggered, + actionLabel: 'DIGIT_ACKNOWLEDGEMENT_ACTION_LABEL', + description: 'DIGIT_ACKNOWLEDGEMENT_DESCRIPTION', + label: 'DIGIT_ACKNOWLEDGEMENT_LABEL', + ), + ), + ); + + expect( + find.widgetWithText( + DigitAcknowledgement, + 'DIGIT_ACKNOWLEDGEMENT_LABEL', + ), + findsOneWidget, + ); + + expect( + find.widgetWithIcon( + DigitAcknowledgement, + Icons.error, + ), + findsOneWidget, + ); + + expect(actionTriggered, false); + await widgetTester.tap( + find.widgetWithText( + DigitElevatedButton, + 'DIGIT_ACKNOWLEDGEMENT_ACTION_LABEL', + ), + ); + + expect(actionTriggered, true); + }, + ); + }, + ); +} diff --git a/vehicle-tracker/packages/digit_components/test/widgets/molecules/digit_language_card_test.dart b/vehicle-tracker/packages/digit_components/test/widgets/molecules/digit_language_card_test.dart new file mode 100644 index 00000000..39c9b722 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/widgets/molecules/digit_language_card_test.dart @@ -0,0 +1,77 @@ +import 'dart:convert'; +import 'package:digit_components/digit_components.dart'; +import 'package:digit_components/models/digit_row_card/digit_row_card_model.dart'; +import 'package:digit_components/widgets/molecules/digit_language_card.dart'; +import 'package:flutter_test/flutter_test.dart'; +import '../widget_app.dart'; + +const _target = """ + [ + { + "label": "ਪੰਜਾਬੀ", + "value": "pn_IN", + "isSelected": false + }, + { + "label": "ENGLISH", + "value": "en_IN", + "isSelected": true + } + ] + """; +void main() { + bool languageChangeTriggered = false; + bool languageChangeSubmitTriggered = false; + + final List list = json.decode(_target); + List languageList = + list.map((e) => DigitRowCardModel.fromJson(e)).toList(); + group('Digit Language Card ', () { + testWidgets('Widget is created without errors', (widgetTester) async { + await widgetTester.pumpWidget( + WidgetApp( + child: DigitLanguageCard( + digitRowCardItems: languageList, + languageSubmitLabel: 'Continue', + onLanguageSubmit: () => languageChangeSubmitTriggered = + !languageChangeSubmitTriggered, + onLanguageChange: (data) { + languageChangeTriggered = !languageChangeTriggered; + }), + ), + ); + + expect( + find.widgetWithText( + DigitLanguageCard, + 'Continue', + ), + findsOneWidget, + ); + +// Test case for LanguageChange Button + await widgetTester.tap( + find.text( + 'ENGLISH', + ), + ); + + await widgetTester.pumpAndSettle(); + expect( + languageChangeTriggered, + true, + ); + +// Test case for Submit Button + await widgetTester.tap( + find.text('Continue'), + ); + + await widgetTester.pumpAndSettle(); + expect( + languageChangeSubmitTriggered, + true, + ); + }); + }); +} diff --git a/vehicle-tracker/packages/digit_components/test/widgets/molecules/digit_row_card_test.dart b/vehicle-tracker/packages/digit_components/test/widgets/molecules/digit_row_card_test.dart new file mode 100644 index 00000000..1e296f24 --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/widgets/molecules/digit_row_card_test.dart @@ -0,0 +1,69 @@ +import 'dart:convert'; +import 'package:digit_components/models/digit_row_card/digit_row_card_model.dart'; +import 'package:digit_components/widgets/digit_row_card/digit_row_card.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../widget_app.dart'; + +const _target = """ + [ + { + "label": "ਪੰਜਾਬੀ", + "value": "pn_IN", + "isSelected": false + }, + { + "label": "ENGLISH", + "value": "en_IN", + "isSelected": true + } + ] + """; +void main() { + group('Digit Row card widget', () { + final List list = json.decode(_target); + List languageList = + list.map((e) => DigitRowCardModel.fromJson(e)).toList(); + testWidgets('Widget is created without errors', (widgetTester) async { + bool primary = false; + + onPressed(data) { + primary = !primary; + } + + await widgetTester.pumpWidget(WidgetApp( + child: DigitRowCard( + rowItems: languageList, + onChanged: (data) => onPressed(data), + width: 90, + ))); + + expect( + find.widgetWithText(DigitRowCard, 'ENGLISH'), + findsOneWidget, + ); + }); + + testWidgets('DigitRowcard widget OnTap', (widgetTester) async { + bool primary = false; + + onPressed(data) { + primary = !primary; + } + + await widgetTester.pumpWidget(WidgetApp( + child: DigitRowCard( + rowItems: languageList, + onChanged: (data) => onPressed(data), + width: 90, + ))); + + await widgetTester.pumpAndSettle(); + await widgetTester.tap(find.widgetWithText(Center, 'ENGLISH')); + await widgetTester.pumpAndSettle(); + expect(primary, true); + }); + }); +} diff --git a/vehicle-tracker/packages/digit_components/test/widgets/powered_by_digit_test.dart b/vehicle-tracker/packages/digit_components/test/widgets/powered_by_digit_test.dart new file mode 100644 index 00000000..8328addf --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/widgets/powered_by_digit_test.dart @@ -0,0 +1,24 @@ +import 'package:digit_components/digit_components.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'widget_app.dart'; + +void main() { + group('Powered by Digit widget', () { + testWidgets('Widget is created without errors', (widgetTester) async { + await widgetTester.pumpWidget(const WidgetApp(child: PoweredByDigit())); + + expect( + find.widgetWithImage( + PoweredByDigit, + const AssetImage( + 'assets/images/powered_by_digit.png', + package: 'digit_components', + ), + ), + findsOneWidget, + ); + }); + }); +} diff --git a/vehicle-tracker/packages/digit_components/test/widgets/widget_app.dart b/vehicle-tracker/packages/digit_components/test/widgets/widget_app.dart new file mode 100644 index 00000000..58d6107a --- /dev/null +++ b/vehicle-tracker/packages/digit_components/test/widgets/widget_app.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; + +class WidgetApp extends StatelessWidget { + final Widget child; + final NavigatorObserver? navigatorObserver; + + const WidgetApp({ + super.key, + required this.child, + this.navigatorObserver, + }); + + @override + Widget build(BuildContext context) => MaterialApp( + navigatorObservers: [if (navigatorObserver != null) navigatorObserver!], + home: Scaffold(body: child), + ); +} diff --git a/vehicle-tracker/vehicle_tracker_app/android/app/build.gradle b/vehicle-tracker/vehicle_tracker_app/android/app/build.gradle index b965d21f..afbe308b 100644 --- a/vehicle-tracker/vehicle_tracker_app/android/app/build.gradle +++ b/vehicle-tracker/vehicle_tracker_app/android/app/build.gradle @@ -48,7 +48,7 @@ android { applicationId "com.example.vehicle_tracker_app" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdkVersion flutter.minSdkVersion + minSdkVersion 18 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/vehicle-tracker/vehicle_tracker_app/assets/images/not_found.svg b/vehicle-tracker/vehicle_tracker_app/assets/images/not_found.svg new file mode 100644 index 00000000..ba16372c --- /dev/null +++ b/vehicle-tracker/vehicle_tracker_app/assets/images/not_found.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vehicle-tracker/vehicle_tracker_app/lib/blocs/home/controllers/info_controllers.dart b/vehicle-tracker/vehicle_tracker_app/lib/blocs/home/controllers/info_controllers.dart index 26281061..1c5f8484 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/blocs/home/controllers/info_controllers.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/blocs/home/controllers/info_controllers.dart @@ -7,6 +7,7 @@ import 'package:vehicle_tracker_app/blocs/home/repository/home_http_repository.d import 'package:vehicle_tracker_app/constants.dart'; import 'package:vehicle_tracker_app/data/secure_storage_service.dart'; import 'package:vehicle_tracker_app/models/home_trip/home_trip_model/home_trip_model.dart'; +import 'package:vehicle_tracker_app/router/routes.dart'; import 'package:vehicle_tracker_app/util/logout.dart'; class InfoController extends GetxController { @@ -37,8 +38,8 @@ class InfoController extends GetxController { logout(); return; } - - await fillList(tenantId, operatorId); + final selectedCity= await SecureStorageService.read(CITYCODE); + await fillList(selectedCity!, operatorId); } // ? It will get the trip data and filter the data based on the status. @@ -47,7 +48,7 @@ class InfoController extends GetxController { isLoading.toggle(); // ! For now we are hardcoding the city id as "pg.citya" - final totalList = await homeHTTPRepository.getHomeTripData("pg.citya", operatorId); + final totalList = await homeHTTPRepository.getHomeTripData(tentantId, operatorId); normalTripList.value = totalList.where((element) { return element.value.status != TripStates.COMPLETED; @@ -114,4 +115,4 @@ class InfoController extends GetxController { }).toList(); } } -} +} \ No newline at end of file diff --git a/vehicle-tracker/vehicle_tracker_app/lib/blocs/home/controllers/trip_tracker_controllers.dart b/vehicle-tracker/vehicle_tracker_app/lib/blocs/home/controllers/trip_tracker_controllers.dart index 6d63cc4b..b6350e70 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/blocs/home/controllers/trip_tracker_controllers.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/blocs/home/controllers/trip_tracker_controllers.dart @@ -19,48 +19,94 @@ import 'package:vehicle_tracker_app/util/trip_tracker_utility.dart'; import 'package:wakelock/wakelock.dart'; class TripControllers extends GetxController { - final BuildContext context; + static final TripControllers _singleton = TripControllers._internal(); - RxBool isRunning = false.obs; // This variable is to check if the tracking is running or not - RxBool isLoading = false.obs; // This variable is to check if startTracking is loading or not + factory TripControllers() { + return _singleton; + } + + TripControllers._internal(); + + RxBool isRunning = + false.obs; // This variable is to check if the tracking is running or not + RxBool isLoading = + false.obs; // This variable is to check if startTracking is loading or not HomeHTTPRepository homeHTTPRepository = HomeHTTPRepository(); HomeHiveRepository homeHiveRepository = HomeHiveRepository(); TripTrackerUtility tripTrackerUtility = TripTrackerUtility(); InfoController infoController = Get.find(); - TripControllers(this.context); - // * This function starts the tracking peroiodic event Future startTracking(Rx data) async { log('---- Trip and Tracking started ----'); log("Start TRIP API"); - final status = await homeHTTPRepository.updateTrip(data.value, TripStates.ONGOING); + final status = + await homeHTTPRepository.updateTrip(data.value, TripStates.ONGOING); if (!status) { - toaster(null, AppTranslation.TRIP_NOT_STARTED_MESSAGE.tr, isError: true); + toaster(AppTranslation.TRIP_NOT_STARTED_MESSAGE.tr, isError: true); data.value.status = TripStates.NOTSTARTED; update([data.value.id]); return; } - toaster(null, AppTranslation.TRIP_STARTED_SUCCESFULLY_MESSAGE.tr, isError: false); + toaster(AppTranslation.TRIP_STARTED_SUCCESFULLY_MESSAGE.tr, isError: false); data.value.status = TripStates.ONGOING; update([data.value.id]); // Calls the periodic function startPeriodicFunction(data.value); + + // Start tracking immediately + trackerLogic("In Progress", data.value); + } + + //send the positions stored in local storage to the server + Future sendStoredPositions(HomeTripModel trip) async { + log("Sending stored positions to server"); + final isConnected = await tripTrackerUtility.isConnected(); + if (!isConnected) { + log("No internet connection"); + return; + } + + await trackerLogic('Completed', trip); + + final List positions = homeHiveRepository.getTripData(); + if (positions.isEmpty) { + log("No positions to send"); + return; + } else { + log("Sending positions to server"); + final status = + await homeHTTPRepository.updateTripProgress(trip, positions); + if (status) { + log("Positions sent successfully"); + await homeHiveRepository.deleteTripData(); + toaster(AppTranslation.POSITION_SENT_MESSAGE.tr); + } else { + log("Error sending positions"); + toaster(AppTranslation.POSITION_HIVE_STORE_MESSAGE.tr, isError: true); + } + } } // ? This functions starts a timer which will call the trackerLogic function every n seconds // ? The timer will stop if the isRunning variable is false // ? The main point on this function is to get and send tracker function like a cron schedule + Timer? _timer; + void startPeriodicFunction(HomeTripModel trip) { log('Periodic function started'); isRunning.value = true; - Timer.periodic(Duration(seconds: periodicTrackingFrequency), (_) async { + // Cancel the existing timer if it's running + _timer?.cancel(); + + _timer = + Timer.periodic(Duration(seconds: periodicTrackingFrequency), (_) async { log("Periodic function called"); if (!isRunning.value) { log("Periodic function stopped"); @@ -75,7 +121,8 @@ class TripControllers extends GetxController { // ? If the location permissions are not granted, the function will stop and return early // ? If the location permissions are granted, the function will get the current location and use it accordingly Future trackerLogic(String alert, HomeTripModel trip) async { - bool permissions = await tripTrackerUtility.handleLocationPermission(Get.context); + bool permissions = + await tripTrackerUtility.handleLocationPermission(Get.context); if (!permissions) { isRunning.value = false; log('Location permissions not granted'); @@ -101,7 +148,8 @@ class TripControllers extends GetxController { // ? It will check if the device is connected to internet or not // ? If there is internet connection, it will send the data to server // ? If by any chance the data sending fails, it will store the data to hive - Future positionSender(Position? position, String alert, HomeTripModel trip) async { + Future positionSender( + Position? position, String alert, HomeTripModel trip) async { TripHiveModel tripHiveModel = TripHiveModel( latitude: position?.latitude ?? 0, longitude: position?.longitude ?? 0, @@ -121,11 +169,12 @@ class TripControllers extends GetxController { // if success delete the hive data // else save the data to hive log("Sending position to server"); - final status = await homeHTTPRepository.updateTripProgress(trip, positions); + final status = + await homeHTTPRepository.updateTripProgress(trip, positions); if (status) { log("Position sent successfully"); await homeHiveRepository.deleteTripData(); - toaster(null, AppTranslation.POSITION_SENT_MESSAGE.tr); + toaster(AppTranslation.POSITION_SENT_MESSAGE.tr); return status; } else { // If the position sending fails, save the data to hive @@ -137,7 +186,7 @@ class TripControllers extends GetxController { // If not connected to internet, save the data to hive log("No internet connection, saving to hive"); await homeHiveRepository.storeTripData(tripHiveModel); - toaster(null, AppTranslation.POSITION_HIVE_STORE_MESSAGE.tr); + toaster(AppTranslation.POSITION_HIVE_STORE_MESSAGE.tr); return false; } } @@ -147,7 +196,6 @@ class TripControllers extends GetxController { bool spamChecker(BuildContext context) { if (isLoading.isTrue) { toaster( - context, AppTranslation.START_LOADING_MESSAGE.tr, isError: true, ); @@ -186,15 +234,16 @@ class TripControllers extends GetxController { Get.back(); - final status = await homeHTTPRepository.updateTrip(data.value, TripStates.COMPLETED); + final status = + await homeHTTPRepository.updateTrip(data.value, TripStates.COMPLETED); if (!status) { data.value.status = TripStates.ONGOING; update([data.value.id]); - toaster(null, AppTranslation.TRIP_NOT_END_MESSAGE.tr, isError: true); + toaster(AppTranslation.TRIP_NOT_END_MESSAGE.tr, isError: true); return; } - toaster(null, AppTranslation.TRIP_ENDED_SUCCESFULLY_MESSAGE.tr, isError: false); + toaster(AppTranslation.TRIP_ENDED_SUCCESFULLY_MESSAGE.tr, isError: false); log("Deleting trip data from hive"); await homeHiveRepository.deleteTripData(); diff --git a/vehicle-tracker/vehicle_tracker_app/lib/blocs/home/repository/home_http_repository.dart b/vehicle-tracker/vehicle_tracker_app/lib/blocs/home/repository/home_http_repository.dart index 589bc2c2..d507c135 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/blocs/home/repository/home_http_repository.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/blocs/home/repository/home_http_repository.dart @@ -7,22 +7,26 @@ import 'package:vehicle_tracker_app/models/home_trip/home_trip_model/home_trip_m import 'package:vehicle_tracker_app/models/trip/trip_tracker_info/trip_tracker_hive_model.dart'; import 'package:vehicle_tracker_app/util/i18n_translations.dart'; import 'package:vehicle_tracker_app/util/toaster.dart'; +import 'package:vehicle_tracker_app/blocs/home/controllers/trip_tracker_controllers.dart' + as send_local_data; import '../../../data/secure_storage_service.dart'; class HomeHTTPRepository { // ? Uses the userId to get the list of trips. - Future>> getHomeTripData(String tenantId, String operatorId) async { + Future>> getHomeTripData( + String tenantId, String operatorId) async { List> homeTripModel = []; - String reqUrl = "$apiUrl/trip/_search?operatorId=$operatorId&tenantId=$tenantId"; + String reqUrl = + "$apiUrl/trip/_search?operatorId=$operatorId&tenantId=$tenantId"; final response = await HttpService.getRequest(reqUrl); if (response.statusCode != 200) { log("Error Code: ${response.statusCode}"); log("Error: ${response.body}"); - toaster(Get.context, AppTranslation.NETWORK_ERROR_MESSAGE.tr, isError: true); + toaster(AppTranslation.NETWORK_ERROR_MESSAGE.tr, isError: true); return homeTripModel; } @@ -32,10 +36,12 @@ class HomeHTTPRepository { homeTripModel.add(Rx(HomeTripModel.fromJson(item))); } } on FormatException catch (e) { - toaster(Get.context, AppTranslation.NETWORK_ERROR_MESSAGE.tr, isError: true, error: e.message); + toaster(AppTranslation.NETWORK_ERROR_MESSAGE.tr, + isError: true, error: e.message); homeTripModel.clear(); } on Exception catch (e) { - toaster(Get.context, AppTranslation.NETWORK_ERROR_MESSAGE.tr, isError: true, error: e.toString()); + toaster(AppTranslation.NETWORK_ERROR_MESSAGE.tr, + isError: true, error: e.toString()); homeTripModel.clear(); } @@ -45,7 +51,8 @@ class HomeHTTPRepository { // ? API to start and end the Trip // ? If start is true, then the trip will start // ? If start is false, then the trip will end - Future updateTrip(HomeTripModel data, String status, {String? tenantId}) async { + Future updateTrip(HomeTripModel data, String status, + {String? tenantId}) async { String reqUrl = "$apiUrl/trip/_update"; final operatorId = await SecureStorageService.read(OPERATOR_ID); @@ -59,6 +66,8 @@ class HomeHTTPRepository { log("URL: $reqUrl"); log("Body: $body"); + await send_local_data.TripControllers().sendStoredPositions(data); + final response = await HttpService.putRequest(reqUrl, body); // ? If the response is null OR not 200, then return false. @@ -74,7 +83,8 @@ class HomeHTTPRepository { } // ? API to update the trip progress - Future updateTripProgress(HomeTripModel data, List positions) async { + Future updateTripProgress( + HomeTripModel data, List positions) async { String reqUrl = "$apiUrl/trip/_progress"; final operatorId = await SecureStorageService.read(OPERATOR_ID); @@ -114,14 +124,16 @@ class HomeHTTPRepository { } // ? API to create a new POI - Future callTrackingApi(List positions, String alert, String tripId) async { + Future callTrackingApi( + List positions, String alert, String tripId) async { String reqUrl = "$apiUrl/poi/_create"; final operatorId = await SecureStorageService.read(OPERATOR_ID); List> latLong = []; for (var position in positions) { - latLong.add({"latitude": position.latitude, "longitude": position.longitude}); + latLong.add( + {"latitude": position.latitude, "longitude": position.longitude}); } Map body = { diff --git a/vehicle-tracker/vehicle_tracker_app/lib/blocs/login/controllers/login_controllers.dart b/vehicle-tracker/vehicle_tracker_app/lib/blocs/login/controllers/login_controllers.dart index cdb3e5a1..531b61c9 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/blocs/login/controllers/login_controllers.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/blocs/login/controllers/login_controllers.dart @@ -6,19 +6,32 @@ import 'package:vehicle_tracker_app/constants.dart'; import 'package:vehicle_tracker_app/router/routes.dart'; import 'package:vehicle_tracker_app/util/i18n_translations.dart'; +import '../../../data/secure_storage_service.dart'; + class LoginController extends GetxController { TextEditingController userNameController = TextEditingController(); TextEditingController passwordController = TextEditingController(); - String city = cities.keys.first; + TextEditingController cityController = TextEditingController(); + + RxBool isLoading = false.obs; + void navgiateTocity(context) async { + isLoading.value = false; + Get.toNamed(SELECTCITY); + } + + void login() async { + isLoading.value = true; + final data = await SecureStorageService.read(CITYCODE); + await SecureStorageService.write(CITYCODE, cityController.text); - void login(context) async { final isLogin = await LoginHTTPRepository.login( - context, userNameController.text, passwordController.text, - cities[city] ?? "", + cityController.text, ); + isLoading.value = false; + if (isLogin) { Get.offAllNamed(HOME); } @@ -32,7 +45,23 @@ class LoginController extends GetxController { titleText: AppTranslation.FORGOT_PASSWORD.tr, titleIcon: const Icon(Icons.warning_rounded, color: Colors.red), contentText: AppTranslation.FORGOT_PASSWORD_MESSAGE.tr, - primaryAction: DigitDialogActions(label: AppTranslation.OK.tr, action: (context) => Get.back())), + primaryAction: DigitDialogActions( + label: AppTranslation.OK.tr, action: (context) => Get.back())), ); } + + void sendOTP(context) async { + isLoading.value = true; + + final isSent = await LoginHTTPRepository.sendOtp(context, + mobileNumber: userNameController.text); + + if (isSent) { + if (Get.currentRoute != OTP) { + Get.toNamed(OTP); + } + } else { + isLoading.value = false; + } + } } diff --git a/vehicle-tracker/vehicle_tracker_app/lib/blocs/login/repository/login_http_reposotry.dart b/vehicle-tracker/vehicle_tracker_app/lib/blocs/login/repository/login_http_reposotry.dart index de689185..302ba4b5 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/blocs/login/repository/login_http_reposotry.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/blocs/login/repository/login_http_reposotry.dart @@ -14,7 +14,38 @@ import '../../../util/i18n_translations.dart'; import '../../../util/toaster.dart'; class LoginHTTPRepository { - static Future login(BuildContext context, String username, String password, String city) async { +// sendOtp + + static Future sendOtp(BuildContext context, + {required String mobileNumber}) async { + try { + final sendOtpUrl = "$unifiedDevApiUrl/user-otp/v1/_send"; + + Map formData = { + "otp": { + "mobileNumber": mobileNumber, + "tenantId": "pg", + "type": "login", + "userType": "citizen" + } + }; + + final response = await HttpService.postRequest(sendOtpUrl, formData); + if (response.statusCode != 200) { + log("Error Code: ${response.statusCode}"); + toaster(AppTranslation.LOGIN_FAILED_MESSAGE.tr, isError: true); + return false; + } + return response.body['isSuccessful'] as bool; + } catch (e) { + return false; + } + } + +// + + static Future login(String username, + String password, String city) async { try { final loginUrl = "$unifiedDevApiUrl/user/oauth/token"; @@ -23,53 +54,59 @@ class LoginHTTPRepository { "scope": "read", "username": username.trim(), "password": password.trim(), - "userType": "EMPLOYEE", + "userType": "citizen", "tenantId": city, }; final response = await HttpService.postWithFormData(loginUrl, formData); if (response.statusCode != 200) { log("Error Code: ${response.statusCode}"); - toaster(context, AppTranslation.LOGIN_FAILED_MESSAGE.tr, isError: true); + toaster(AppTranslation.LOGIN_FAILED_MESSAGE.tr, isError: true); return false; } final loginModel = LoginDataModel.fromJson(response.body); - - final driverId = await getDriverId(loginModel.access_token, loginModel.UserRequest.uuid, "pg.citya"); + final data = await SecureStorageService.read(CITYCODE); + final driverId = await getDriverId( + loginModel.access_token, loginModel.UserRequest.uuid, data.toString(), + mobileNumber: username.trim()); if (driverId == "") { - toaster(context, AppTranslation.LOGIN_FAILED_MESSAGE.tr, isError: true); + toaster(AppTranslation.LOGIN_FAILED_MESSAGE.tr, isError: true); return false; } await SecureStorageService.writeAll( token: loginModel.access_token, uuid: loginModel.UserRequest.uuid, - tenantId: loginModel.UserRequest.tenantId, + tenantId: data.toString(), operatorId: driverId, ); - await HiveService.addUserData(loginModel.UserRequest.name, loginModel.UserRequest.mobileNumber); + await HiveService.addUserData( + loginModel.UserRequest.name, loginModel.UserRequest.mobileNumber); - toaster(null, AppTranslation.LOGIN_SUCCESS_MESSAGE.tr); + toaster(AppTranslation.LOGIN_SUCCESS_MESSAGE.tr, isError: false); return true; } on FormatException catch (e) { log("Error: ${e.message}"); - toaster(context, AppTranslation.LOGIN_FAILED_MESSAGE.tr, isError: true); + toaster(AppTranslation.LOGIN_FAILED_MESSAGE.tr, isError: true); return false; } on Exception catch (e) { log("Error: ${e.toString()}"); - toaster(context, AppTranslation.LOGIN_FAILED_MESSAGE.tr, isError: true); + toaster(AppTranslation.LOGIN_FAILED_MESSAGE.tr, isError: true); return false; } } - static Future getDriverId(String authToken, String uuid, String tenantId) async { + static Future getDriverId( + String authToken, String uuid, String tenantId, + {required String mobileNumber}) async { try { - final url = "$unifiedDevApiUrl/vendor/driver/v1/_search"; - final loginUrl = "$url?tenantId=$tenantId&ownerIds=$uuid"; + final url = "$unifiedDevApiUrl/individual/v1/_search"; + final loginUrl = "$url?tenantId=$tenantId&offset=0&limit=1"; Map body = { + "Individual": {"mobileNumber": mobileNumber}, "RequestInfo": { "apiId": "Rainmaker", "authToken": authToken, @@ -78,13 +115,13 @@ class LoginHTTPRepository { final response = await HttpService.postRequest(loginUrl, body); if (response.statusCode != 200) { - log("Error in getting driver id : ${response.statusCode}"); + log("Error in getting Individual id : ${response.statusCode}"); return ""; } - return response.body["driver"][0]["id"]; + return response.body["Individual"][0]["id"]; } catch (e) { - log("Error in getting driver id : ${e.toString()}"); + log("Error in getting Individual id : ${e.toString()}"); return ""; } } diff --git a/vehicle-tracker/vehicle_tracker_app/lib/constants.dart b/vehicle-tracker/vehicle_tracker_app/lib/constants.dart index 34528ba5..1e433c9f 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/constants.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/constants.dart @@ -9,13 +9,8 @@ final String mdmsUrl = dotenv.env["MDMS_URL"] ?? ""; final int periodicTrackingFrequency = int.parse(dotenv.env["PERIODIC_TRACKING_FREQUENCY"] ?? "10"); final String unifiedDevApiUrl = dotenv.env["UNIFIED_DEV_API_URL"] ?? ""; -const Map cities = { - "PG": "pg", - "Amritsar": "pb.amritsar", - "City A": "pg.citya", -}; -final List cityNames = cities.keys.toList(); + const String TOKEN = "token"; const String UUID = "uuid"; @@ -23,6 +18,7 @@ const String TENANT_ID = "tenantId"; const String OPERATOR_ID = "operatorId"; const String NAME = "name"; const String MOBILE_NUMBER = "mobileNumber"; +const String CITYCODE="cityCode"; const List hiveBoxes = ["en_IN", "or_IN", "mdms", "tracker", "user"]; diff --git a/vehicle-tracker/vehicle_tracker_app/lib/data/hive_service.dart b/vehicle-tracker/vehicle_tracker_app/lib/data/hive_service.dart index 8ebff886..688cd220 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/data/hive_service.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/data/hive_service.dart @@ -58,13 +58,13 @@ class HiveService { } // ? For storing of MDMS data into Hive - static Future> storeMdmsData(MdmsModel mdmsModel) async { + static Future> storeMdmsData(MdmsResponse mdmsModel) async { List mdmsHiveModelList = []; // Loops through all the StateInfo for lanuage - for (var item in mdmsModel.StateInfo) { + for (var item in mdmsModel!.mdmsRes!.commonMasters!.stateInfo!) { List languageHiveModelList = []; - for (var language in item.languages) { + for (var language in item!.languages!) { languageHiveModelList.add(LanguageHiveModel( label: language.label, value: language.value, @@ -72,11 +72,21 @@ class HiveService { } mdmsHiveModelList.add(MdmsHiveModel( - name: item.name, - code: item.code, + name: item.name!, + code: item.code!, languages: languageHiveModelList, + cityHive: [], )); } + List cityHiveModel=[]; + for (var element in mdmsModel!.mdmsRes!.tenant!.tenants!) { + + + + cityHiveModel.add(CityHiveModel(cityCode: element.code!, cityName: element.city!.name!)); + } + + mdmsHiveModelList.first.cityHive.addAll(cityHiveModel); await Hive.box("mdms").addAll(mdmsHiveModelList); @@ -92,4 +102,6 @@ class HiveService { static deleteMdmsData() async { await Hive.box("mdms").clear(); } -} + + +} \ No newline at end of file diff --git a/vehicle-tracker/vehicle_tracker_app/lib/data/http_service.dart b/vehicle-tracker/vehicle_tracker_app/lib/data/http_service.dart index 9dc45194..b18da9f2 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/data/http_service.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/data/http_service.dart @@ -58,9 +58,10 @@ class HttpService { }, body: body, ); - if (response.statusCode == 200) { + if (response.statusCode == 200||response.statusCode == 201) { var body = json.decode(response.body); - return Response(body: body, statusCode: response.statusCode); + + return Response(body: body, statusCode: response.statusCode==201?200:200); } else if (response.statusCode == 401) { logout(); return const Response(body: null, statusCode: 401); @@ -113,10 +114,64 @@ class HttpService { } static Future getRequestWithoutToken(String url) async { + + final data= { + "MdmsCriteria": { + "tenantId": "pg", + "moduleDetails": [ + { + "moduleName": "common-masters", + "masterDetails": [ + { + "name": "Department" + }, + { + "name": "Designation" + }, + { + "name": "StateInfo" + }, + { + "name": "wfSlaConfig" + }, + { + "name": "uiHomePage" + } + ] + }, + { + "moduleName": "tenant", + "masterDetails": [ + { + "name": "tenants" + }, + { + "name": "citymodule" + } + ] + }, + { + "moduleName": "DIGIT-UI", + "masterDetails": [ + { + "name": "ApiCachingSettings" + } + ] + } + ] + }, + "RequestInfo": { + "apiId": "Rainmaker", + "msgId": "1706591204091|en_IN", + "plainAccessRequest": {} + } + }; try { - var response = await http.get(Uri.parse(url), headers: { + var response = await http.post(Uri.parse(url), headers: { 'Content-Type': 'application/json', - }); + }, + body:jsonEncode(data) + ); if (response.statusCode == 200) { var body = json.decode(response.body); return Response(body: body, statusCode: response.statusCode); @@ -174,4 +229,4 @@ class HttpService { return const Response(body: null, statusCode: 500); } } -} +} \ No newline at end of file diff --git a/vehicle-tracker/vehicle_tracker_app/lib/data/mdms_service.dart b/vehicle-tracker/vehicle_tracker_app/lib/data/mdms_service.dart index 9ffb57ac..2f5e3838 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/data/mdms_service.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/data/mdms_service.dart @@ -1,6 +1,5 @@ import 'dart:developer'; -import 'package:vehicle_tracker_app/constants.dart'; import 'package:vehicle_tracker_app/data/hive_service.dart'; import '../models/mdms/mdms_hive/mdms_hive_model.dart'; @@ -34,15 +33,16 @@ class MdmsService { } } - static Future callMdmsAPI() async { - + static Future callMdmsAPI() async { - var response = await HttpService.getRequestWithoutToken(mdmsUrl); + const url= "https://unified-dev.digit.org/egov-mdms-service/v1/_search?tenantId=pg"; + + var response = await HttpService.getRequestWithoutToken(url); if (response.statusCode == 200) { Map json = response.body; - return MdmsModel.fromJson(json); + return MdmsResponse.fromJson(json); } else { return null; } } -} +} \ No newline at end of file diff --git a/vehicle-tracker/vehicle_tracker_app/lib/data/secure_storage_service.dart b/vehicle-tracker/vehicle_tracker_app/lib/data/secure_storage_service.dart index ab5b0781..b3285322 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/data/secure_storage_service.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/data/secure_storage_service.dart @@ -25,6 +25,7 @@ class SecureStorageService { delete(UUID), delete(TENANT_ID), delete(OPERATOR_ID), + delete(CITYCODE) ]); log("All data deleted from secure storage"); @@ -45,4 +46,4 @@ class SecureStorageService { log("All data written to secure storage"); } -} +} \ No newline at end of file diff --git a/vehicle-tracker/vehicle_tracker_app/lib/main.dart b/vehicle-tracker/vehicle_tracker_app/lib/main.dart index 8d877019..2a60ec2f 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/main.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/main.dart @@ -62,10 +62,11 @@ class MyApp extends StatelessWidget { // Common function to register all the Hive adapters registerAdaptersFunc() { - // For Localization + // For Localization Hive.registerAdapter(LocalizationHiveModelAdapter()); // For MDMS data + Hive.registerAdapter(CityHiveModelAdapter()); Hive.registerAdapter(MdmsHiveModelAdapter()); Hive.registerAdapter(LanguageHiveModelAdapter()); diff --git a/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_hive/mdms_hive_model.dart b/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_hive/mdms_hive_model.dart index 89a16935..dc708bb8 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_hive/mdms_hive_model.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_hive/mdms_hive_model.dart @@ -1,3 +1,4 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first import 'package:hive/hive.dart'; part 'mdms_hive_model.g.dart'; @@ -13,10 +14,14 @@ class MdmsHiveModel extends HiveObject { @HiveField(2) List languages; + @HiveField(3) + List cityHive; + MdmsHiveModel({ required this.name, required this.code, required this.languages, + required this.cityHive, }); } @@ -33,3 +38,20 @@ class LanguageHiveModel extends HiveObject { required this.value, }); } + +@HiveType(typeId:5) +class CityHiveModel extends HiveObject { + + + @HiveField(0) + String cityCode; + + @HiveField(1) + String cityName; + + CityHiveModel({ + required this.cityCode, + required this.cityName, + }); + +} \ No newline at end of file diff --git a/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_hive/mdms_hive_model.g.dart b/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_hive/mdms_hive_model.g.dart index aa11f4f0..295bab68 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_hive/mdms_hive_model.g.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_hive/mdms_hive_model.g.dart @@ -20,19 +20,22 @@ class MdmsHiveModelAdapter extends TypeAdapter { name: fields[0] as String, code: fields[1] as String, languages: (fields[2] as List).cast(), + cityHive: (fields[3] as List).cast(), ); } @override void write(BinaryWriter writer, MdmsHiveModel obj) { writer - ..writeByte(3) + ..writeByte(4) ..writeByte(0) ..write(obj.name) ..writeByte(1) ..write(obj.code) ..writeByte(2) - ..write(obj.languages); + ..write(obj.languages) + ..writeByte(3) + ..write(obj.cityHive); } @override @@ -82,3 +85,40 @@ class LanguageHiveModelAdapter extends TypeAdapter { runtimeType == other.runtimeType && typeId == other.typeId; } + +class CityHiveModelAdapter extends TypeAdapter { + @override + final int typeId = 5; + + @override + CityHiveModel read(BinaryReader reader) { + final numOfFields = reader.readByte(); + final fields = { + for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), + }; + return CityHiveModel( + cityCode: fields[0] as String, + cityName: fields[1] as String, + ); + } + + @override + void write(BinaryWriter writer, CityHiveModel obj) { + writer + ..writeByte(2) + ..writeByte(0) + ..write(obj.cityCode) + ..writeByte(1) + ..write(obj.cityName); + } + + @override + int get hashCode => typeId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is CityHiveModelAdapter && + runtimeType == other.runtimeType && + typeId == other.typeId; +} diff --git a/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_model/mdms_model.dart b/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_model/mdms_model.dart index 318004bd..834e9106 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_model/mdms_model.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_model/mdms_model.dart @@ -5,37 +5,76 @@ import 'package:freezed_annotation/freezed_annotation.dart'; part 'mdms_model.freezed.dart'; part 'mdms_model.g.dart'; + @freezed -class MdmsModel with _$MdmsModel { - const factory MdmsModel({ - required String tenantId, - required String moduleName, - required List StateInfo, - }) = _MdmsModel; +class MdmsResponse with _$MdmsResponse { + + factory MdmsResponse({ + + @JsonKey(name: "MdmsRes") + + MdmsRes? mdmsRes, - factory MdmsModel.fromJson(Map json) => _$MdmsModelFromJson(json); + + + })= _MdmsResponse; + + factory MdmsResponse.fromJson(Map json) => _$MdmsResponseFromJson(json); } + + @freezed -class StateInfoModel with _$StateInfoModel { - const factory StateInfoModel({ - required String name, - required String code, - required String qrCodeURL, - required String bannerUrl, - required String logoUrl, - required String logoUrlWhite, - required String statelogo, - required bool hasLocalisation, - required bool enableWhatsApp, - required Map defaultUrl, - required List languages, - required List localizationModules, +class MdmsRes with _$MdmsRes { + + factory MdmsRes({ + + @JsonKey(name: "common-masters") + + CommonMasters? commonMasters, + @JsonKey(name:"tenant") + Tenant? tenant, + })= _MdmsRes; + + factory MdmsRes.fromJson(Map json) => _$MdmsResFromJson(json); +} + + +@freezed +class CommonMasters with _$CommonMasters { + + factory CommonMasters({ + + @JsonKey(name: "StateInfo") + + List? stateInfo + })= _CommonMasters; + + factory CommonMasters.fromJson(Map json) => _$CommonMastersFromJson(json); +} + + +@freezed +class StateInfo with _$StateInfo { + const factory StateInfo({ + String? name, + String? code, + String? qrCodeURL, + String? bannerUrl, + String? logoUrl, + String? logoUrlWhite, + String? statelogo, + bool? hasLocalisation, + bool? enableWhatsApp, + Map? defaultUrl, + List? languages, + List? localizationModules, }) = _StateInfo; - factory StateInfoModel.fromJson(Map json) => _$StateInfoModelFromJson(json); + factory StateInfo.fromJson(Map json) => _$StateInfoFromJson(json); } + @freezed class Language with _$Language { const factory Language({ @@ -55,3 +94,62 @@ class LocalizationModule with _$LocalizationModule { factory LocalizationModule.fromJson(Map json) => _$LocalizationModuleFromJson(json); } + + + +@freezed +class Tenant with _$Tenant { + + + factory Tenant({ + @JsonKey(name: "tenants") + + List?tenants + + })=_Tenant; + + factory Tenant.fromJson(Map json) => _$TenantFromJson(json); +} + + +@freezed +class Tenants with _$Tenants{ + + + factory Tenants({ + @JsonKey(name: "code") + String? code, + + @JsonKey(name:"name") + String? name, + @JsonKey(name: "type") + String? type, + + @JsonKey(name: "city") + City? city + + })=_Tenants; + + factory Tenants.fromJson(Map json) => _$TenantsFromJson(json); +} + + +@freezed +class City with _$City{ + + + factory City({ + @JsonKey(name: "name") + required String name, + + @JsonKey(name:"localName") + required String localName, + @JsonKey(name: "code") + required String code, + + + + })=_City; + + factory City.fromJson(Map json) => _$CityFromJson(json); +} \ No newline at end of file diff --git a/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_model/mdms_model.freezed.dart b/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_model/mdms_model.freezed.dart index 314cda58..0dc70c7e 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_model/mdms_model.freezed.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_model/mdms_model.freezed.dart @@ -14,35 +14,196 @@ T _$identity(T value) => value; final _privateConstructorUsedError = UnsupportedError( 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); -MdmsModel _$MdmsModelFromJson(Map json) { - return _MdmsModel.fromJson(json); +MdmsResponse _$MdmsResponseFromJson(Map json) { + return _MdmsResponse.fromJson(json); } /// @nodoc -mixin _$MdmsModel { - String get tenantId => throw _privateConstructorUsedError; - String get moduleName => throw _privateConstructorUsedError; - List get StateInfo => throw _privateConstructorUsedError; +mixin _$MdmsResponse { + @JsonKey(name: "MdmsRes") + MdmsRes? get mdmsRes => throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @JsonKey(ignore: true) - $MdmsModelCopyWith get copyWith => + $MdmsResponseCopyWith get copyWith => throw _privateConstructorUsedError; } /// @nodoc -abstract class $MdmsModelCopyWith<$Res> { - factory $MdmsModelCopyWith(MdmsModel value, $Res Function(MdmsModel) then) = - _$MdmsModelCopyWithImpl<$Res, MdmsModel>; +abstract class $MdmsResponseCopyWith<$Res> { + factory $MdmsResponseCopyWith( + MdmsResponse value, $Res Function(MdmsResponse) then) = + _$MdmsResponseCopyWithImpl<$Res, MdmsResponse>; + @useResult + $Res call({@JsonKey(name: "MdmsRes") MdmsRes? mdmsRes}); + + $MdmsResCopyWith<$Res>? get mdmsRes; +} + +/// @nodoc +class _$MdmsResponseCopyWithImpl<$Res, $Val extends MdmsResponse> + implements $MdmsResponseCopyWith<$Res> { + _$MdmsResponseCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? mdmsRes = freezed, + }) { + return _then(_value.copyWith( + mdmsRes: freezed == mdmsRes + ? _value.mdmsRes + : mdmsRes // ignore: cast_nullable_to_non_nullable + as MdmsRes?, + ) as $Val); + } + + @override + @pragma('vm:prefer-inline') + $MdmsResCopyWith<$Res>? get mdmsRes { + if (_value.mdmsRes == null) { + return null; + } + + return $MdmsResCopyWith<$Res>(_value.mdmsRes!, (value) { + return _then(_value.copyWith(mdmsRes: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$_MdmsResponseCopyWith<$Res> + implements $MdmsResponseCopyWith<$Res> { + factory _$$_MdmsResponseCopyWith( + _$_MdmsResponse value, $Res Function(_$_MdmsResponse) then) = + __$$_MdmsResponseCopyWithImpl<$Res>; + @override + @useResult + $Res call({@JsonKey(name: "MdmsRes") MdmsRes? mdmsRes}); + + @override + $MdmsResCopyWith<$Res>? get mdmsRes; +} + +/// @nodoc +class __$$_MdmsResponseCopyWithImpl<$Res> + extends _$MdmsResponseCopyWithImpl<$Res, _$_MdmsResponse> + implements _$$_MdmsResponseCopyWith<$Res> { + __$$_MdmsResponseCopyWithImpl( + _$_MdmsResponse _value, $Res Function(_$_MdmsResponse) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? mdmsRes = freezed, + }) { + return _then(_$_MdmsResponse( + mdmsRes: freezed == mdmsRes + ? _value.mdmsRes + : mdmsRes // ignore: cast_nullable_to_non_nullable + as MdmsRes?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_MdmsResponse implements _MdmsResponse { + _$_MdmsResponse({@JsonKey(name: "MdmsRes") this.mdmsRes}); + + factory _$_MdmsResponse.fromJson(Map json) => + _$$_MdmsResponseFromJson(json); + + @override + @JsonKey(name: "MdmsRes") + final MdmsRes? mdmsRes; + + @override + String toString() { + return 'MdmsResponse(mdmsRes: $mdmsRes)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_MdmsResponse && + (identical(other.mdmsRes, mdmsRes) || other.mdmsRes == mdmsRes)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, mdmsRes); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_MdmsResponseCopyWith<_$_MdmsResponse> get copyWith => + __$$_MdmsResponseCopyWithImpl<_$_MdmsResponse>(this, _$identity); + + @override + Map toJson() { + return _$$_MdmsResponseToJson( + this, + ); + } +} + +abstract class _MdmsResponse implements MdmsResponse { + factory _MdmsResponse({@JsonKey(name: "MdmsRes") final MdmsRes? mdmsRes}) = + _$_MdmsResponse; + + factory _MdmsResponse.fromJson(Map json) = + _$_MdmsResponse.fromJson; + + @override + @JsonKey(name: "MdmsRes") + MdmsRes? get mdmsRes; + @override + @JsonKey(ignore: true) + _$$_MdmsResponseCopyWith<_$_MdmsResponse> get copyWith => + throw _privateConstructorUsedError; +} + +MdmsRes _$MdmsResFromJson(Map json) { + return _MdmsRes.fromJson(json); +} + +/// @nodoc +mixin _$MdmsRes { + @JsonKey(name: "common-masters") + CommonMasters? get commonMasters => throw _privateConstructorUsedError; + @JsonKey(name: "tenant") + Tenant? get tenant => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $MdmsResCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $MdmsResCopyWith<$Res> { + factory $MdmsResCopyWith(MdmsRes value, $Res Function(MdmsRes) then) = + _$MdmsResCopyWithImpl<$Res, MdmsRes>; @useResult $Res call( - {String tenantId, String moduleName, List StateInfo}); + {@JsonKey(name: "common-masters") CommonMasters? commonMasters, + @JsonKey(name: "tenant") Tenant? tenant}); + + $CommonMastersCopyWith<$Res>? get commonMasters; + $TenantCopyWith<$Res>? get tenant; } /// @nodoc -class _$MdmsModelCopyWithImpl<$Res, $Val extends MdmsModel> - implements $MdmsModelCopyWith<$Res> { - _$MdmsModelCopyWithImpl(this._value, this._then); +class _$MdmsResCopyWithImpl<$Res, $Val extends MdmsRes> + implements $MdmsResCopyWith<$Res> { + _$MdmsResCopyWithImpl(this._value, this._then); // ignore: unused_field final $Val _value; @@ -52,203 +213,360 @@ class _$MdmsModelCopyWithImpl<$Res, $Val extends MdmsModel> @pragma('vm:prefer-inline') @override $Res call({ - Object? tenantId = null, - Object? moduleName = null, - Object? StateInfo = null, + Object? commonMasters = freezed, + Object? tenant = freezed, }) { return _then(_value.copyWith( - tenantId: null == tenantId - ? _value.tenantId - : tenantId // ignore: cast_nullable_to_non_nullable - as String, - moduleName: null == moduleName - ? _value.moduleName - : moduleName // ignore: cast_nullable_to_non_nullable - as String, - StateInfo: null == StateInfo - ? _value.StateInfo - : StateInfo // ignore: cast_nullable_to_non_nullable - as List, + commonMasters: freezed == commonMasters + ? _value.commonMasters + : commonMasters // ignore: cast_nullable_to_non_nullable + as CommonMasters?, + tenant: freezed == tenant + ? _value.tenant + : tenant // ignore: cast_nullable_to_non_nullable + as Tenant?, ) as $Val); } + + @override + @pragma('vm:prefer-inline') + $CommonMastersCopyWith<$Res>? get commonMasters { + if (_value.commonMasters == null) { + return null; + } + + return $CommonMastersCopyWith<$Res>(_value.commonMasters!, (value) { + return _then(_value.copyWith(commonMasters: value) as $Val); + }); + } + + @override + @pragma('vm:prefer-inline') + $TenantCopyWith<$Res>? get tenant { + if (_value.tenant == null) { + return null; + } + + return $TenantCopyWith<$Res>(_value.tenant!, (value) { + return _then(_value.copyWith(tenant: value) as $Val); + }); + } } /// @nodoc -abstract class _$$_MdmsModelCopyWith<$Res> implements $MdmsModelCopyWith<$Res> { - factory _$$_MdmsModelCopyWith( - _$_MdmsModel value, $Res Function(_$_MdmsModel) then) = - __$$_MdmsModelCopyWithImpl<$Res>; +abstract class _$$_MdmsResCopyWith<$Res> implements $MdmsResCopyWith<$Res> { + factory _$$_MdmsResCopyWith( + _$_MdmsRes value, $Res Function(_$_MdmsRes) then) = + __$$_MdmsResCopyWithImpl<$Res>; @override @useResult $Res call( - {String tenantId, String moduleName, List StateInfo}); + {@JsonKey(name: "common-masters") CommonMasters? commonMasters, + @JsonKey(name: "tenant") Tenant? tenant}); + + @override + $CommonMastersCopyWith<$Res>? get commonMasters; + @override + $TenantCopyWith<$Res>? get tenant; } /// @nodoc -class __$$_MdmsModelCopyWithImpl<$Res> - extends _$MdmsModelCopyWithImpl<$Res, _$_MdmsModel> - implements _$$_MdmsModelCopyWith<$Res> { - __$$_MdmsModelCopyWithImpl( - _$_MdmsModel _value, $Res Function(_$_MdmsModel) _then) +class __$$_MdmsResCopyWithImpl<$Res> + extends _$MdmsResCopyWithImpl<$Res, _$_MdmsRes> + implements _$$_MdmsResCopyWith<$Res> { + __$$_MdmsResCopyWithImpl(_$_MdmsRes _value, $Res Function(_$_MdmsRes) _then) : super(_value, _then); @pragma('vm:prefer-inline') @override $Res call({ - Object? tenantId = null, - Object? moduleName = null, - Object? StateInfo = null, + Object? commonMasters = freezed, + Object? tenant = freezed, }) { - return _then(_$_MdmsModel( - tenantId: null == tenantId - ? _value.tenantId - : tenantId // ignore: cast_nullable_to_non_nullable - as String, - moduleName: null == moduleName - ? _value.moduleName - : moduleName // ignore: cast_nullable_to_non_nullable - as String, - StateInfo: null == StateInfo - ? _value._StateInfo - : StateInfo // ignore: cast_nullable_to_non_nullable - as List, + return _then(_$_MdmsRes( + commonMasters: freezed == commonMasters + ? _value.commonMasters + : commonMasters // ignore: cast_nullable_to_non_nullable + as CommonMasters?, + tenant: freezed == tenant + ? _value.tenant + : tenant // ignore: cast_nullable_to_non_nullable + as Tenant?, )); } } /// @nodoc @JsonSerializable() -class _$_MdmsModel implements _MdmsModel { - const _$_MdmsModel( - {required this.tenantId, - required this.moduleName, - required final List StateInfo}) - : _StateInfo = StateInfo; +class _$_MdmsRes implements _MdmsRes { + _$_MdmsRes( + {@JsonKey(name: "common-masters") this.commonMasters, + @JsonKey(name: "tenant") this.tenant}); + + factory _$_MdmsRes.fromJson(Map json) => + _$$_MdmsResFromJson(json); + + @override + @JsonKey(name: "common-masters") + final CommonMasters? commonMasters; + @override + @JsonKey(name: "tenant") + final Tenant? tenant; + + @override + String toString() { + return 'MdmsRes(commonMasters: $commonMasters, tenant: $tenant)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_MdmsRes && + (identical(other.commonMasters, commonMasters) || + other.commonMasters == commonMasters) && + (identical(other.tenant, tenant) || other.tenant == tenant)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, commonMasters, tenant); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_MdmsResCopyWith<_$_MdmsRes> get copyWith => + __$$_MdmsResCopyWithImpl<_$_MdmsRes>(this, _$identity); + + @override + Map toJson() { + return _$$_MdmsResToJson( + this, + ); + } +} + +abstract class _MdmsRes implements MdmsRes { + factory _MdmsRes( + {@JsonKey(name: "common-masters") final CommonMasters? commonMasters, + @JsonKey(name: "tenant") final Tenant? tenant}) = _$_MdmsRes; + + factory _MdmsRes.fromJson(Map json) = _$_MdmsRes.fromJson; + + @override + @JsonKey(name: "common-masters") + CommonMasters? get commonMasters; + @override + @JsonKey(name: "tenant") + Tenant? get tenant; + @override + @JsonKey(ignore: true) + _$$_MdmsResCopyWith<_$_MdmsRes> get copyWith => + throw _privateConstructorUsedError; +} + +CommonMasters _$CommonMastersFromJson(Map json) { + return _CommonMasters.fromJson(json); +} + +/// @nodoc +mixin _$CommonMasters { + @JsonKey(name: "StateInfo") + List? get stateInfo => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $CommonMastersCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CommonMastersCopyWith<$Res> { + factory $CommonMastersCopyWith( + CommonMasters value, $Res Function(CommonMasters) then) = + _$CommonMastersCopyWithImpl<$Res, CommonMasters>; + @useResult + $Res call({@JsonKey(name: "StateInfo") List? stateInfo}); +} + +/// @nodoc +class _$CommonMastersCopyWithImpl<$Res, $Val extends CommonMasters> + implements $CommonMastersCopyWith<$Res> { + _$CommonMastersCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; - factory _$_MdmsModel.fromJson(Map json) => - _$$_MdmsModelFromJson(json); + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? stateInfo = freezed, + }) { + return _then(_value.copyWith( + stateInfo: freezed == stateInfo + ? _value.stateInfo + : stateInfo // ignore: cast_nullable_to_non_nullable + as List?, + ) as $Val); + } +} +/// @nodoc +abstract class _$$_CommonMastersCopyWith<$Res> + implements $CommonMastersCopyWith<$Res> { + factory _$$_CommonMastersCopyWith( + _$_CommonMasters value, $Res Function(_$_CommonMasters) then) = + __$$_CommonMastersCopyWithImpl<$Res>; @override - final String tenantId; + @useResult + $Res call({@JsonKey(name: "StateInfo") List? stateInfo}); +} + +/// @nodoc +class __$$_CommonMastersCopyWithImpl<$Res> + extends _$CommonMastersCopyWithImpl<$Res, _$_CommonMasters> + implements _$$_CommonMastersCopyWith<$Res> { + __$$_CommonMastersCopyWithImpl( + _$_CommonMasters _value, $Res Function(_$_CommonMasters) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') @override - final String moduleName; - final List _StateInfo; + $Res call({ + Object? stateInfo = freezed, + }) { + return _then(_$_CommonMasters( + stateInfo: freezed == stateInfo + ? _value._stateInfo + : stateInfo // ignore: cast_nullable_to_non_nullable + as List?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_CommonMasters implements _CommonMasters { + _$_CommonMasters( + {@JsonKey(name: "StateInfo") final List? stateInfo}) + : _stateInfo = stateInfo; + + factory _$_CommonMasters.fromJson(Map json) => + _$$_CommonMastersFromJson(json); + + final List? _stateInfo; @override - List get StateInfo { - if (_StateInfo is EqualUnmodifiableListView) return _StateInfo; + @JsonKey(name: "StateInfo") + List? get stateInfo { + final value = _stateInfo; + if (value == null) return null; + if (_stateInfo is EqualUnmodifiableListView) return _stateInfo; // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_StateInfo); + return EqualUnmodifiableListView(value); } @override String toString() { - return 'MdmsModel(tenantId: $tenantId, moduleName: $moduleName, StateInfo: $StateInfo)'; + return 'CommonMasters(stateInfo: $stateInfo)'; } @override bool operator ==(dynamic other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _$_MdmsModel && - (identical(other.tenantId, tenantId) || - other.tenantId == tenantId) && - (identical(other.moduleName, moduleName) || - other.moduleName == moduleName) && + other is _$_CommonMasters && const DeepCollectionEquality() - .equals(other._StateInfo, _StateInfo)); + .equals(other._stateInfo, _stateInfo)); } @JsonKey(ignore: true) @override - int get hashCode => Object.hash(runtimeType, tenantId, moduleName, - const DeepCollectionEquality().hash(_StateInfo)); + int get hashCode => + Object.hash(runtimeType, const DeepCollectionEquality().hash(_stateInfo)); @JsonKey(ignore: true) @override @pragma('vm:prefer-inline') - _$$_MdmsModelCopyWith<_$_MdmsModel> get copyWith => - __$$_MdmsModelCopyWithImpl<_$_MdmsModel>(this, _$identity); + _$$_CommonMastersCopyWith<_$_CommonMasters> get copyWith => + __$$_CommonMastersCopyWithImpl<_$_CommonMasters>(this, _$identity); @override Map toJson() { - return _$$_MdmsModelToJson( + return _$$_CommonMastersToJson( this, ); } } -abstract class _MdmsModel implements MdmsModel { - const factory _MdmsModel( - {required final String tenantId, - required final String moduleName, - required final List StateInfo}) = _$_MdmsModel; +abstract class _CommonMasters implements CommonMasters { + factory _CommonMasters( + {@JsonKey(name: "StateInfo") final List? stateInfo}) = + _$_CommonMasters; - factory _MdmsModel.fromJson(Map json) = - _$_MdmsModel.fromJson; + factory _CommonMasters.fromJson(Map json) = + _$_CommonMasters.fromJson; @override - String get tenantId; - @override - String get moduleName; - @override - List get StateInfo; + @JsonKey(name: "StateInfo") + List? get stateInfo; @override @JsonKey(ignore: true) - _$$_MdmsModelCopyWith<_$_MdmsModel> get copyWith => + _$$_CommonMastersCopyWith<_$_CommonMasters> get copyWith => throw _privateConstructorUsedError; } -StateInfoModel _$StateInfoModelFromJson(Map json) { +StateInfo _$StateInfoFromJson(Map json) { return _StateInfo.fromJson(json); } /// @nodoc -mixin _$StateInfoModel { - String get name => throw _privateConstructorUsedError; - String get code => throw _privateConstructorUsedError; - String get qrCodeURL => throw _privateConstructorUsedError; - String get bannerUrl => throw _privateConstructorUsedError; - String get logoUrl => throw _privateConstructorUsedError; - String get logoUrlWhite => throw _privateConstructorUsedError; - String get statelogo => throw _privateConstructorUsedError; - bool get hasLocalisation => throw _privateConstructorUsedError; - bool get enableWhatsApp => throw _privateConstructorUsedError; - Map get defaultUrl => throw _privateConstructorUsedError; - List get languages => throw _privateConstructorUsedError; - List get localizationModules => +mixin _$StateInfo { + String? get name => throw _privateConstructorUsedError; + String? get code => throw _privateConstructorUsedError; + String? get qrCodeURL => throw _privateConstructorUsedError; + String? get bannerUrl => throw _privateConstructorUsedError; + String? get logoUrl => throw _privateConstructorUsedError; + String? get logoUrlWhite => throw _privateConstructorUsedError; + String? get statelogo => throw _privateConstructorUsedError; + bool? get hasLocalisation => throw _privateConstructorUsedError; + bool? get enableWhatsApp => throw _privateConstructorUsedError; + Map? get defaultUrl => throw _privateConstructorUsedError; + List? get languages => throw _privateConstructorUsedError; + List? get localizationModules => throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @JsonKey(ignore: true) - $StateInfoModelCopyWith get copyWith => + $StateInfoCopyWith get copyWith => throw _privateConstructorUsedError; } /// @nodoc -abstract class $StateInfoModelCopyWith<$Res> { - factory $StateInfoModelCopyWith( - StateInfoModel value, $Res Function(StateInfoModel) then) = - _$StateInfoModelCopyWithImpl<$Res, StateInfoModel>; +abstract class $StateInfoCopyWith<$Res> { + factory $StateInfoCopyWith(StateInfo value, $Res Function(StateInfo) then) = + _$StateInfoCopyWithImpl<$Res, StateInfo>; @useResult $Res call( - {String name, - String code, - String qrCodeURL, - String bannerUrl, - String logoUrl, - String logoUrlWhite, - String statelogo, - bool hasLocalisation, - bool enableWhatsApp, - Map defaultUrl, - List languages, - List localizationModules}); + {String? name, + String? code, + String? qrCodeURL, + String? bannerUrl, + String? logoUrl, + String? logoUrlWhite, + String? statelogo, + bool? hasLocalisation, + bool? enableWhatsApp, + Map? defaultUrl, + List? languages, + List? localizationModules}); } /// @nodoc -class _$StateInfoModelCopyWithImpl<$Res, $Val extends StateInfoModel> - implements $StateInfoModelCopyWith<$Res> { - _$StateInfoModelCopyWithImpl(this._value, this._then); +class _$StateInfoCopyWithImpl<$Res, $Val extends StateInfo> + implements $StateInfoCopyWith<$Res> { + _$StateInfoCopyWithImpl(this._value, this._then); // ignore: unused_field final $Val _value; @@ -258,98 +576,97 @@ class _$StateInfoModelCopyWithImpl<$Res, $Val extends StateInfoModel> @pragma('vm:prefer-inline') @override $Res call({ - Object? name = null, - Object? code = null, - Object? qrCodeURL = null, - Object? bannerUrl = null, - Object? logoUrl = null, - Object? logoUrlWhite = null, - Object? statelogo = null, - Object? hasLocalisation = null, - Object? enableWhatsApp = null, - Object? defaultUrl = null, - Object? languages = null, - Object? localizationModules = null, + Object? name = freezed, + Object? code = freezed, + Object? qrCodeURL = freezed, + Object? bannerUrl = freezed, + Object? logoUrl = freezed, + Object? logoUrlWhite = freezed, + Object? statelogo = freezed, + Object? hasLocalisation = freezed, + Object? enableWhatsApp = freezed, + Object? defaultUrl = freezed, + Object? languages = freezed, + Object? localizationModules = freezed, }) { return _then(_value.copyWith( - name: null == name + name: freezed == name ? _value.name : name // ignore: cast_nullable_to_non_nullable - as String, - code: null == code + as String?, + code: freezed == code ? _value.code : code // ignore: cast_nullable_to_non_nullable - as String, - qrCodeURL: null == qrCodeURL + as String?, + qrCodeURL: freezed == qrCodeURL ? _value.qrCodeURL : qrCodeURL // ignore: cast_nullable_to_non_nullable - as String, - bannerUrl: null == bannerUrl + as String?, + bannerUrl: freezed == bannerUrl ? _value.bannerUrl : bannerUrl // ignore: cast_nullable_to_non_nullable - as String, - logoUrl: null == logoUrl + as String?, + logoUrl: freezed == logoUrl ? _value.logoUrl : logoUrl // ignore: cast_nullable_to_non_nullable - as String, - logoUrlWhite: null == logoUrlWhite + as String?, + logoUrlWhite: freezed == logoUrlWhite ? _value.logoUrlWhite : logoUrlWhite // ignore: cast_nullable_to_non_nullable - as String, - statelogo: null == statelogo + as String?, + statelogo: freezed == statelogo ? _value.statelogo : statelogo // ignore: cast_nullable_to_non_nullable - as String, - hasLocalisation: null == hasLocalisation + as String?, + hasLocalisation: freezed == hasLocalisation ? _value.hasLocalisation : hasLocalisation // ignore: cast_nullable_to_non_nullable - as bool, - enableWhatsApp: null == enableWhatsApp + as bool?, + enableWhatsApp: freezed == enableWhatsApp ? _value.enableWhatsApp : enableWhatsApp // ignore: cast_nullable_to_non_nullable - as bool, - defaultUrl: null == defaultUrl + as bool?, + defaultUrl: freezed == defaultUrl ? _value.defaultUrl : defaultUrl // ignore: cast_nullable_to_non_nullable - as Map, - languages: null == languages + as Map?, + languages: freezed == languages ? _value.languages : languages // ignore: cast_nullable_to_non_nullable - as List, - localizationModules: null == localizationModules + as List?, + localizationModules: freezed == localizationModules ? _value.localizationModules : localizationModules // ignore: cast_nullable_to_non_nullable - as List, + as List?, ) as $Val); } } /// @nodoc -abstract class _$$_StateInfoCopyWith<$Res> - implements $StateInfoModelCopyWith<$Res> { +abstract class _$$_StateInfoCopyWith<$Res> implements $StateInfoCopyWith<$Res> { factory _$$_StateInfoCopyWith( _$_StateInfo value, $Res Function(_$_StateInfo) then) = __$$_StateInfoCopyWithImpl<$Res>; @override @useResult $Res call( - {String name, - String code, - String qrCodeURL, - String bannerUrl, - String logoUrl, - String logoUrlWhite, - String statelogo, - bool hasLocalisation, - bool enableWhatsApp, - Map defaultUrl, - List languages, - List localizationModules}); + {String? name, + String? code, + String? qrCodeURL, + String? bannerUrl, + String? logoUrl, + String? logoUrlWhite, + String? statelogo, + bool? hasLocalisation, + bool? enableWhatsApp, + Map? defaultUrl, + List? languages, + List? localizationModules}); } /// @nodoc class __$$_StateInfoCopyWithImpl<$Res> - extends _$StateInfoModelCopyWithImpl<$Res, _$_StateInfo> + extends _$StateInfoCopyWithImpl<$Res, _$_StateInfo> implements _$$_StateInfoCopyWith<$Res> { __$$_StateInfoCopyWithImpl( _$_StateInfo _value, $Res Function(_$_StateInfo) _then) @@ -358,68 +675,68 @@ class __$$_StateInfoCopyWithImpl<$Res> @pragma('vm:prefer-inline') @override $Res call({ - Object? name = null, - Object? code = null, - Object? qrCodeURL = null, - Object? bannerUrl = null, - Object? logoUrl = null, - Object? logoUrlWhite = null, - Object? statelogo = null, - Object? hasLocalisation = null, - Object? enableWhatsApp = null, - Object? defaultUrl = null, - Object? languages = null, - Object? localizationModules = null, + Object? name = freezed, + Object? code = freezed, + Object? qrCodeURL = freezed, + Object? bannerUrl = freezed, + Object? logoUrl = freezed, + Object? logoUrlWhite = freezed, + Object? statelogo = freezed, + Object? hasLocalisation = freezed, + Object? enableWhatsApp = freezed, + Object? defaultUrl = freezed, + Object? languages = freezed, + Object? localizationModules = freezed, }) { return _then(_$_StateInfo( - name: null == name + name: freezed == name ? _value.name : name // ignore: cast_nullable_to_non_nullable - as String, - code: null == code + as String?, + code: freezed == code ? _value.code : code // ignore: cast_nullable_to_non_nullable - as String, - qrCodeURL: null == qrCodeURL + as String?, + qrCodeURL: freezed == qrCodeURL ? _value.qrCodeURL : qrCodeURL // ignore: cast_nullable_to_non_nullable - as String, - bannerUrl: null == bannerUrl + as String?, + bannerUrl: freezed == bannerUrl ? _value.bannerUrl : bannerUrl // ignore: cast_nullable_to_non_nullable - as String, - logoUrl: null == logoUrl + as String?, + logoUrl: freezed == logoUrl ? _value.logoUrl : logoUrl // ignore: cast_nullable_to_non_nullable - as String, - logoUrlWhite: null == logoUrlWhite + as String?, + logoUrlWhite: freezed == logoUrlWhite ? _value.logoUrlWhite : logoUrlWhite // ignore: cast_nullable_to_non_nullable - as String, - statelogo: null == statelogo + as String?, + statelogo: freezed == statelogo ? _value.statelogo : statelogo // ignore: cast_nullable_to_non_nullable - as String, - hasLocalisation: null == hasLocalisation + as String?, + hasLocalisation: freezed == hasLocalisation ? _value.hasLocalisation : hasLocalisation // ignore: cast_nullable_to_non_nullable - as bool, - enableWhatsApp: null == enableWhatsApp + as bool?, + enableWhatsApp: freezed == enableWhatsApp ? _value.enableWhatsApp : enableWhatsApp // ignore: cast_nullable_to_non_nullable - as bool, - defaultUrl: null == defaultUrl + as bool?, + defaultUrl: freezed == defaultUrl ? _value._defaultUrl : defaultUrl // ignore: cast_nullable_to_non_nullable - as Map, - languages: null == languages + as Map?, + languages: freezed == languages ? _value._languages : languages // ignore: cast_nullable_to_non_nullable - as List, - localizationModules: null == localizationModules + as List?, + localizationModules: freezed == localizationModules ? _value._localizationModules : localizationModules // ignore: cast_nullable_to_non_nullable - as List, + as List?, )); } } @@ -428,18 +745,18 @@ class __$$_StateInfoCopyWithImpl<$Res> @JsonSerializable() class _$_StateInfo implements _StateInfo { const _$_StateInfo( - {required this.name, - required this.code, - required this.qrCodeURL, - required this.bannerUrl, - required this.logoUrl, - required this.logoUrlWhite, - required this.statelogo, - required this.hasLocalisation, - required this.enableWhatsApp, - required final Map defaultUrl, - required final List languages, - required final List localizationModules}) + {this.name, + this.code, + this.qrCodeURL, + this.bannerUrl, + this.logoUrl, + this.logoUrlWhite, + this.statelogo, + this.hasLocalisation, + this.enableWhatsApp, + final Map? defaultUrl, + final List? languages, + final List? localizationModules}) : _defaultUrl = defaultUrl, _languages = languages, _localizationModules = localizationModules; @@ -448,51 +765,57 @@ class _$_StateInfo implements _StateInfo { _$$_StateInfoFromJson(json); @override - final String name; + final String? name; @override - final String code; + final String? code; @override - final String qrCodeURL; + final String? qrCodeURL; @override - final String bannerUrl; + final String? bannerUrl; @override - final String logoUrl; + final String? logoUrl; @override - final String logoUrlWhite; + final String? logoUrlWhite; @override - final String statelogo; + final String? statelogo; @override - final bool hasLocalisation; + final bool? hasLocalisation; @override - final bool enableWhatsApp; - final Map _defaultUrl; + final bool? enableWhatsApp; + final Map? _defaultUrl; @override - Map get defaultUrl { + Map? get defaultUrl { + final value = _defaultUrl; + if (value == null) return null; if (_defaultUrl is EqualUnmodifiableMapView) return _defaultUrl; // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_defaultUrl); + return EqualUnmodifiableMapView(value); } - final List _languages; + final List? _languages; @override - List get languages { + List? get languages { + final value = _languages; + if (value == null) return null; if (_languages is EqualUnmodifiableListView) return _languages; // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_languages); + return EqualUnmodifiableListView(value); } - final List _localizationModules; + final List? _localizationModules; @override - List get localizationModules { + List? get localizationModules { + final value = _localizationModules; + if (value == null) return null; if (_localizationModules is EqualUnmodifiableListView) return _localizationModules; // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_localizationModules); + return EqualUnmodifiableListView(value); } @override String toString() { - return 'StateInfoModel(name: $name, code: $code, qrCodeURL: $qrCodeURL, bannerUrl: $bannerUrl, logoUrl: $logoUrl, logoUrlWhite: $logoUrlWhite, statelogo: $statelogo, hasLocalisation: $hasLocalisation, enableWhatsApp: $enableWhatsApp, defaultUrl: $defaultUrl, languages: $languages, localizationModules: $localizationModules)'; + return 'StateInfo(name: $name, code: $code, qrCodeURL: $qrCodeURL, bannerUrl: $bannerUrl, logoUrl: $logoUrl, logoUrlWhite: $logoUrlWhite, statelogo: $statelogo, hasLocalisation: $hasLocalisation, enableWhatsApp: $enableWhatsApp, defaultUrl: $defaultUrl, languages: $languages, localizationModules: $localizationModules)'; } @override @@ -554,49 +877,48 @@ class _$_StateInfo implements _StateInfo { } } -abstract class _StateInfo implements StateInfoModel { +abstract class _StateInfo implements StateInfo { const factory _StateInfo( - {required final String name, - required final String code, - required final String qrCodeURL, - required final String bannerUrl, - required final String logoUrl, - required final String logoUrlWhite, - required final String statelogo, - required final bool hasLocalisation, - required final bool enableWhatsApp, - required final Map defaultUrl, - required final List languages, - required final List localizationModules}) = - _$_StateInfo; + {final String? name, + final String? code, + final String? qrCodeURL, + final String? bannerUrl, + final String? logoUrl, + final String? logoUrlWhite, + final String? statelogo, + final bool? hasLocalisation, + final bool? enableWhatsApp, + final Map? defaultUrl, + final List? languages, + final List? localizationModules}) = _$_StateInfo; factory _StateInfo.fromJson(Map json) = _$_StateInfo.fromJson; @override - String get name; + String? get name; @override - String get code; + String? get code; @override - String get qrCodeURL; + String? get qrCodeURL; @override - String get bannerUrl; + String? get bannerUrl; @override - String get logoUrl; + String? get logoUrl; @override - String get logoUrlWhite; + String? get logoUrlWhite; @override - String get statelogo; + String? get statelogo; @override - bool get hasLocalisation; + bool? get hasLocalisation; @override - bool get enableWhatsApp; + bool? get enableWhatsApp; @override - Map get defaultUrl; + Map? get defaultUrl; @override - List get languages; + List? get languages; @override - List get localizationModules; + List? get localizationModules; @override @JsonKey(ignore: true) _$$_StateInfoCopyWith<_$_StateInfo> get copyWith => @@ -907,3 +1229,551 @@ abstract class _LocalizationModule implements LocalizationModule { _$$_LocalizationModuleCopyWith<_$_LocalizationModule> get copyWith => throw _privateConstructorUsedError; } + +Tenant _$TenantFromJson(Map json) { + return _Tenant.fromJson(json); +} + +/// @nodoc +mixin _$Tenant { + @JsonKey(name: "tenants") + List? get tenants => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $TenantCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $TenantCopyWith<$Res> { + factory $TenantCopyWith(Tenant value, $Res Function(Tenant) then) = + _$TenantCopyWithImpl<$Res, Tenant>; + @useResult + $Res call({@JsonKey(name: "tenants") List? tenants}); +} + +/// @nodoc +class _$TenantCopyWithImpl<$Res, $Val extends Tenant> + implements $TenantCopyWith<$Res> { + _$TenantCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? tenants = freezed, + }) { + return _then(_value.copyWith( + tenants: freezed == tenants + ? _value.tenants + : tenants // ignore: cast_nullable_to_non_nullable + as List?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_TenantCopyWith<$Res> implements $TenantCopyWith<$Res> { + factory _$$_TenantCopyWith(_$_Tenant value, $Res Function(_$_Tenant) then) = + __$$_TenantCopyWithImpl<$Res>; + @override + @useResult + $Res call({@JsonKey(name: "tenants") List? tenants}); +} + +/// @nodoc +class __$$_TenantCopyWithImpl<$Res> + extends _$TenantCopyWithImpl<$Res, _$_Tenant> + implements _$$_TenantCopyWith<$Res> { + __$$_TenantCopyWithImpl(_$_Tenant _value, $Res Function(_$_Tenant) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? tenants = freezed, + }) { + return _then(_$_Tenant( + tenants: freezed == tenants + ? _value._tenants + : tenants // ignore: cast_nullable_to_non_nullable + as List?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_Tenant implements _Tenant { + _$_Tenant({@JsonKey(name: "tenants") final List? tenants}) + : _tenants = tenants; + + factory _$_Tenant.fromJson(Map json) => + _$$_TenantFromJson(json); + + final List? _tenants; + @override + @JsonKey(name: "tenants") + List? get tenants { + final value = _tenants; + if (value == null) return null; + if (_tenants is EqualUnmodifiableListView) return _tenants; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'Tenant(tenants: $tenants)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_Tenant && + const DeepCollectionEquality().equals(other._tenants, _tenants)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => + Object.hash(runtimeType, const DeepCollectionEquality().hash(_tenants)); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_TenantCopyWith<_$_Tenant> get copyWith => + __$$_TenantCopyWithImpl<_$_Tenant>(this, _$identity); + + @override + Map toJson() { + return _$$_TenantToJson( + this, + ); + } +} + +abstract class _Tenant implements Tenant { + factory _Tenant({@JsonKey(name: "tenants") final List? tenants}) = + _$_Tenant; + + factory _Tenant.fromJson(Map json) = _$_Tenant.fromJson; + + @override + @JsonKey(name: "tenants") + List? get tenants; + @override + @JsonKey(ignore: true) + _$$_TenantCopyWith<_$_Tenant> get copyWith => + throw _privateConstructorUsedError; +} + +Tenants _$TenantsFromJson(Map json) { + return _Tenants.fromJson(json); +} + +/// @nodoc +mixin _$Tenants { + @JsonKey(name: "code") + String? get code => throw _privateConstructorUsedError; + @JsonKey(name: "name") + String? get name => throw _privateConstructorUsedError; + @JsonKey(name: "type") + String? get type => throw _privateConstructorUsedError; + @JsonKey(name: "city") + City? get city => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $TenantsCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $TenantsCopyWith<$Res> { + factory $TenantsCopyWith(Tenants value, $Res Function(Tenants) then) = + _$TenantsCopyWithImpl<$Res, Tenants>; + @useResult + $Res call( + {@JsonKey(name: "code") String? code, + @JsonKey(name: "name") String? name, + @JsonKey(name: "type") String? type, + @JsonKey(name: "city") City? city}); + + $CityCopyWith<$Res>? get city; +} + +/// @nodoc +class _$TenantsCopyWithImpl<$Res, $Val extends Tenants> + implements $TenantsCopyWith<$Res> { + _$TenantsCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? code = freezed, + Object? name = freezed, + Object? type = freezed, + Object? city = freezed, + }) { + return _then(_value.copyWith( + code: freezed == code + ? _value.code + : code // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + type: freezed == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as String?, + city: freezed == city + ? _value.city + : city // ignore: cast_nullable_to_non_nullable + as City?, + ) as $Val); + } + + @override + @pragma('vm:prefer-inline') + $CityCopyWith<$Res>? get city { + if (_value.city == null) { + return null; + } + + return $CityCopyWith<$Res>(_value.city!, (value) { + return _then(_value.copyWith(city: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$_TenantsCopyWith<$Res> implements $TenantsCopyWith<$Res> { + factory _$$_TenantsCopyWith( + _$_Tenants value, $Res Function(_$_Tenants) then) = + __$$_TenantsCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {@JsonKey(name: "code") String? code, + @JsonKey(name: "name") String? name, + @JsonKey(name: "type") String? type, + @JsonKey(name: "city") City? city}); + + @override + $CityCopyWith<$Res>? get city; +} + +/// @nodoc +class __$$_TenantsCopyWithImpl<$Res> + extends _$TenantsCopyWithImpl<$Res, _$_Tenants> + implements _$$_TenantsCopyWith<$Res> { + __$$_TenantsCopyWithImpl(_$_Tenants _value, $Res Function(_$_Tenants) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? code = freezed, + Object? name = freezed, + Object? type = freezed, + Object? city = freezed, + }) { + return _then(_$_Tenants( + code: freezed == code + ? _value.code + : code // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + type: freezed == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as String?, + city: freezed == city + ? _value.city + : city // ignore: cast_nullable_to_non_nullable + as City?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_Tenants implements _Tenants { + _$_Tenants( + {@JsonKey(name: "code") this.code, + @JsonKey(name: "name") this.name, + @JsonKey(name: "type") this.type, + @JsonKey(name: "city") this.city}); + + factory _$_Tenants.fromJson(Map json) => + _$$_TenantsFromJson(json); + + @override + @JsonKey(name: "code") + final String? code; + @override + @JsonKey(name: "name") + final String? name; + @override + @JsonKey(name: "type") + final String? type; + @override + @JsonKey(name: "city") + final City? city; + + @override + String toString() { + return 'Tenants(code: $code, name: $name, type: $type, city: $city)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_Tenants && + (identical(other.code, code) || other.code == code) && + (identical(other.name, name) || other.name == name) && + (identical(other.type, type) || other.type == type) && + (identical(other.city, city) || other.city == city)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, code, name, type, city); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_TenantsCopyWith<_$_Tenants> get copyWith => + __$$_TenantsCopyWithImpl<_$_Tenants>(this, _$identity); + + @override + Map toJson() { + return _$$_TenantsToJson( + this, + ); + } +} + +abstract class _Tenants implements Tenants { + factory _Tenants( + {@JsonKey(name: "code") final String? code, + @JsonKey(name: "name") final String? name, + @JsonKey(name: "type") final String? type, + @JsonKey(name: "city") final City? city}) = _$_Tenants; + + factory _Tenants.fromJson(Map json) = _$_Tenants.fromJson; + + @override + @JsonKey(name: "code") + String? get code; + @override + @JsonKey(name: "name") + String? get name; + @override + @JsonKey(name: "type") + String? get type; + @override + @JsonKey(name: "city") + City? get city; + @override + @JsonKey(ignore: true) + _$$_TenantsCopyWith<_$_Tenants> get copyWith => + throw _privateConstructorUsedError; +} + +City _$CityFromJson(Map json) { + return _City.fromJson(json); +} + +/// @nodoc +mixin _$City { + @JsonKey(name: "name") + String get name => throw _privateConstructorUsedError; + @JsonKey(name: "localName") + String get localName => throw _privateConstructorUsedError; + @JsonKey(name: "code") + String get code => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $CityCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CityCopyWith<$Res> { + factory $CityCopyWith(City value, $Res Function(City) then) = + _$CityCopyWithImpl<$Res, City>; + @useResult + $Res call( + {@JsonKey(name: "name") String name, + @JsonKey(name: "localName") String localName, + @JsonKey(name: "code") String code}); +} + +/// @nodoc +class _$CityCopyWithImpl<$Res, $Val extends City> + implements $CityCopyWith<$Res> { + _$CityCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? localName = null, + Object? code = null, + }) { + return _then(_value.copyWith( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + localName: null == localName + ? _value.localName + : localName // ignore: cast_nullable_to_non_nullable + as String, + code: null == code + ? _value.code + : code // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_CityCopyWith<$Res> implements $CityCopyWith<$Res> { + factory _$$_CityCopyWith(_$_City value, $Res Function(_$_City) then) = + __$$_CityCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {@JsonKey(name: "name") String name, + @JsonKey(name: "localName") String localName, + @JsonKey(name: "code") String code}); +} + +/// @nodoc +class __$$_CityCopyWithImpl<$Res> extends _$CityCopyWithImpl<$Res, _$_City> + implements _$$_CityCopyWith<$Res> { + __$$_CityCopyWithImpl(_$_City _value, $Res Function(_$_City) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? localName = null, + Object? code = null, + }) { + return _then(_$_City( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + localName: null == localName + ? _value.localName + : localName // ignore: cast_nullable_to_non_nullable + as String, + code: null == code + ? _value.code + : code // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_City implements _City { + _$_City( + {@JsonKey(name: "name") required this.name, + @JsonKey(name: "localName") required this.localName, + @JsonKey(name: "code") required this.code}); + + factory _$_City.fromJson(Map json) => _$$_CityFromJson(json); + + @override + @JsonKey(name: "name") + final String name; + @override + @JsonKey(name: "localName") + final String localName; + @override + @JsonKey(name: "code") + final String code; + + @override + String toString() { + return 'City(name: $name, localName: $localName, code: $code)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_City && + (identical(other.name, name) || other.name == name) && + (identical(other.localName, localName) || + other.localName == localName) && + (identical(other.code, code) || other.code == code)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, name, localName, code); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_CityCopyWith<_$_City> get copyWith => + __$$_CityCopyWithImpl<_$_City>(this, _$identity); + + @override + Map toJson() { + return _$$_CityToJson( + this, + ); + } +} + +abstract class _City implements City { + factory _City( + {@JsonKey(name: "name") required final String name, + @JsonKey(name: "localName") required final String localName, + @JsonKey(name: "code") required final String code}) = _$_City; + + factory _City.fromJson(Map json) = _$_City.fromJson; + + @override + @JsonKey(name: "name") + String get name; + @override + @JsonKey(name: "localName") + String get localName; + @override + @JsonKey(name: "code") + String get code; + @override + @JsonKey(ignore: true) + _$$_CityCopyWith<_$_City> get copyWith => throw _privateConstructorUsedError; +} diff --git a/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_model/mdms_model.g.dart b/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_model/mdms_model.g.dart index 292a64a7..05669fdc 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_model/mdms_model.g.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/models/mdms/mdms_model/mdms_model.g.dart @@ -6,37 +6,64 @@ part of 'mdms_model.dart'; // JsonSerializableGenerator // ************************************************************************** -_$_MdmsModel _$$_MdmsModelFromJson(Map json) => _$_MdmsModel( - tenantId: json['tenantId'] as String, - moduleName: json['moduleName'] as String, - StateInfo: (json['StateInfo'] as List) - .map((e) => StateInfoModel.fromJson(e as Map)) +_$_MdmsResponse _$$_MdmsResponseFromJson(Map json) => + _$_MdmsResponse( + mdmsRes: json['MdmsRes'] == null + ? null + : MdmsRes.fromJson(json['MdmsRes'] as Map), + ); + +Map _$$_MdmsResponseToJson(_$_MdmsResponse instance) => + { + 'MdmsRes': instance.mdmsRes, + }; + +_$_MdmsRes _$$_MdmsResFromJson(Map json) => _$_MdmsRes( + commonMasters: json['common-masters'] == null + ? null + : CommonMasters.fromJson( + json['common-masters'] as Map), + tenant: json['tenant'] == null + ? null + : Tenant.fromJson(json['tenant'] as Map), + ); + +Map _$$_MdmsResToJson(_$_MdmsRes instance) => + { + 'common-masters': instance.commonMasters, + 'tenant': instance.tenant, + }; + +_$_CommonMasters _$$_CommonMastersFromJson(Map json) => + _$_CommonMasters( + stateInfo: (json['StateInfo'] as List?) + ?.map((e) => StateInfo.fromJson(e as Map)) .toList(), ); -Map _$$_MdmsModelToJson(_$_MdmsModel instance) => +Map _$$_CommonMastersToJson(_$_CommonMasters instance) => { - 'tenantId': instance.tenantId, - 'moduleName': instance.moduleName, - 'StateInfo': instance.StateInfo, + 'StateInfo': instance.stateInfo, }; _$_StateInfo _$$_StateInfoFromJson(Map json) => _$_StateInfo( - name: json['name'] as String, - code: json['code'] as String, - qrCodeURL: json['qrCodeURL'] as String, - bannerUrl: json['bannerUrl'] as String, - logoUrl: json['logoUrl'] as String, - logoUrlWhite: json['logoUrlWhite'] as String, - statelogo: json['statelogo'] as String, - hasLocalisation: json['hasLocalisation'] as bool, - enableWhatsApp: json['enableWhatsApp'] as bool, - defaultUrl: Map.from(json['defaultUrl'] as Map), - languages: (json['languages'] as List) - .map((e) => Language.fromJson(e as Map)) + name: json['name'] as String?, + code: json['code'] as String?, + qrCodeURL: json['qrCodeURL'] as String?, + bannerUrl: json['bannerUrl'] as String?, + logoUrl: json['logoUrl'] as String?, + logoUrlWhite: json['logoUrlWhite'] as String?, + statelogo: json['statelogo'] as String?, + hasLocalisation: json['hasLocalisation'] as bool?, + enableWhatsApp: json['enableWhatsApp'] as bool?, + defaultUrl: (json['defaultUrl'] as Map?)?.map( + (k, e) => MapEntry(k, e as String), + ), + languages: (json['languages'] as List?) + ?.map((e) => Language.fromJson(e as Map)) .toList(), - localizationModules: (json['localizationModules'] as List) - .map((e) => LocalizationModule.fromJson(e as Map)) + localizationModules: (json['localizationModules'] as List?) + ?.map((e) => LocalizationModule.fromJson(e as Map)) .toList(), ); @@ -80,3 +107,42 @@ Map _$$_LocalizationModuleToJson( 'label': instance.label, 'value': instance.value, }; + +_$_Tenant _$$_TenantFromJson(Map json) => _$_Tenant( + tenants: (json['tenants'] as List?) + ?.map((e) => Tenants.fromJson(e as Map)) + .toList(), + ); + +Map _$$_TenantToJson(_$_Tenant instance) => { + 'tenants': instance.tenants, + }; + +_$_Tenants _$$_TenantsFromJson(Map json) => _$_Tenants( + code: json['code'] as String?, + name: json['name'] as String?, + type: json['type'] as String?, + city: json['city'] == null + ? null + : City.fromJson(json['city'] as Map), + ); + +Map _$$_TenantsToJson(_$_Tenants instance) => + { + 'code': instance.code, + 'name': instance.name, + 'type': instance.type, + 'city': instance.city, + }; + +_$_City _$$_CityFromJson(Map json) => _$_City( + name: json['name'] as String, + localName: json['localName'] as String, + code: json['code'] as String, + ); + +Map _$$_CityToJson(_$_City instance) => { + 'name': instance.name, + 'localName': instance.localName, + 'code': instance.code, + }; diff --git a/vehicle-tracker/vehicle_tracker_app/lib/pages/home/home_page.dart b/vehicle-tracker/vehicle_tracker_app/lib/pages/home/home_page.dart index 9251b334..152d8dc0 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/pages/home/home_page.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/pages/home/home_page.dart @@ -14,7 +14,7 @@ class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { - Get.put(TripControllers(context), permanent: true); + Get.put(TripControllers(), permanent: true); final infoController = Get.find(); final theme = DigitTheme.instance; @@ -35,18 +35,19 @@ class HomePage extends StatelessWidget { body: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // * Help Button - Padding( - padding: theme.buttonPadding, - child: Align( - alignment: Alignment.topRight, - child: DigitIconButton( - icon: Icons.help_outline_rounded, - iconText: AppTranslation.HELP.tr, - onPressed: () {}, - ), - ), - ), + + // * Help Button // Removed as per UIUX audit feedback + // Padding( + // padding: theme.buttonPadding, + // child: Align( + // alignment: Alignment.topRight, + // child: DigitIconButton( + // icon: Icons.help_outline_rounded, + // iconText: AppTranslation.HELP.tr, + // onPressed: () {}, + // ), + // ), + // ), // * App heading Padding( diff --git a/vehicle-tracker/vehicle_tracker_app/lib/pages/login/city_select_page.dart b/vehicle-tracker/vehicle_tracker_app/lib/pages/login/city_select_page.dart new file mode 100644 index 00000000..7fcfba8d --- /dev/null +++ b/vehicle-tracker/vehicle_tracker_app/lib/pages/login/city_select_page.dart @@ -0,0 +1,92 @@ +import 'package:digit_components/theme/digit_theme.dart'; +import 'package:digit_components/widgets/atoms/digit_dropdown.dart'; +import 'package:digit_components/widgets/digit_card.dart'; +import 'package:digit_components/widgets/digit_elevated_button.dart'; +import 'package:digit_components/widgets/powered_by_digit.dart'; +import 'package:digit_components/widgets/scrollable_content.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:vehicle_tracker_app/data/hive_service.dart'; +import 'package:vehicle_tracker_app/models/mdms/mdms_hive/mdms_hive_model.dart'; + +import '../../blocs/login/controllers/login_controllers.dart'; +import '../../router/routes.dart'; +import '../../util/i18n_translations.dart'; +import '../../widgets/utils/scrollable_header_widget.dart'; + +class CitySelectPage extends StatefulWidget { + const CitySelectPage({super.key}); + + @override + State createState() => _CitySelectPageState(); +} + +class _CitySelectPageState extends State { + @override + Widget build(BuildContext context) { + LoginController loginController = Get.find(); + final textTheme = DigitTheme.instance.mobileTheme.textTheme; + + var data = HiveService.getMdmsData(); + + List s = data.first.cityHive; + + return Scaffold( + appBar: AppBar( + // title: Text(AppTranslation.HOME_APP_BAR.tr), + centerTitle: false, + automaticallyImplyLeading: false, + ), + body: ScrollableContent( + footer: const PoweredByDigit(), + header: scrollableHeaderWidget(true, false), + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // * Login Card + DigitCard( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppTranslation.PLEASE_SELECT_CITY.tr ?? + "Choose your location", + style: textTheme.displayMedium, + ), + const SizedBox( + height: 8, + ), + + //* City Dropdown + DigitDropdown( + value: s.first, + label: AppTranslation.CITY.tr, + menuItems: s, + onChanged: (value) { + loginController.cityController.text = + value!.cityCode.toString(); + }, + valueMapper: (value) => value.cityName, + ), + + // * Login Button + Padding( + padding: const EdgeInsets.only(top: kPadding) * 2, + child: Obx(() { + if (loginController.isLoading.value) { + return const Center(child: CircularProgressIndicator()); + } else { + return DigitElevatedButton( + child: Text(AppTranslation.CONTINUE.tr), + onPressed: () => loginController.login(), + ); + } + }), + ), + ], + ), + ) + ], + ), + ); + } +} diff --git a/vehicle-tracker/vehicle_tracker_app/lib/pages/login/login_page.dart b/vehicle-tracker/vehicle_tracker_app/lib/pages/login/login_page.dart index 1472800e..ddfa1658 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/pages/login/login_page.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/pages/login/login_page.dart @@ -35,42 +35,38 @@ class LoginPage extends StatelessWidget { AppTranslation.LOGIN.tr, style: textTheme.displayMedium, ), - - // * Text Fields for User ID and Password - DigitTextField( - label: AppTranslation.USER_ID.tr, - controller: loginController.userNameController, + const SizedBox( + height: 8, ), - DigitTextField( - label: AppTranslation.PASSWORD.tr, - controller: loginController.passwordController, + Text( + AppTranslation.LOGIN_SUB_LINE.tr ?? + "Provide mobile number and validate with OTP sent to you through SMS", + style: textTheme.titleLarge, ), - // * City Dropdown - DigitDropdown( - value: loginController.city, - label: AppTranslation.CITY.tr, - menuItems: cityNames, - onChanged: (value) => loginController.city = value ?? "", - valueMapper: (value) => value, + DigitTextField( + maxLength: 10, + prefixText: '+91', + textInputType: TextInputType.number, + isRequired: true, + label: MOBILE_NUMBER, + controller: loginController.userNameController, ), // * Login Button Padding( padding: const EdgeInsets.only(top: kPadding) * 2, - child: DigitElevatedButton( - child: Text(AppTranslation.LOGIN.tr), - onPressed: () => loginController.login(context), - ), + child: Obx(() { + if (loginController.isLoading.value) { + return const Center(child: CircularProgressIndicator()); + } else { + return DigitElevatedButton( + child: Text(AppTranslation.CONTINUE.tr), + onPressed: () => loginController.sendOTP(context), + ); + } + }), ), - - // * Forgot Password Button - Center( - child: DigitIconButton( - iconText: AppTranslation.FORGOT_PASSWORD.tr, - onPressed: () => loginController.forgetPassword(context), - ), - ) ], ), ) diff --git a/vehicle-tracker/vehicle_tracker_app/lib/pages/login/otp_page.dart b/vehicle-tracker/vehicle_tracker_app/lib/pages/login/otp_page.dart new file mode 100644 index 00000000..94e446a2 --- /dev/null +++ b/vehicle-tracker/vehicle_tracker_app/lib/pages/login/otp_page.dart @@ -0,0 +1,174 @@ +import 'dart:async'; + +import 'package:digit_components/theme/digit_theme.dart'; +import 'package:digit_components/widgets/atoms/digit_icon_button.dart'; +import 'package:digit_components/widgets/digit_card.dart'; +import 'package:digit_components/widgets/digit_elevated_button.dart'; +import 'package:digit_components/widgets/digit_text_field.dart'; +import 'package:digit_components/widgets/powered_by_digit.dart'; +import 'package:digit_components/widgets/scrollable_content.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:pin_input_text_field/pin_input_text_field.dart'; + +import '../../blocs/login/controllers/login_controllers.dart'; +import '../../util/i18n_translations.dart'; +import '../../widgets/utils/scrollable_header_widget.dart'; + +class OTPPage extends StatefulWidget { + const OTPPage({super.key}); + + @override + State createState() => _OTPPageState(); +} + +class _OTPPageState extends State { + bool next = false; + + final FocusNode pinFocusNode = FocusNode(); + + late LoginController loginController; + + int _remainingSeconds = 30; + late Timer _timer; + + @override + void initState() { + loginController = Get.find(); + loginController.passwordController.clear(); + startTimer(); + super.initState(); + } + + void startTimer() { + const oneSecond = Duration(seconds: 1); + _timer = Timer.periodic(oneSecond, (timer) { + setState(() { + if (_remainingSeconds == 0) { + timer.cancel(); + } else { + _remainingSeconds--; + } + }); + }); + } + + @override + void dispose() { + pinFocusNode.dispose(); + _timer.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + // LoginController loginController = Get.find(); + final textTheme = DigitTheme.instance.mobileTheme.textTheme; + return Scaffold( + appBar: AppBar( + // title: Text(AppTranslation.HOME_APP_BAR.tr), + centerTitle: false, + automaticallyImplyLeading: false, + ), + body: ScrollableContent( + footer: const PoweredByDigit(), + header: scrollableHeaderWidget(true, false), + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // * Login Card + DigitCard( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppTranslation.OTP_VERIFY.tr ?? "OTP Verification", + style: textTheme.displayMedium, + ), + const SizedBox( + height: 8, + ), + Text( + "${AppTranslation.ENTER_OTP_SENT}${loginController.userNameController.text}", + style: textTheme.labelMedium, + ), + + const SizedBox( + height: 8, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Align( + alignment: Alignment.centerLeft, + child: SizedBox( + height: 40, + width: MediaQuery.of(context).size.width < 720 + ? MediaQuery.of(context).size.width - 50 + : 350, + child: PinInputTextField( + pinLength: 6, + cursor: Cursor( + width: 2, + height: 20, + color: Colors.black, + radius: const Radius.circular(0.5), + enabled: true, + ), + decoration: BoxLooseDecoration( + textStyle: DigitTheme + .instance.mobileTheme.textTheme.bodyLarge, + strokeColorBuilder: PinListenColorBuilder( + DigitTheme.instance.colorScheme.primary, + Colors.grey), + radius: Radius.zero), + controller: loginController.passwordController, + onChanged: (value) { + setState(() { + next = loginController + .passwordController.text.length == + 6; + }); + }, + autoFocus: true, + focusNode: pinFocusNode, + textInputAction: TextInputAction.go, + keyboardType: TextInputType.phone, + enableInteractiveSelection: true, + inputFormatters: [ + FilteringTextInputFormatter.allow( + RegExp(r'^[0-9]+$')) + ], + ), + )), + ), + _remainingSeconds == 0 + ? DigitIconButton( + iconText: AppTranslation.RESEND_OTP.tr, + onPressed: () { + loginController.passwordController.clear(); + _remainingSeconds = 30; + _timer.cancel(); + startTimer(); + + loginController.sendOTP(context); + }) + : Text( + '${AppTranslation.REQUEST_ANOTHER_OTP.tr} $_remainingSeconds seconds', + style: const TextStyle(fontSize: 18), + ), + // * Login Button + Padding( + padding: const EdgeInsets.only(top: kPadding) * 2, + child: DigitElevatedButton( + child: Text(AppTranslation.CONTINUE.tr), + onPressed: () => loginController.navgiateTocity(context), + ), + ), + ], + ), + ) + ], + ), + ); + } +} diff --git a/vehicle-tracker/vehicle_tracker_app/lib/pages/trip/trip_complete.dart b/vehicle-tracker/vehicle_tracker_app/lib/pages/trip/trip_complete.dart index 9a73f6b2..0fbee68b 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/pages/trip/trip_complete.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/pages/trip/trip_complete.dart @@ -3,8 +3,8 @@ import 'package:flutter/material.dart'; import '../../widgets/trip/trip_info_widget.dart'; -class TripCompletepage extends StatelessWidget { - const TripCompletepage({super.key}); +class TripCompletePage extends StatelessWidget { + const TripCompletePage({super.key}); @override Widget build(BuildContext context) { diff --git a/vehicle-tracker/vehicle_tracker_app/lib/pages/trip/upload_drop_photo_page.dart b/vehicle-tracker/vehicle_tracker_app/lib/pages/trip/upload_photo_page.dart similarity index 65% rename from vehicle-tracker/vehicle_tracker_app/lib/pages/trip/upload_drop_photo_page.dart rename to vehicle-tracker/vehicle_tracker_app/lib/pages/trip/upload_photo_page.dart index b798fb70..3316067d 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/pages/trip/upload_drop_photo_page.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/pages/trip/upload_photo_page.dart @@ -7,28 +7,22 @@ import 'package:vehicle_tracker_app/widgets/trip/camera_widget.dart'; import '../../blocs/details/controllers/camera_controllers.dart'; import '../../widgets/utils/drawer_widget.dart'; -class UploadDropPhotoPgae extends StatelessWidget { - const UploadDropPhotoPgae({super.key}); +enum PhotoType { Drop, Safety } + +class UploadPhotoPage extends StatelessWidget { + final PhotoType photoType; + + const UploadPhotoPage({Key? key, required this.photoType}) : super(key: key); @override Widget build(BuildContext context) { final cameraController = Get.find(); return Scaffold( - // * AppBar - appBar: AppBar( - // title: Text(AppTranslation.HOME_APP_BAR.tr), - centerTitle: false, - ), - - // * Drawer + appBar: AppBar(centerTitle: false), drawer: const CustomDrawer(), - - // * Body body: ScrollableContent( - // * Headers header: scrollableHeaderWidget(true, true), - crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ @@ -36,14 +30,15 @@ class UploadDropPhotoPgae extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text("Your drop location is not within FSTP boundary!"), - const Text("Please upload Photograph at FSTP for additional verification"), - - // todo: Take image widget + Text(photoType == PhotoType.Drop + ? "Your drop location is not within FSTP boundary!" + : "Your safety location is not within FSTP boundary!"), + const Text( + "Please upload Photograph at FSTP for additional verification"), CameraWidget(), - - DigitElevatedButton(child: const Text("End Trip"), onPressed: () {}), - + DigitElevatedButton( + child: const Text("End Trip"), + onPressed: () {}), // TODO: Implement End Trip Functionality Obx(() { if (cameraController.imageDrop.value != null) { return Center( @@ -53,12 +48,11 @@ class UploadDropPhotoPgae extends StatelessWidget { ), ); } - return const SizedBox(); - }) + }), ], ), - ) + ), ], ), ); diff --git a/vehicle-tracker/vehicle_tracker_app/lib/pages/trip/upload_safety_photo_page.dart b/vehicle-tracker/vehicle_tracker_app/lib/pages/trip/upload_safety_photo_page.dart deleted file mode 100644 index ef5cf785..00000000 --- a/vehicle-tracker/vehicle_tracker_app/lib/pages/trip/upload_safety_photo_page.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'package:digit_components/digit_components.dart'; -import 'package:flutter/material.dart'; -import 'package:get/get.dart'; -import 'package:vehicle_tracker_app/router/routes.dart'; -import 'package:vehicle_tracker_app/widgets/utils/scrollable_header_widget.dart'; -import 'package:vehicle_tracker_app/widgets/trip/camera_widget.dart'; - -import '../../blocs/details/controllers/camera_controllers.dart'; -import '../../widgets/utils/drawer_widget.dart'; - -class UploadSafetyPhotoPgae extends StatelessWidget { - UploadSafetyPhotoPgae({super.key}); - - final cameraController = Get.find(); - - @override - Widget build(BuildContext context) { - return Scaffold( - // * AppBar - appBar: AppBar( - // title: Text(AppTranslation.HOME_APP_BAR.tr), - centerTitle: false, - ), - - // * Drawer - drawer: const CustomDrawer(), - - // * Body - body: ScrollableContent( - // * Headers - header: scrollableHeaderWidget(true, true), - - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - DigitCard( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text("Upload your photo with Safety Gear"), - const Text("This is to verify that the necessary safety protocols are followed. "), - - // todo: Take image widget - CameraWidget(), - - DigitElevatedButton(child: const Text("End Trip"), onPressed: () => Get.toNamed(TRIP_COMPLETE)), - - Obx(() { - if (cameraController.imageSafety.value != null) { - return Center( - child: DigitOutLineButton( - label: "Re - Upload Photograph", - onPressed: () => cameraController.pickImageSafety(), - ), - ); - } - - return const SizedBox(); - }) - ], - ), - ) - ], - ), - ); - } -} diff --git a/vehicle-tracker/vehicle_tracker_app/lib/router/routes.dart b/vehicle-tracker/vehicle_tracker_app/lib/router/routes.dart index aa4d817f..b6165e45 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/router/routes.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/router/routes.dart @@ -7,11 +7,13 @@ import 'package:vehicle_tracker_app/pages/home/home_page.dart'; import 'package:vehicle_tracker_app/pages/login/login_lang_select_page.dart'; import 'package:vehicle_tracker_app/pages/login/login_page.dart'; import 'package:vehicle_tracker_app/pages/trip/trip_complete.dart'; -import 'package:vehicle_tracker_app/pages/trip/upload_safety_photo_page.dart'; import '../blocs/home/bindings/home_bindings.dart'; import '../blocs/login/bindings/login_bindings.dart'; +import '../pages/login/city_select_page.dart'; +import '../pages/login/otp_page.dart'; import '../pages/trip/trip_fill_details_page.dart'; +import '../pages/trip/upload_photo_page.dart'; String HOME = "/"; String LOGIN = "/login"; @@ -21,6 +23,8 @@ String DETAILS = "/details"; String UPLOAD_SAFETY = "/upload_safety"; String UPLOAD_DROP = "/upload_drop"; String TRIP_COMPLETE = "/trip_complete"; +String OTP="/otp"; +String SELECTCITY="/select_city"; List> getPages = [ GetPage( @@ -33,6 +37,16 @@ List> getPages = [ page: () => const LoginPage(), binding: LoginBindings(), ), + GetPage( + name: OTP, + page: () => const OTPPage(), + binding: LoginBindings(), + ), + GetPage( + name: SELECTCITY, + page: () => const CitySelectPage(), + binding: LoginBindings(), + ), GetPage( name: LANG, page: () => const LoginLangSelectPage(), @@ -50,16 +64,16 @@ List> getPages = [ ), GetPage( name: UPLOAD_SAFETY, - page: () => UploadSafetyPhotoPgae(), + page: () => const UploadPhotoPage(photoType: PhotoType.Safety,), binding: DetailBindings(), ), GetPage( name: UPLOAD_DROP, - page: () => UploadSafetyPhotoPgae(), + page: () => const UploadPhotoPage(photoType: PhotoType.Drop,), binding: DetailBindings(), ), GetPage( name: TRIP_COMPLETE, - page: () => const TripCompletepage(), + page: () => const TripCompletePage(), ) -]; +]; \ No newline at end of file diff --git a/vehicle-tracker/vehicle_tracker_app/lib/util/i18n_translations.dart b/vehicle-tracker/vehicle_tracker_app/lib/util/i18n_translations.dart index 26d4f1e3..a28d4ada 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/util/i18n_translations.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/util/i18n_translations.dart @@ -30,6 +30,7 @@ class AppTranslation extends Translations { static String get NAME => 'NAME'; static String get MOBILE_NUMBER => 'MOBILE_NUMBER'; static String get VIEW_DETAILS => 'VIEW_DETAILS'; + static String get NO_TASK_ASSIGNED => 'NO_TASK_ASSIGNED'; static String get START_TRIP => 'START_TRIP'; static String get END_TRIP => 'END_TRIP'; static String get TRIP_COMPLETED => 'TRIP_COMPLETED'; @@ -43,13 +44,17 @@ class AppTranslation extends Translations { static String get END_TRIP_MESSAGE => 'END_TRIP_MESSAGE'; static String get START_LOADING_MESSAGE => 'START_LOADING_MESSAGE'; static String get POSITION_SENT_MESSAGE => 'POSITION_SENT_MESSAGE'; - static String get POSITION_HIVE_STORE_MESSAGE => 'POSITION_HIVE_STORE_MESSAGE'; + static String get POSITION_HIVE_STORE_MESSAGE => + 'POSITION_HIVE_STORE_MESSAGE'; static String get NETWORK_ERROR_MESSAGE => 'NETWORK_ERROR_MESSAGE'; static String get LOGIN_SUCCESS_MESSAGE => 'LOGIN_SUCCESS_MESSAGE'; static String get LOGIN_FAILED_MESSAGE => 'LOGIN_FAILED_MESSAGE'; - static String get LOCATION_SERVICE_DISABLED_MESSAGE => 'LOCATION_SERVICE_DISABLED_MESSAGE'; - static String get LOCATION_PERMISSION_DENIED_MESSAGE => 'LOCATION_PERMISSION_DENIED_MESSAGE'; - static String get LOCATION_PERMISSION_DENIED_FOREVER_MESSAGE => 'LOCATION_PERMISSION_DENIED_FOREVER_MESSAGE'; + static String get LOCATION_SERVICE_DISABLED_MESSAGE => + 'LOCATION_SERVICE_DISABLED_MESSAGE'; + static String get LOCATION_PERMISSION_DENIED_MESSAGE => + 'LOCATION_PERMISSION_DENIED_MESSAGE'; + static String get LOCATION_PERMISSION_DENIED_FOREVER_MESSAGE => + 'LOCATION_PERMISSION_DENIED_FOREVER_MESSAGE'; static String get TRIP_NOT_END_MESSAGE => 'TRIP_NOT_END_MESSAGE'; static String get TRIP_NOT_STARTED_MESSAGE => 'TRIP_NOT_STARTED_MESSAGE'; static String get NONE_TRIP_STATUS => 'NONE_TRIP_STATUS'; @@ -61,9 +66,18 @@ class AppTranslation extends Translations { static String get DATE => 'DATE'; static String get DETAILS => 'DETAILS'; static String get STATUS => 'STATUS'; - static String get TRIP_STARTED_SUCCESFULLY_MESSAGE => 'TRIP_STARTED_SUCCESFULLY_MESSAGE'; - static String get TRIP_ENDED_SUCCESFULLY_MESSAGE => 'TRIP_ENDED_SUCCESFULLY_MESSAGE'; - + static String get TRIP_STARTED_SUCCESFULLY_MESSAGE => + 'TRIP_STARTED_SUCCESFULLY_MESSAGE'; + static String get TRIP_ENDED_SUCCESFULLY_MESSAGE => + 'TRIP_ENDED_SUCCESFULLY_MESSAGE'; + // SELECT CITY + static String get PLEASE_SELECT_CITY => "PLEASE_SELECT_CITY"; + static String get SELECT_CITY_SUB_LINE => "SELECT_CITY_SUB_LINE"; + static String get LOGIN_SUB_LINE => "LOGIN_SUB_LINE"; + static String get OTP_VERIFY => "OTP_VERIFY"; + static String get RESEND_OTP => "RESEND_OTP"; + static String get ENTER_OTP_SENT => "ENTER_OTP_SENT"; + static String get REQUEST_ANOTHER_OTP => "REQUEST_ANOTHER_OTP"; // ? This was the old way of doing translations // ? Its not here for reference, will be deleted soon @@ -123,9 +137,11 @@ class AppTranslation extends Translations { @override Map> get keys => { // English - 'en_IN': LocalizationService.englishMap, // change this to english map when english is ready + 'en_IN': LocalizationService + .englishMap, // change this to english map when english is ready // Hindi - 'or_IN': LocalizationService.orissaMap, // change this to hindi map when hindi is ready + 'or_IN': LocalizationService + .orissaMap, // change this to hindi map when hindi is ready }; } diff --git a/vehicle-tracker/vehicle_tracker_app/lib/util/toaster.dart b/vehicle-tracker/vehicle_tracker_app/lib/util/toaster.dart index b79a3619..95cbf3de 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/util/toaster.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/util/toaster.dart @@ -4,44 +4,18 @@ import 'dart:developer'; import 'package:digit_components/digit_components.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; -toaster(BuildContext? context, String message, {bool isError = false, String? error}) { - try { - if (context == null) { - Fluttertoast.showToast( - msg: message, - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - backgroundColor: isError ? Colors.red : Colors.green, - textColor: Colors.white, - fontSize: 16.0); - - log(message); - - if (error != null) { - log("Error : $error"); - } - } else { - DigitToast2.show( - context, - options: DigitToastOptions( - message, - isError, - DigitTheme.instance, - ), - ); - } - } on Exception catch (e) { - log("Normal Toast Error : $e"); - Fluttertoast.showToast( - msg: message, - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - backgroundColor: isError ? Colors.red : Colors.green, - textColor: Colors.white, - fontSize: 16.0, - ); - } +toaster(String message, + {bool isError = false, String? error}) { + DigitToast2.show( + Get.overlayContext!, + options: DigitToastOptions( + message, + isError, + DigitTheme.instance, + ), + ); } class DigitToast2 { @@ -62,7 +36,9 @@ class DigitToast2 { return ftoast.showToast( child: Container( - color: options.isError ? options.theme.colorScheme.error : options.theme.colors.darkSpringGreen, + color: options.isError + ? options.theme.colorScheme.error + : options.theme.colors.darkSpringGreen, padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), child: Row( mainAxisSize: MainAxisSize.min, diff --git a/vehicle-tracker/vehicle_tracker_app/lib/util/trip_tracker_utility.dart b/vehicle-tracker/vehicle_tracker_app/lib/util/trip_tracker_utility.dart index afb04d8d..f8564b1b 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/util/trip_tracker_utility.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/util/trip_tracker_utility.dart @@ -10,7 +10,6 @@ import 'package:vehicle_tracker_app/util/i18n_translations.dart'; import 'package:vehicle_tracker_app/util/toaster.dart'; class TripTrackerUtility { - // ? This function is to check the location permissions // ? If the location permissions are not granted, it will request for the permissions // ? If the location services are disabled, it will request to enable the services @@ -25,7 +24,7 @@ class TripTrackerUtility { log("handleLocationPermission called"); serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { - toaster(context, AppTranslation.LOCATION_SERVICE_DISABLED_MESSAGE.tr); + toaster(AppTranslation.LOCATION_SERVICE_DISABLED_MESSAGE.tr); return false; } @@ -33,12 +32,12 @@ class TripTrackerUtility { if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission == LocationPermission.denied) { - toaster(context, AppTranslation.LOCATION_PERMISSION_DENIED_MESSAGE.tr); + toaster(AppTranslation.LOCATION_PERMISSION_DENIED_MESSAGE.tr); return false; } } if (permission == LocationPermission.deniedForever) { - toaster(context, AppTranslation.LOCATION_PERMISSION_DENIED_FOREVER_MESSAGE.tr); + toaster(AppTranslation.LOCATION_PERMISSION_DENIED_FOREVER_MESSAGE.tr); return false; } @@ -49,7 +48,8 @@ class TripTrackerUtility { // ? It uses the geolocator package to get the current location Future getCurrentLocation() async { try { - return await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.best); + return await Geolocator.getCurrentPosition( + desiredAccuracy: LocationAccuracy.best); } catch (e) { log('Error getting current location: $e'); return null; diff --git a/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/info_page_widget.dart b/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/info_page_widget.dart index 378ca2e0..2642ae08 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/info_page_widget.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/info_page_widget.dart @@ -13,38 +13,21 @@ import 'status_info_widget.dart'; Widget textColumnWidget(Rx data) { return Padding( padding: DigitTheme.instance.verticalMargin, - // child: Column( - // children: [ - // textRow(AppTranslation.TRIP_ID.tr, data.value.id), - // textRow(AppTranslation.NAME.tr, data.value.operator?.name ?? ""), - // textRow(AppTranslation.VEHICLE_NUMBER.tr, data.value.operator?.contactNumber ?? ""), - // textRow(AppTranslation.PICK_UP_LOCATION.tr, data.value.routeId ?? ""), - // textRow(AppTranslation.DROP_LOCATION.tr, data.value.routeId ?? ""), - // textRow(AppTranslation.DATE.tr, data.value.plannedStartTime ?? ""), - // Row( - // children: [ - // paddedText("${AppTranslation.STATUS.tr}\t\t", bold: true), - // GetBuilder( - // id: "data.value.id", - // builder: (tripControllers) => statusInfoWidget(data.value.status ?? TripStates.NONE), - // ), - // ], - // ) - // ], - // ), - child: Table( columnWidths: const { 0: FlexColumnWidth(2), 1: FlexColumnWidth(7), }, children: [ - tableRow(AppTranslation.TRIP_ID.tr, data.value.id), - tableRow(AppTranslation.NAME.tr, data.value.citizen?.name ?? ""), - tableRow(AppTranslation.VEHICLE_NUMBER.tr, data.value.vehicle?.registrationNumber ?? ""), - tableRow(AppTranslation.PICK_UP_LOCATION.tr, data.value.pickupLocation ?? ""), - tableRow(AppTranslation.DROP_LOCATION.tr, data.value.dropLocation ?? ""), - tableRow(AppTranslation.DATE.tr, formattedDate(data.value.plannedStartTime)), + textRow(AppTranslation.TRIP_ID.tr, data.value.id), + textRow(AppTranslation.NAME.tr, data.value.citizen?.name ?? ""), + textRow(AppTranslation.VEHICLE_NUMBER.tr, + data.value.vehicle?.registrationNumber ?? ""), + textRow(AppTranslation.PICK_UP_LOCATION.tr, + data.value.pickupLocation ?? ""), + textRow(AppTranslation.DROP_LOCATION.tr, data.value.dropLocation ?? ""), + textRow( + AppTranslation.DATE.tr, formattedDate(data.value.plannedStartTime)), TableRow( children: [ paddedText("Status", bold: true), @@ -52,7 +35,8 @@ Widget textColumnWidget(Rx data) { children: [ GetBuilder( id: data.value.id, - builder: (tripControllers) => statusInfoWidget(data.value.status ?? TripStates.NOTSTARTED), + builder: (tripControllers) => statusInfoWidget( + data.value.status ?? TripStates.NOTSTARTED), ), ], ), @@ -63,14 +47,7 @@ Widget textColumnWidget(Rx data) { ); } -Widget textRow(String key, String value) => Row( - children: [ - paddedText("$key\t\t", bold: true), - Expanded(child: paddedText(value)), - ], - ); - -TableRow tableRow(String key, String value) => TableRow( +TableRow textRow(String key, String value) => TableRow( children: [ paddedText("$key\t\t", bold: true), paddedText(value), @@ -93,7 +70,7 @@ String formattedDate(String? timestamp) { } try { final date = DateTime.parse(timestamp); - return "${date.hour}:${date.minute} ${date.day}/${date.month}/${date.year}"; + return "${date.day}/${date.month}/${date.year}"; } on Exception catch (e) { log(e.toString()); return ""; diff --git a/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/toggle_switch.dart b/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/toggle_switch.dart index 77e112df..5ee4649a 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/toggle_switch.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/toggle_switch.dart @@ -5,6 +5,8 @@ import 'package:toggle_switch/toggle_switch.dart'; import 'package:vehicle_tracker_app/blocs/home/controllers/info_controllers.dart'; import 'package:vehicle_tracker_app/util/i18n_translations.dart'; +import '../../util/toaster.dart'; + Widget toggler(BuildContext context, InfoController infoController) { final theme = DigitTheme.instance; diff --git a/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/trip_button.dart b/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/trip_button.dart index ca8311df..10af201c 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/trip_button.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/trip_button.dart @@ -11,10 +11,9 @@ import '../../models/home_trip/home_trip_model/home_trip_model.dart'; import '../../util/i18n_translations.dart'; class StartTripButton extends StatelessWidget { - StartTripButton({super.key, required this.data}); + StartTripButton({Key? key, required this.data}) : super(key: key); final Rx data; - - final tripControllers = Get.find(); + final TripControllers tripControllers = Get.find(); @override Widget build(BuildContext context) { @@ -26,18 +25,11 @@ class StartTripButton extends StatelessWidget { return GetBuilder( id: data.value.id, builder: (tripControllers) { - // if (data.value.status == null) { - // return SizedBox( - // width: double.infinity, - // child: DigitOutLineButton(label: AppTranslation.NONE_TRIP.tr, onPressed: null), - // ); - // } - if (data.value.status == TripStates.LOADING) { - return Center(child: CircularProgressIndicator(color: DigitTheme.instance.colors.mangoOrange)); - } - - if (data.value.status == TripStates.ONGOING) { + return Center( + child: CircularProgressIndicator( + color: DigitTheme.instance.colors.mangoOrange)); + } else if (data.value.status == TripStates.ONGOING) { return SizedBox( width: double.infinity, child: DigitOutLineButton( @@ -47,38 +39,22 @@ class StartTripButton extends StatelessWidget { }, ), ); - } - - if (data.value.status == TripStates.COMPLETED) { - return SizedBox( - width: double.infinity, - child: DigitOutLineButton( - label: AppTranslation.TRIP_COMPLETED.tr, - onPressed: () {}, - ), + } else if (data.value.status == TripStates.COMPLETED) { + return const Offstage(); + } else { + return DigitElevatedButton( + child: Text(AppTranslation.START_TRIP.tr), + onPressed: () async { + if (tripControllers.isLoading.isTrue || + tripControllers.isRunning.isTrue) { + toaster(AppTranslation.TRIP_RUNNING_MESSAGE.tr, isError: true); + return; + } + await tripControllers.startTrip(context, data); + }, ); } - - return DigitElevatedButton( - child: Text(AppTranslation.START_TRIP.tr), - onPressed: () async { - if (tripControllers.isLoading.isTrue || tripControllers.isRunning.isTrue) { - toaster(context, AppTranslation.TRIP_RUNNING_MESSAGE.tr, isError: true); - return; - } - - await tripControllers.startTrip(context, data); - }, - ); }, ); } } - -Widget customOutlineButton() => OutlinedButton( - onPressed: () {}, - style: OutlinedButton.styleFrom( - minimumSize: const Size.fromWidth(double.infinity), - ), - child: const Text("Start Trip"), - ); diff --git a/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/trip_info_card_widget.dart b/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/trip_info_card_widget.dart index d109086e..dc765434 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/trip_info_card_widget.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/trip_info_card_widget.dart @@ -41,6 +41,7 @@ class TripInfoCardWidget extends StatelessWidget { DigitIconButton( iconText: AppTranslation.VIEW_DETAILS.tr, + textDecoration: TextDecoration.underline, icon: Icons.arrow_forward, onPressed: () => Get.toNamed(INFO, arguments: data), ), diff --git a/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/trip_info_list_widget.dart b/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/trip_info_list_widget.dart index f91b3c04..cbbea90d 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/trip_info_list_widget.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/widgets/home/trip_info_list_widget.dart @@ -1,8 +1,11 @@ import 'package:digit_components/digit_components.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:get/get.dart'; +import 'package:vehicle_tracker_app/util/i18n_translations.dart'; import '../../blocs/home/controllers/info_controllers.dart'; +import '../../util/toaster.dart'; import 'trip_info_card_widget.dart'; class TripInfoListBuilderWidget extends StatelessWidget { @@ -25,47 +28,41 @@ class TripInfoListBuilderWidget extends StatelessWidget { ); } - // ? If the search text is empty and the isCompleted is false, then the normalTripList is displayed. - if (infoController.isTextControllerEmpty.isTrue && infoController.isCompleted.isFalse) { - final list = infoController.normalTripList; - return ListView.builder( - itemCount: list.length, - itemBuilder: (context, index) { - return TripInfoCardWidget(data: list[index]); - }, - ); - } - - // ? If the search text is empty and the isCompleted is true, then the completedTripList is displayed. - if (infoController.isTextControllerEmpty.isTrue && infoController.isCompleted.isTrue) { - final list = infoController.completedTripList; - return ListView.builder( - itemCount: list.length, - itemBuilder: (context, index) { - return TripInfoCardWidget(data: list[index]); - }, - ); - } + List list; - // ? If the search text is not empty and the isCompleted is false, then the filteredNormalTripList is displayed. - if (infoController.isTextControllerEmpty.isFalse && infoController.isCompleted.isFalse) { - final list = infoController.filteredNormalTripList; - return ListView.builder( - itemCount: list.length, - itemBuilder: (context, index) { - return TripInfoCardWidget(data: list[index]); - }, - ); + if (infoController.isTextControllerEmpty.isTrue && + infoController.isCompleted.isFalse) { + list = infoController.normalTripList; + } else if (infoController.isTextControllerEmpty.isTrue && + infoController.isCompleted.isTrue) { + list = infoController.completedTripList; + } else if (infoController.isTextControllerEmpty.isFalse && + infoController.isCompleted.isFalse) { + list = infoController.filteredNormalTripList; + } else { + list = infoController.filteredCompletedTripList; } - // ? If the search text is not empty and the isCompleted is true, then the filteredCompletedTripList is displayed. - final list = infoController.filteredCompletedTripList; - return ListView.builder( - itemCount: list.length, - itemBuilder: (context, index) { - return TripInfoCardWidget(data: list[index]); - }, - ); + return list.isEmpty + ? Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + "assets/images/not_found.svg", + height: 200, + ), + Text(AppTranslation.NO_TASK_ASSIGNED), + ], + ), + ) + : ListView.builder( + itemCount: list.length, + itemBuilder: (context, index) { + return TripInfoCardWidget(data: list[index]); + }, + ); }), ), ); diff --git a/vehicle-tracker/vehicle_tracker_app/lib/widgets/login/lang_select_card.dart b/vehicle-tracker/vehicle_tracker_app/lib/widgets/login/lang_select_card.dart index 388d3593..d71dc158 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/widgets/login/lang_select_card.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/widgets/login/lang_select_card.dart @@ -5,6 +5,7 @@ import 'package:vehicle_tracker_app/router/routes.dart'; import 'package:vehicle_tracker_app/util/i18n_translations.dart'; import '../../constants.dart'; +import '../utils/languages_button_widget.dart'; class LangSelectCard extends StatelessWidget { const LangSelectCard({super.key}); @@ -17,83 +18,29 @@ class LangSelectCard extends StatelessWidget { return Padding( padding: theme.verticalMargin, child: DigitCard( - child: Column( - children: [ - // * Heading - Padding( - padding: theme.buttonPadding, - child: Row( + child: Padding( + padding: theme.buttonPadding, + child: Column( + children: [ + // * Heading + Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(AppTranslation.LOGIN.tr, style: textTheme.headlineLarge), ], ), - ), - // * Language Button - LanguageButtonWidget(theme: theme), + // * Language Button + const LanguageButtonsWidget( + bottomPadding: false, isSideBar: false), - // * Continue Button - Padding( - padding: theme.buttonPadding, - child: DigitElevatedButton(child: Text(AppTranslation.CONTINUE.tr), onPressed: () => Get.toNamed(LOGIN)), - ) - ], - ), - ), - ); - } -} - -class LanguageButtonWidget extends StatelessWidget { - const LanguageButtonWidget({ - super.key, - required this.theme, - }); - - final DigitTheme theme; - - @override - Widget build(BuildContext context) { - if (Get.locale == ENG_LOCALE) { - return Padding( - padding: theme.buttonPadding, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - DigitOutLineButton( - label: AppTranslation.ODIA.tr, - onPressed: () => Get.updateLocale(ORI_LOCALE), - ), - DigitElevatedButton( - child: Padding( - padding: theme.buttonPadding * 0.4, - child: Text(AppTranslation.ENGLISH.tr), - ), - onPressed: () => Get.updateLocale(ENG_LOCALE), - ), - ], - ), - ); - } - - return Padding( - padding: theme.buttonPadding, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - DigitElevatedButton( - child: Padding( - padding: theme.buttonPadding * 0.4, - child: Text(AppTranslation.ODIA.tr), - ), - onPressed: () => Get.updateLocale(ORI_LOCALE), + // * Continue Button + DigitElevatedButton( + child: Text(AppTranslation.CONTINUE.tr), + onPressed: () => Get.toNamed(LOGIN)) + ], ), - DigitOutLineButton( - label: AppTranslation.ENGLISH.tr, - onPressed: () => Get.updateLocale(ENG_LOCALE), - ), - ], + ), ), ); } diff --git a/vehicle-tracker/vehicle_tracker_app/lib/widgets/utils/drawer_widget.dart b/vehicle-tracker/vehicle_tracker_app/lib/widgets/utils/drawer_widget.dart index 7d60f894..030b972a 100644 --- a/vehicle-tracker/vehicle_tracker_app/lib/widgets/utils/drawer_widget.dart +++ b/vehicle-tracker/vehicle_tracker_app/lib/widgets/utils/drawer_widget.dart @@ -1,4 +1,5 @@ import 'package:digit_components/digit_components.dart'; +import 'package:digit_components/models/digit_row_card/digit_row_card_model.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:vehicle_tracker_app/data/hive_service.dart'; @@ -8,6 +9,7 @@ import '../../constants.dart'; import '../../router/routes.dart'; import '../../util/logout.dart'; import 'custom_outline_button_widget.dart'; +import 'languages_button_widget.dart'; class CustomDrawer extends StatelessWidget { const CustomDrawer({super.key}); @@ -21,7 +23,7 @@ class CustomDrawer extends StatelessWidget { return Drawer( child: ScrollableContent( header: Container( - color: DigitTheme.instance.colors.cloudGray, + color: DigitTheme.instance.colors.quillGray, padding: theme.buttonPadding, child: Padding( padding: const EdgeInsets.symmetric(vertical: kPadding * 13), @@ -50,9 +52,12 @@ class CustomDrawer extends StatelessWidget { icon: Icons.home, ), DigitIconTile( - title: Get.locale == ENG_LOCALE ? AppTranslation.ENGLISH.tr : AppTranslation.ODIA.tr, + title: Get.locale == ENG_LOCALE + ? AppTranslation.ENGLISH.tr + : AppTranslation.ODIA.tr, onPressed: () {}, - content: const LanguageButtonsWidget(), + content: const LanguageButtonsWidget( + bottomPadding: false, isSideBar: true), icon: Icons.language, ), DigitIconTile( @@ -65,42 +70,3 @@ class CustomDrawer extends StatelessWidget { ); } } - -class LanguageButtonsWidget extends StatelessWidget { - const LanguageButtonsWidget({ - super.key, - }); - - @override - Widget build(BuildContext context) { - if (Get.locale == ENG_LOCALE) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - CustomOutLineButton( - label: AppTranslation.ODIA.tr, - onPressed: () => Get.updateLocale(ORI_LOCALE), - ), - DigitElevatedButton( - child: Text(AppTranslation.ENGLISH.tr), - onPressed: () => Get.updateLocale(ENG_LOCALE), - ), - ], - ); - } - - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - DigitElevatedButton( - child: Text(AppTranslation.ODIA.tr), - onPressed: () => Get.updateLocale(ORI_LOCALE), - ), - CustomOutLineButton( - label: AppTranslation.ENGLISH.tr, - onPressed: () => Get.updateLocale(ENG_LOCALE), - ), - ], - ); - } -} diff --git a/vehicle-tracker/vehicle_tracker_app/lib/widgets/utils/languages_button_widget.dart b/vehicle-tracker/vehicle_tracker_app/lib/widgets/utils/languages_button_widget.dart new file mode 100644 index 00000000..ccd04683 --- /dev/null +++ b/vehicle-tracker/vehicle_tracker_app/lib/widgets/utils/languages_button_widget.dart @@ -0,0 +1,49 @@ +import 'package:digit_components/models/digit_row_card/digit_row_card_model.dart'; +import 'package:digit_components/widgets/digit_row_card/digit_row_card.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../constants.dart'; +import '../../util/i18n_translations.dart'; + +class LanguageButtonsWidget extends StatelessWidget { + final bool bottomPadding; + final bool isSideBar; + const LanguageButtonsWidget({ + required this.bottomPadding, + required this.isSideBar, + super.key, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only( + top: 20, + bottom: bottomPadding ? 0 : 20, + left: isSideBar ? 0 : 8, + right: isSideBar ? 0 : 8), + child: DigitRowCard( + rowItems: [ + DigitRowCardModel( + label: AppTranslation.ODIA.tr, + value: ORI_LOCALE.languageCode, + isSelected: Get.locale == ORI_LOCALE), + DigitRowCardModel( + label: AppTranslation.ENGLISH.tr, + value: ENG_LOCALE.languageCode, + isSelected: Get.locale == ENG_LOCALE), + ], + width: isSideBar + ? ((MediaQuery.of(context).size.width * 0.56 / 2) - (4 * 2)) + : ((MediaQuery.of(context).size.width * 0.76 / 2)), + onChanged: (selectedModel) { + if (selectedModel.value == ORI_LOCALE.languageCode) { + Get.updateLocale(ORI_LOCALE); + } else { + Get.updateLocale(ENG_LOCALE); + } + }), + ); + } +} diff --git a/vehicle-tracker/vehicle_tracker_app/pubspec.lock b/vehicle-tracker/vehicle_tracker_app/pubspec.lock index 2a93f8ef..8b4a57dc 100644 --- a/vehicle-tracker/vehicle_tracker_app/pubspec.lock +++ b/vehicle-tracker/vehicle_tracker_app/pubspec.lock @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.17.1" convert: dependency: transitive description: @@ -196,10 +196,9 @@ packages: digit_components: dependency: "direct main" description: - name: digit_components - sha256: "261f4407e5fe2ab3be3800dfbdc69112b632baa90f87c0e66b5c93f12e10df39" - url: "https://pub.dev" - source: hosted + path: "../packages/digit_components" + relative: true + source: path version: "0.0.1+8" fake_async: dependency: transitive @@ -419,6 +418,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.2.0" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" + url: "https://pub.dev" + source: hosted + version: "2.0.10+1" flutter_test: dependency: "direct dev" description: flutter @@ -438,7 +445,7 @@ packages: source: sdk version: "0.0.0" fluttertoast: - dependency: "direct main" + dependency: transitive description: name: fluttertoast sha256: "474f7d506230897a3cd28c965ec21c5328ae5605fc9c400cd330e9e9d6ac175c" @@ -705,10 +712,10 @@ packages: dependency: transitive description: name: intl - sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 url: "https://pub.dev" source: hosted - version: "0.18.1" + version: "0.18.0" io: dependency: transitive description: @@ -749,30 +756,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" - url: "https://pub.dev" - source: hosted - version: "10.0.0" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 - url: "https://pub.dev" - source: hosted - version: "2.0.1" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 - url: "https://pub.dev" - source: hosted - version: "2.0.1" lints: dependency: transitive description: @@ -825,26 +808,26 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.2.0" meta: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.9.1" mgrs_dart: dependency: transitive description: @@ -889,10 +872,18 @@ packages: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.8.3" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" path_provider: dependency: transitive description: @@ -941,6 +932,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.7" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + url: "https://pub.dev" + source: hosted + version: "5.4.0" + pin_input_text_field: + dependency: "direct main" + description: + name: pin_input_text_field + sha256: "8d6fc670aa673a4df5976086f0e8039972a5b2bcb783c8db8dd3b9b4b072ca90" + url: "https://pub.dev" + source: hosted + version: "4.5.1" platform: dependency: transitive description: @@ -1070,26 +1077,26 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.1" stream_transform: dependency: transitive description: @@ -1118,10 +1125,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.5.1" timing: dependency: transitive description: @@ -1162,22 +1169,38 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.7" - vector_math: + vector_graphics: dependency: transitive description: - name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + name: vector_graphics + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" url: "https://pub.dev" source: hosted - version: "2.1.4" - vm_service: + version: "1.1.11+1" + vector_graphics_codec: dependency: transitive description: - name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + name: vector_graphics_codec + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "1.1.11+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" wakelock: dependency: "direct main" description: @@ -1258,6 +1281,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + xml: + dependency: transitive + description: + name: xml + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + url: "https://pub.dev" + source: hosted + version: "6.3.0" yaml: dependency: transitive description: @@ -1267,5 +1298,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0-0 <4.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.10.0" diff --git a/vehicle-tracker/vehicle_tracker_app/pubspec.yaml b/vehicle-tracker/vehicle_tracker_app/pubspec.yaml index f74c460f..3b7018bb 100644 --- a/vehicle-tracker/vehicle_tracker_app/pubspec.yaml +++ b/vehicle-tracker/vehicle_tracker_app/pubspec.yaml @@ -19,7 +19,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: '>=3.0.2 <4.0.0' + sdk: '>=3.0.0 <4.0.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -40,7 +40,6 @@ dependencies: http: ^1.1.0 flutter_map: ^5.0.0 geolocator: ^9.0.2 - fluttertoast: ^8.2.2 latlong2: any flutter_secure_storage: ^8.0.0 digit_components: ^0.0.1+8 @@ -53,7 +52,9 @@ dependencies: image_picker: ^1.0.2 wakelock: ^0.6.2 toggle_switch: ^2.1.0 - + pin_input_text_field: ^4.5.1 + flutter_svg: ^2.0.8 + dev_dependencies: flutter_test: sdk: flutter @@ -81,6 +82,7 @@ flutter: # To add assets to your application, add an assets section, like this: assets: + - assets/images/ - .env # An image asset can refer to one or more resolution-specific "variants", see diff --git a/vehicle-tracker/vehicle_tracker_app/pubspec_overrides.yaml b/vehicle-tracker/vehicle_tracker_app/pubspec_overrides.yaml new file mode 100644 index 00000000..a4ed6c5f --- /dev/null +++ b/vehicle-tracker/vehicle_tracker_app/pubspec_overrides.yaml @@ -0,0 +1,3 @@ +dependency_overrides: + digit_components: + path: ../packages/digit_components \ No newline at end of file