Dinesh Veeran 2 éve
commit
188f2cc791
88 módosított fájl, 10267 hozzáadás és 0 törlés
  1. 47 0
      .flutter-plugins
  2. 1 0
      .flutter-plugins-dependencies
  3. 30 0
      .gitignore
  4. 10 0
      .metadata
  5. 3 0
      CHANGELOG.md
  6. 1 0
      LICENSE
  7. 39 0
      README.md
  8. 4 0
      analysis_options.yaml
  9. BIN
      generala package 12-12-23.zip
  10. 27 0
      lib/DB/db.dart
  11. 94 0
      lib/Json Example/DymanicForms.json
  12. 114 0
      lib/Json Example/DynamicFormTypes.json
  13. 66 0
      lib/Json Example/onboard.json
  14. 342 0
      lib/animated_splash_screen/animated_splash_screen.dart
  15. 266 0
      lib/apiservices/apiservices.dart
  16. 35 0
      lib/authservices/auth_service.dart
  17. 66 0
      lib/clip_shadow/clip_shadow.dart
  18. 38 0
      lib/coloredcontainer/coloredcontainer.dart
  19. 44 0
      lib/constants/constants.dart
  20. 4 0
      lib/coupon_uikit/coupon_uikit.dart
  21. 105 0
      lib/coupon_uikit/horizontal_coupon.dart
  22. 145 0
      lib/coupon_uikit/src/clippers/coupon_clipper.dart
  23. 24 0
      lib/coupon_uikit/src/painters/coupon_with_shadow_painter.dart
  24. 128 0
      lib/coupon_uikit/src/widgets/coupon_card.dart
  25. 91 0
      lib/coupon_uikit/vertical_coupen.dart
  26. 213 0
      lib/dotted_line/dotted_line.dart
  27. 158 0
      lib/draggable_fab/draggable_fab.dart
  28. 3 0
      lib/dynamic_form/dynamic_form.dart
  29. 617 0
      lib/dynamic_form/src/model/dynamic_form_model.dart
  30. 336 0
      lib/dynamic_form/src/view/dynamic_form.dart
  31. 301 0
      lib/dynamic_form/src/view/dynamic_form_button.dart
  32. 165 0
      lib/dynamic_form/src/view/dynamic_form_connectors.dart
  33. 129 0
      lib/dynamic_form/src/view/dynamic_form_date_slider.dart
  34. 64 0
      lib/dynamic_form/src/view/dynamic_form_date_time_range.dart
  35. 171 0
      lib/dynamic_form/src/view/dynamic_form_image_upload.dart
  36. 1847 0
      lib/dynamic_form/src/view/dynamic_form_input.dart
  37. 112 0
      lib/dynamic_form/src/view/dynamic_form_otp.dart
  38. 90 0
      lib/dynamic_form/src/view/dynamic_form_radio.dart
  39. 126 0
      lib/dynamic_form/src/view/dynamic_form_rating.dart
  40. 108 0
      lib/dynamic_form/src/view/dynamic_form_tab.dart
  41. 161 0
      lib/dynamic_form/src/view/dynamic_form_value_add_service.dart
  42. 260 0
      lib/dynamic_form/src/view/f_datetimerangepicker.dart
  43. 50 0
      lib/enum_to_string/camel_case_to_words.dart
  44. 105 0
      lib/enum_to_string/enum_to_string.dart
  45. 1 0
      lib/general_package.dart
  46. 159 0
      lib/get_device_info/get_device_info.dart
  47. 7 0
      lib/gradients/gradients.dart
  48. 366 0
      lib/gradients/src/gradient_painter.dart
  49. 31 0
      lib/icon_button_widget/icon_button_widget.dart
  50. 43 0
      lib/icons/gozap_icons.dart
  51. 36 0
      lib/icons/gozap_icons_old.dart
  52. 36 0
      lib/localization/app_translations.dart
  53. 25 0
      lib/localization/app_translations_delegate.dart
  54. 28 0
      lib/localization/application.dart
  55. 20 0
      lib/mainUrl_provider/mainUrl_provider.dart
  56. 92 0
      lib/onboard/DymanicForms.json
  57. 4 0
      lib/onboard/onboard.dart
  58. 89 0
      lib/onboard/onboard.json
  59. 201 0
      lib/onboard/src/model/onboard_model.dart
  60. 11 0
      lib/onboard/src/utils/constants.dart
  61. 9 0
      lib/onboard/src/utils/extensions.dart
  62. 11 0
      lib/onboard/src/utils/paddings.dart
  63. 5 0
      lib/onboard/src/utils/spaces.dart
  64. 162 0
      lib/onboard/src/view/onboard.dart
  65. 35 0
      lib/onboard/src/widgets/dots_selector.dart
  66. 281 0
      lib/onboard/src/widgets/onboard_body.dart
  67. 19 0
      lib/onboard/src/widgets/skip_button.dart
  68. 10 0
      lib/permisiion_converter/permission_converter.dart
  69. 259 0
      lib/quantity_input/quantity_input.dart
  70. 7 0
      lib/rating/rating.dart
  71. 40 0
      lib/rating/src/models/rating_config_model.dart
  72. 21 0
      lib/rating/src/models/rating_criterion_model.dart
  73. 29 0
      lib/rating/src/models/rating_model.dart
  74. 71 0
      lib/rating/src/rating_controller.dart
  75. 53 0
      lib/rating/src/rating_cubit.dart
  76. 31 0
      lib/rating/src/rating_state.dart
  77. 183 0
      lib/rating/src/rating_widget.dart
  78. 40 0
      lib/rating/src/widgets/busy_indicator.dart
  79. 44 0
      lib/rating/src/widgets/criterion_button_widget.dart
  80. 89 0
      lib/rating/src/widgets/default_button.dart
  81. 112 0
      lib/rating/src/widgets/loader_widget.dart
  82. 85 0
      lib/rating/src/widgets/stars_widget.dart
  83. 113 0
      lib/responsive/responsive.dart
  84. 64 0
      lib/themes/themes.dart
  85. 79 0
      lib/ticket_widget/ticket_widget.dart
  86. 437 0
      lib/validator/validator.dart
  87. 88 0
      pubspec.yaml
  88. 1 0
      test/general_package_test.dart

+ 47 - 0
.flutter-plugins

@@ -0,0 +1,47 @@
+# This is a generated file; do not edit or check into version control.
+connectivity_plus=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus-2.3.9\\
+connectivity_plus_linux=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_linux-1.3.1\\
+connectivity_plus_macos=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_macos-1.2.6\\
+connectivity_plus_web=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_web-1.2.5\\
+connectivity_plus_windows=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\connectivity_plus_windows-1.2.2\\
+device_info_plus=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\device_info_plus-9.1.1\\
+file_selector_linux=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\file_selector_linux-0.9.2+1\\
+file_selector_macos=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\file_selector_macos-0.9.3+3\\
+file_selector_windows=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\file_selector_windows-0.9.3+1\\
+firebase_core=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\firebase_core-2.24.2\\
+firebase_core_web=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\firebase_core_web-2.10.0\\
+firebase_messaging=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\firebase_messaging-14.7.8\\
+firebase_messaging_web=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\firebase_messaging_web-3.5.17\\
+flutter_barcode_scanner=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\flutter_barcode_scanner-2.0.0\\
+flutter_plugin_android_lifecycle=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\flutter_plugin_android_lifecycle-2.0.17\\
+fluttertoast=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\fluttertoast-8.2.4\\
+geolocator=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\geolocator-10.1.0\\
+geolocator_android=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\geolocator_android-4.4.0\\
+geolocator_apple=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\geolocator_apple-2.3.2\\
+geolocator_web=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\geolocator_web-2.2.0\\
+geolocator_windows=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\geolocator_windows-0.2.2\\
+image_picker=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\image_picker-1.0.4\\
+image_picker_android=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\image_picker_android-0.8.8+2\\
+image_picker_for_web=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\image_picker_for_web-2.2.0\\
+image_picker_ios=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\image_picker_ios-0.8.8+4\\
+image_picker_linux=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\image_picker_linux-0.2.1+1\\
+image_picker_macos=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\image_picker_macos-0.2.1+1\\
+image_picker_windows=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\image_picker_windows-0.2.1+1\\
+path_provider=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider-2.1.1\\
+path_provider_android=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_android-2.2.1\\
+path_provider_foundation=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_foundation-2.3.1\\
+path_provider_linux=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_linux-2.2.1\\
+path_provider_windows=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_windows-2.2.1\\
+permission_handler=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\permission_handler-10.4.5\\
+permission_handler_android=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\permission_handler_android-10.3.6\\
+permission_handler_apple=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\permission_handler_apple-9.1.4\\
+permission_handler_windows=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\permission_handler_windows-0.1.3\\
+shared_preferences=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\shared_preferences-2.2.2\\
+shared_preferences_android=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\shared_preferences_android-2.2.1\\
+shared_preferences_foundation=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\shared_preferences_foundation-2.3.4\\
+shared_preferences_linux=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\shared_preferences_linux-2.3.2\\
+shared_preferences_web=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\shared_preferences_web-2.2.1\\
+shared_preferences_windows=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\shared_preferences_windows-2.3.2\\
+smart_auth=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\smart_auth-1.1.1\\
+sqflite=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\sqflite-2.2.8+4\\
+webview_windows=C:\\Users\\DineshVeeran\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\webview_windows-0.2.2\\

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
.flutter-plugins-dependencies


+ 30 - 0
.gitignore

@@ -0,0 +1,30 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+.packages
+build/

+ 10 - 0
.metadata

@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+  revision: 6928314d505d2bb4777be05e45d7808a5aa91d2a
+  channel: stable
+
+project_type: package

+ 3 - 0
CHANGELOG.md

@@ -0,0 +1,3 @@
+## 0.0.1
+
+* TODO: Describe initial release.

+ 1 - 0
LICENSE

@@ -0,0 +1 @@
+TODO: Add your license here.

+ 39 - 0
README.md

@@ -0,0 +1,39 @@
+<!--
+This README describes the package. If you publish this package to pub.dev,
+this README's contents appear on the landing page for your package.
+
+For information about how to write a good package README, see the guide for
+[writing package pages](https://dart.dev/guides/libraries/writing-package-pages).
+
+For general information about developing packages, see the Dart guide for
+[creating packages](https://dart.dev/guides/libraries/create-library-packages)
+and the Flutter guide for
+[developing packages and plugins](https://flutter.dev/developing-packages).
+-->
+
+TODO: Put a short description of the package here that helps potential users
+know whether this package might be useful for them.
+
+## Features
+
+TODO: List what your package can do. Maybe include images, gifs, or videos.
+
+## Getting started
+
+TODO: List prerequisites and provide or point to information on how to
+start using the package.
+
+## Usage
+
+TODO: Include short and useful examples for package users. Add longer examples
+to `/example` folder.
+
+```dart
+const like = 'sample';
+```
+
+## Additional information
+
+TODO: Tell users more about the package: where to find more information, how to
+contribute to the package, how to file issues, what response they can expect
+from the package authors, and more.

+ 4 - 0
analysis_options.yaml

@@ -0,0 +1,4 @@
+include: package:flutter_lints/flutter.yaml
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options

BIN
generala package 12-12-23.zip


+ 27 - 0
lib/DB/db.dart

@@ -0,0 +1,27 @@
+
+import 'package:flutter/cupertino.dart';
+import 'package:encrypted_shared_preferences/encrypted_shared_preferences.dart';
+
+class LocalDB extends ChangeNotifier {
+  EncryptedSharedPreferences encryptedSharedPreferences =
+      EncryptedSharedPreferences();
+  Future<String> readData(String tableName) async {
+    final items = await encryptedSharedPreferences.getString(tableName);
+    return items;
+  }
+
+  Future<bool> writeData(String tableName, String data) async {
+    final items = await encryptedSharedPreferences.setString(tableName, data);
+    return items;
+  }
+
+  Future<bool> removeData(String tableName) async {
+    final items = encryptedSharedPreferences.remove(tableName);
+    return items;
+  }
+
+  Future<bool> removeAllData() async {
+    final isCleared = encryptedSharedPreferences.clear();
+    return isCleared;
+  }
+}

+ 94 - 0
lib/Json Example/DymanicForms.json

@@ -0,0 +1,94 @@
+{
+    "slug":"SignUP",
+    "title":"Create New Account",
+    "description":null,
+    "image":"",
+    "imageWidth":100,
+    "imageHeight":100,
+    "onSubmit":"",
+    "fields":[
+        {
+            "id":1,
+            "name":"Category",
+            "title":null,
+            "placeHolder":null,
+            "padding":8.0,
+            "type":"Radio",
+            "option":["Individual","Corporate"],
+            "value":"Individual",
+            "isRequired":true,
+            "DynamicFormFieldCondition":null
+        },
+        {
+            "id":2,
+            "name":"Name",
+            "title":"Name",
+            "placeHolder":"Enter here",
+            "padding":8.0,
+            "type":"Text",
+            "value":null,
+            "isRequired":true,
+            "DynamicFormFieldCondition":null
+        },
+        {
+            "id":3,
+            "name":"PhoneNumber",
+            "title":"Phone Number",
+            "placeHolder":"Enter here",
+            "padding":8.0,
+            "type":"PhoneNumber",
+            "value":null,
+            "isRequired":true,
+            "DynamicFormFieldCondition":null
+        },
+        {
+            "id":4,
+            "name":"EmailAddress",
+            "title":"Email Address",
+            "placeHolder":"Enter here",
+            "padding":8.0,
+            "type":"Email",
+            "value":null,
+            "isRequired":true,
+            "DynamicFormFieldCondition":null
+        },
+        {
+            "id":5,
+            "name":"Password",
+            "title":"Password",
+            "placeHolder":"Enter here",
+            "padding":8.0,
+            "type":"Password",
+            "value":null,
+            "isRequired":true,
+            "DynamicFormFieldCondition":null
+        },
+        {
+            "id":6,
+            "name":"DEID",
+            "title":"DE ID",
+            "placeHolder":"Enter here",
+            "padding":8.0,
+            "type":"Email",
+            "value":null,
+            "isRequired":true,
+            "DynamicFormFieldCondition": {
+                "id":1,
+                "EqualValue":"Corporate",
+                "RunTimeTypeForID":"int",
+                "RunTimeTypeForValue":"String"
+            }
+        },
+        {
+            "id":7,
+            "name":"ReferID",
+            "title":"Refer ID",
+            "placeHolder":"Enter here",
+            "padding":8.0,
+            "type":"Text",
+            "value":null,
+            "isRequired":true,
+            "DynamicFormFieldCondition":null
+        }
+    ]
+}

+ 114 - 0
lib/Json Example/DynamicFormTypes.json

@@ -0,0 +1,114 @@
+[
+    {
+        "typeID": 1,
+        "type": "Text",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 2,
+        "type": "PhoneNumber",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 3,
+        "type": "Radio",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 4,
+        "type": "Email",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 5,
+        "type": "Dropdown",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 6,
+        "type": "Date",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 7,
+        "type": "DateTime",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 8,
+        "type": "DateRange",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 9,
+        "type": "Time",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 10,
+        "type": "DateRange",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 11,
+        "type": "RangeSlider",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 12,
+        "type": "SwitchInput",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 13,
+        "type": "checkbox",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 14,
+        "type": "segmented",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 15,
+        "type": "chipsSingle",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    },
+    {
+        "typeID": 16,
+        "type": "chipsMultiple",
+        "DynamicFormFieldIsActive": true,
+        "DynamicFormFieldCreatedAt": "29/11/2022",
+        "DynamicFormFieldUpdatedAt": "29/11/2022"
+    }
+]

+ 66 - 0
lib/Json Example/onboard.json

@@ -0,0 +1,66 @@
+{
+    "AppIconURL":"",
+    "SplashScreenImageURL":"",
+    "OnBoard":[
+        {
+            "OnBoardTitle":"",
+            "OnBoardDescription":"",
+            "OnBoardImageURL":""
+        },
+        {
+            "OnBoardTitle":"",
+            "OnBoardDescription":"",
+            "OnBoardImageURL":""
+        },
+        {
+            "OnBoardTitle":"",
+            "OnBoardDescription":"",
+            "OnBoardImageURL":""
+        }
+    ],
+    "Permission":[
+        {
+            "PermissionTitle":"",
+            "PermissionImageURL":"",
+            "PermissionRequest":"Location",
+            "PermissionListDescription":[
+                {
+                    "PermissionListDescriptionTitle":"",
+                    "PermissionListDescriptionImageURL":""
+                },
+                {
+                    "PermissionListDescriptionTitle":"",
+                    "PermissionListDescriptionImageURL":""
+                }
+            ]
+        },{
+            "PermissionTitle":"",
+            "PermissionImageURL":"",
+            "PermissionRequest":"Camera",
+            "PermissionListDescription":[
+                {
+                    "PermissionListDescriptionTitle":"",
+                    "PermissionListDescriptionImageURL":""
+                },
+                {
+                    "PermissionListDescriptionTitle":"",
+                    "PermissionListDescriptionImageURL":""
+                }
+            ]
+        },{
+            "PermissionTitle":"",
+            "PermissionImageURL":"",
+            "PermissionRequest":"Storage",
+            "PermissionListDescription":[
+                {
+                    "PermissionListDescriptionTitle":"",
+                    "PermissionListDescriptionImageURL":""
+                },
+                {
+                    "PermissionListDescriptionTitle":"",
+                    "PermissionListDescriptionImageURL":""
+                }
+            ]
+        }
+    ]
+}

+ 342 - 0
lib/animated_splash_screen/animated_splash_screen.dart

@@ -0,0 +1,342 @@
+// ignore_for_file: depend_on_referenced_packages
+
+library animated_splash_screen;
+
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:page_transition/page_transition.dart';
+
+enum SplashType { simpleSplash, backgroundScreenReturn }
+
+enum SplashTransition {
+  slideTransition,
+  scaleTransition,
+  rotationTransition,
+
+  sizeTransition,
+  fadeTransition,
+  decoratedBoxTransition
+}
+
+class AnimatedSplashScreen extends StatefulWidget {
+  /// Type of page transition
+  final PageTransitionType transitionType;
+
+  /// Type of splash transition
+  final SplashTransition splashTransition;
+
+  /// Only required while using [AnimatedSplashScreen.withScreenFunction]
+  /// here you pass your function that needs to be called before jumping
+  /// on to the next screen
+  final Future Function()? function;
+
+  /// Custom animation to icon of splash
+  final Animatable? customAnimation;
+
+  /// Background color
+  final Color backgroundColor;
+
+  /// Compulsory in default constructor.
+  /// Here you pass your widget that will be browsed
+  final Widget? nextScreen;
+
+  /// Type of AnimatedSplashScreen
+  final SplashType type;
+
+  /// to make the icon in [Center] of splash
+  final bool centered;
+
+  /// If you want to implement the navigation to the next page yourself.
+  /// By default this is [false], the widget will call Navigator.of(_context).pushReplacement()
+  /// using PageTransition with [transitionType] after [duration] to [nextScreen]
+  final bool disableNavigation;
+
+  /// It can be string for [Image.asserts], normal [Widget] or you can user tags
+  /// to choose which one you image type, for example:
+  /// * '[n]www.my-site.com/my-image.png' to [Image.network]
+  final dynamic splash;
+
+  /// Time in milliseconds after splash animation to jump to next screen
+  /// Default is [milliseconds: 2500], minimum is [milliseconds: 100]
+  final int duration;
+
+  /// Curve of splash animation
+  final Curve curve;
+
+  /// Splash animation duration, default is [milliseconds: 800]
+  final Duration? animationDuration;
+
+  /// Size of an icon in splash screen
+  final double? splashIconSize;
+
+  /// Here you pass your route that will be browsed
+  final String? nextRoute;
+
+  factory AnimatedSplashScreen(
+      {Curve curve = Curves.easeInCirc,
+      Future Function()? function,
+      int duration = 2500,
+      required dynamic splash,
+      required Widget nextScreen,
+      Color backgroundColor = Colors.white,
+      Animatable? customTween,
+      bool centered = true,
+      bool disableNavigation = false,
+      SplashTransition? splashTransition,
+      PageTransitionType? pageTransitionType,
+      Duration? animationDuration,
+      double? splashIconSize,
+      String? nextRoute}) {
+    return AnimatedSplashScreen._internal(
+      backgroundColor: backgroundColor,
+      animationDuration: animationDuration,
+      transitionType: pageTransitionType ?? PageTransitionType.bottomToTop,
+      splashTransition: splashTransition ?? SplashTransition.fadeTransition,
+      splashIconSize: splashIconSize,
+      customAnimation: customTween,
+      function: function,
+      nextRoute: nextRoute,
+      duration: duration,
+      centered: centered,
+      disableNavigation: disableNavigation,
+      splash: splash,
+      type: SplashType.simpleSplash,
+      nextScreen: nextScreen,
+      curve: curve,
+    );
+  }
+
+  factory AnimatedSplashScreen.withScreenFunction({
+    Curve curve = Curves.easeInCirc,
+    bool centered = true,
+    bool disableNavigation = false,
+    int duration = 2500,
+    required dynamic splash,
+    required Future<Widget> Function() screenFunction,
+    Animatable? customTween,
+    Color backgroundColor = Colors.white,
+    SplashTransition? splashTransition,
+    PageTransitionType? pageTransitionType,
+    Duration? animationDuration,
+    double? splashIconSize,
+  }) {
+    return AnimatedSplashScreen._internal(
+      type: SplashType.backgroundScreenReturn,
+      animationDuration: animationDuration,
+      transitionType: pageTransitionType ?? PageTransitionType.bottomToTop,
+      splashTransition: splashTransition ?? SplashTransition.fadeTransition,
+      backgroundColor: backgroundColor,
+      splashIconSize: splashIconSize,
+      customAnimation: customTween,
+      function: screenFunction,
+      duration: duration,
+      centered: centered,
+      disableNavigation: disableNavigation,
+      nextRoute: null,
+      nextScreen: null,
+      splash: splash,
+      curve: curve,
+    );
+  }
+
+  factory AnimatedSplashScreen.withScreenRouteFunction({
+    Curve curve = Curves.easeInCirc,
+    bool centered = true,
+    bool disableNavigation = false,
+    int duration = 2500,
+    required dynamic splash,
+    required Future<String> Function() screenRouteFunction,
+    Animatable? customTween,
+    Color backgroundColor = Colors.white,
+    SplashTransition? splashTransition,
+    PageTransitionType? pageTransitionType,
+    Duration? animationDuration,
+    double? splashIconSize,
+  }) {
+    return AnimatedSplashScreen._internal(
+      type: SplashType.backgroundScreenReturn,
+      animationDuration: animationDuration,
+      transitionType: pageTransitionType ?? PageTransitionType.bottomToTop,
+      splashTransition: splashTransition ?? SplashTransition.fadeTransition,
+      backgroundColor: backgroundColor,
+      splashIconSize: splashIconSize,
+      customAnimation: customTween,
+      function: screenRouteFunction,
+      duration: duration,
+      centered: centered,
+      disableNavigation: disableNavigation,
+      nextRoute: null,
+      nextScreen: null,
+      splash: splash,
+      curve: curve,
+    );
+  }
+
+  AnimatedSplashScreen._internal(
+      {required this.animationDuration,
+      required this.splashTransition,
+      required this.customAnimation,
+      required this.backgroundColor,
+      required this.transitionType,
+      required this.splashIconSize,
+      required this.nextScreen,
+      required this.function,
+      required this.duration,
+      required this.centered,
+      required this.disableNavigation,
+      required this.splash,
+      required this.curve,
+      required this.type,
+      required this.nextRoute});
+
+  @override
+  _AnimatedSplashScreenState createState() => _AnimatedSplashScreenState();
+}
+
+class _AnimatedSplashScreenState extends State<AnimatedSplashScreen>
+    with SingleTickerProviderStateMixin {
+  late AnimationController _animationController;
+  static late BuildContext _context;
+  late Animation _animation;
+
+  AnimatedSplashScreen get w => widget;
+
+  @override
+  void initState() {
+    super.initState();
+
+    _animationController = new AnimationController(
+        duration: w.animationDuration ?? Duration(milliseconds: 800),
+        vsync: this);
+
+    Animatable animation = w.customAnimation ??
+        () {
+          switch (w.splashTransition) {
+            case SplashTransition.slideTransition:
+              return Tween<Offset>(
+                end: Offset.zero,
+                begin: Offset(1, 0),
+              );
+
+            case SplashTransition.decoratedBoxTransition:
+              return DecorationTween(
+                  end: BoxDecoration(color: Colors.black87),
+                  begin: BoxDecoration(color: Colors.redAccent));
+
+            default:
+              return Tween(begin: 0.0, end: 1.0);
+          }
+        }() as Animatable<dynamic>;
+
+    _animation = animation
+        .animate(CurvedAnimation(parent: _animationController, curve: w.curve));
+    _animationController.forward().then((value) => doTransition());
+  }
+
+  /// call function case needed and then jump to next screen
+  doTransition() async {
+    if (w.type == SplashType.backgroundScreenReturn)
+      navigator(await w.function!());
+    else if (!w.disableNavigation) navigator(w.nextRoute ?? w.nextScreen);
+  }
+
+  @override
+  void dispose() {
+    _animationController.reset();
+    _animationController.dispose();
+    super.dispose();
+  }
+
+  navigator(screen) {
+    Future.delayed(Duration(milliseconds: w.duration < 100 ? 100 : w.duration))
+        .then((_) {
+      try {
+        if (screen is String) {
+          // Navigator.of(_context).pushReplacementNamed(screen);
+          Get.offAllNamed(screen);
+        } else {
+          Get.offAll(screen);
+          // Navigator.of(context).push(
+          //   MaterialPageRoute(
+          //     builder: (BuildContext context) {
+          //       return screen;
+          //     },
+              
+          //   ),
+          // );
+          // Navigator.of(_context).pushReplacement(
+          //     PageTransition(type: w.transitionType, child: screen));
+        }
+      } catch (msg) {
+        print('AnimatedSplashScreen -> '
+            'error in jump to next screen, probably '
+            'this run is in hot reload: $msg');
+      }
+    });
+  }
+
+  /// Return icon of splash screen
+  Widget getSplash() {
+    final size =
+        w.splashIconSize ?? MediaQuery.of(context).size.shortestSide * 0.2;
+
+    Widget main({required Widget child}) =>
+        w.centered ? Center(child: child) : child;
+
+    return getTransition(
+        child: main(
+            child: SizedBox(
+                height: size,
+                child: w.splash is String
+                    ? <Widget>() {
+                        if (w.splash.toString().contains('[n]'))
+                          return Image.network(
+                              w.splash.toString().replaceAll('[n]', ''));
+                        else
+                          return Image.asset(w.splash);
+                      }()
+                    : (w.splash is IconData
+                        ? Icon(w.splash, size: size)
+                        : w.splash))));
+  }
+
+  /// return transtion
+  Widget getTransition({required Widget child}) {
+    switch (w.splashTransition) {
+      case SplashTransition.slideTransition:
+        return SlideTransition(
+            position: (_animation as Animation<Offset>), child: child);
+
+      case SplashTransition.scaleTransition:
+        return ScaleTransition(
+            scale: (_animation as Animation<double>), child: child);
+
+      case SplashTransition.rotationTransition:
+        return RotationTransition(
+            turns: (_animation as Animation<double>), child: child);
+
+      case SplashTransition.sizeTransition:
+        return SizeTransition(
+            sizeFactor: (_animation as Animation<double>), child: child);
+
+      case SplashTransition.fadeTransition:
+        return FadeTransition(
+            opacity: (_animation as Animation<double>), child: child);
+
+      case SplashTransition.decoratedBoxTransition:
+        return DecoratedBoxTransition(
+            decoration: (_animation as Animation<Decoration>), child: child);
+
+      default:
+        return FadeTransition(
+            opacity: (_animation as Animation<double>), child: child);
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    _context = context;
+
+    return Scaffold(backgroundColor: w.backgroundColor, body: getSplash());
+  }
+}

+ 266 - 0
lib/apiservices/apiservices.dart

@@ -0,0 +1,266 @@
+// ignore_for_file: unnecessary_question_mark, non_constant_identifier_names, unused_local_variable, prefer_interpolation_to_compose_strings, use_build_context_synchronously
+
+import 'dart:io';
+import 'dart:convert';
+import 'package:fluttertoast/fluttertoast.dart';
+import 'package:general_package/get_device_info/get_device_info.dart';
+import 'package:general_package/mainUrl_provider/mainUrl_provider.dart';
+import 'package:geolocator/geolocator.dart';
+import 'package:get/get.dart';
+import 'package:provider/provider.dart';
+// import 'package:toast/toast.dart';
+import 'package:flutter/material.dart';
+import 'package:http/http.dart' as http;
+import 'package:connectivity_plus/connectivity_plus.dart';
+import 'package:flutter/foundation.dart';
+import 'dart:developer' as logDev;
+import 'package:intl/intl.dart';
+
+import '../authservices/auth_service.dart';
+
+class APIService {
+  BuildContext context;
+  APIService(this.context);
+  Future<bool> GetConnect() async {
+    var connectivityResult = await (Connectivity().checkConnectivity());
+    bool isInternetOn = false;
+    if (connectivityResult == ConnectivityResult.none) {
+      isInternetOn = false;
+    } else if (connectivityResult == ConnectivityResult.mobile) {
+      isInternetOn = true;
+    } else if (connectivityResult == ConnectivityResult.wifi) {
+      isInternetOn = true;
+    }
+    return isInternetOn;
+  }
+
+  getMainURL() {
+    String mainURL =
+        Provider.of<mainURLChangeNotifier>(context, listen: false).mainURL;
+    return mainURL;
+  }
+
+  Future<Position?> determinePosition() async {
+    bool serviceEnabled;
+    LocationPermission permission;
+
+    permission = await Geolocator.checkPermission();
+    if (permission == LocationPermission.denied) {
+      permission = await Geolocator.requestPermission();
+      if (permission == LocationPermission.denied) {
+        // Permissions are denied, next time you could try
+        // requesting permissions again (this is also where
+        // Android's shouldShowRequestPermissionRationale
+        // returned true. According to Android guidelines
+        // your App should show an explanatory UI now.
+        Future.error('Location permissions are denied');
+      }
+    }
+    if (permission == LocationPermission.deniedForever) {
+      // Permissions are denied forever, handle appropriately.
+      Future.error(
+          'Location permissions are permanently denied, we cannot request permissions.');
+    }
+
+    // Test if location services are enabled.
+    serviceEnabled = await Geolocator.isLocationServiceEnabled();
+    if (!serviceEnabled) {
+      // Location services are not enabled don't continue
+      // accessing the position and request users of the
+      // App to enable the location services.
+      // return Future.error('Location services are disabled.');
+      Position? position = await Geolocator.getLastKnownPosition();
+      if (position != null) {
+        return position;
+      }
+      Future.error('Location services are disabled.');
+    }
+    // When we reach here, permissions are granted and we can
+    // continue accessing the position of the device.
+    return await Geolocator.getCurrentPosition();
+  }
+
+  Future<dynamic?> getData(String? url) async {
+    try {
+      Future<bool> internetActive = GetConnect();
+
+      if (await internetActive) {
+        print("API Service Started");
+        String mainURL =
+            Provider.of<mainURLChangeNotifier>(context, listen: false).mainURL;
+        var dURL = mainURL + url!;
+        print(dURL);
+        print("Get Device Info Started");
+        var deviceInfo = await DeviceInfo()
+            .getDeviceInfo(Get.currentRoute, Get.previousRoute);
+        print("Get Device Info Ended");
+        var header = <String, String>{
+          'Content-Type': 'application/json; charset=UTF-8',
+          'Accept': 'application/json',
+        };
+        header.addAll(deviceInfo);
+
+        if (authService.token.isNotEmpty) {
+          header.addAll({"Authorization": "Bearer ${authService.token}"});
+        }
+        print(header);
+
+        final response = await http.get(Uri.parse(dURL), headers: header);
+        if (kDebugMode) {
+          print(response.body);
+          // logDev.log(response.body);
+        }
+        if (response.statusCode == 200 || response.statusCode == 201) {
+          dynamic res = json.decode(response.body);
+
+          if (res["message"] != null) {
+            if (res["message"].toString().isNotEmpty) {
+              Fluttertoast.showToast(
+                  msg: res["message"],
+                  toastLength: Toast.LENGTH_LONG,
+                  gravity: ToastGravity.BOTTOM,
+                  timeInSecForIosWeb: 1,
+                  backgroundColor: Colors.green,
+                  webPosition: "center",
+                  webBgColor: "#008000",
+                  textColor: Colors.white,
+                  fontSize: 16.0);
+            }
+          }
+          return res;
+        } else {
+          dynamic res = json.decode(response.body);
+
+          if (response.statusCode == 401) {
+            authService.logout("/homeScreenView");
+          }
+          if (res["message"] != null) {
+            FToast().init(context);
+            FToast().showToast(child: const Text("data"));
+            Fluttertoast.showToast(
+                msg: res["message"].toString(),
+                toastLength: Toast.LENGTH_LONG,
+                gravity: ToastGravity.BOTTOM,
+                timeInSecForIosWeb: 1,
+                backgroundColor: Colors.red,
+                textColor: Colors.white,
+                webPosition: "center",
+                webBgColor: "#FF0000",
+                fontSize: 16.0);
+          }
+        }
+        print("API Service Ended");
+      }
+    } on SocketException catch (_) {
+      Fluttertoast.showToast(
+          msg: "Please check your internet",
+          toastLength: Toast.LENGTH_LONG,
+          gravity: ToastGravity.BOTTOM,
+          timeInSecForIosWeb: 1,
+          backgroundColor: Colors.red,
+          textColor: Colors.white,
+          webPosition: "center",
+          webBgColor: "#FF0000",
+          fontSize: 16.0);
+    }
+    return null;
+  }
+
+  Future<dynamic?> postData(
+    String? url,
+    Map<String, dynamic> data,
+  ) async {
+    try {
+      bool internetActive = await GetConnect();
+      if (internetActive) {
+        print("API Service Started");
+        String mainURL =
+            Provider.of<mainURLChangeNotifier>(context, listen: false).mainURL;
+        var dURL = mainURL + url!;
+        print(dURL);
+        print("Get Device Info Started");
+        var deviceInfo = await DeviceInfo()
+            .getDeviceInfo(Get.currentRoute, Get.previousRoute);
+        print("Get Device Info Ended");
+        var header = <String, String>{
+          'Content-Type': 'application/json; charset=UTF-8',
+          'Accept': 'application/json',
+        };
+        header.addAll(deviceInfo);
+
+        if (authService.token.isNotEmpty) {
+          header.addAll({"Authorization": "Bearer ${authService.token}"});
+        }
+        print(header);
+        data.forEach((key, value) {
+          if (value.runtimeType == DateTime) {
+            // data[key]=value.toIso8601String();
+            data[key] = DateFormat('dd-MM-yyyy hh:mm:ss a').format(value);
+          }
+        });
+        var body = json.encode(data);
+        if (kDebugMode) {
+          print(dURL);
+          print(body);
+        }
+        final response =
+            await http.post(Uri.parse(dURL), headers: header, body: body);
+        if (kDebugMode) {
+          print(response.body);
+          // logDev.log(response.body);
+        }
+        if (response.body != null ||
+            response.body.isNotEmpty ||
+            response.body != " ") {
+          if (response.statusCode == 200 || response.statusCode == 201) {
+            dynamic res = json.decode(response.body);
+            if (res["message"] != null) {
+              if (res["message"].toString().isNotEmpty) {
+                Fluttertoast.showToast(
+                    msg: res["message"],
+                    toastLength: Toast.LENGTH_LONG,
+                    gravity: ToastGravity.BOTTOM,
+                    timeInSecForIosWeb: 1,
+                    backgroundColor: Colors.green,
+                    textColor: Colors.white,
+                    webPosition: "center",
+                    webBgColor: "#008000",
+                    fontSize: 16.0);
+              }
+            }
+            return res;
+          } else {
+            if (response.statusCode == 401) {
+              authService.logout("/homeScreenView");
+            }
+            dynamic res = json.decode(response.body);
+            if (res["message"] != null) {
+              Fluttertoast.showToast(
+                  msg: res["message"].toString(),
+                  toastLength: Toast.LENGTH_LONG,
+                  gravity: ToastGravity.BOTTOM,
+                  timeInSecForIosWeb: 1,
+                  backgroundColor: Colors.red,
+                  textColor: Colors.white,
+                  webPosition: "center",
+                  webBgColor: "#FF0000",
+                  fontSize: 16.0);
+            }
+          }
+        }
+        print("API Service Ended");
+      }
+    } on SocketException catch (_) {
+      Fluttertoast.showToast(
+          msg: "Please check your internet",
+          toastLength: Toast.LENGTH_LONG,
+          gravity: ToastGravity.BOTTOM,
+          timeInSecForIosWeb: 1,
+          backgroundColor: Colors.red,
+          textColor: Colors.white,
+          webPosition: "center",
+          webBgColor: "#FF0000",
+          fontSize: 16.0);
+    }
+  }
+}

+ 35 - 0
lib/authservices/auth_service.dart

@@ -0,0 +1,35 @@
+// ignore_for_file: non_constant_identifier_names
+
+import 'package:get/get.dart';
+import 'package:get_storage/get_storage.dart';
+
+class AuthService extends GetxService {
+  static AuthService get to => Get.find();
+  final box = GetStorage();
+
+  /// Mocks a login process
+  final _token = ''.obs;
+  String get token => box.read('token') ?? _token.value;
+  final isLoggedIn = false.obs;
+  bool get isLoggedInValue => box.read('auth') ?? isLoggedIn.value;
+  
+
+
+  void login(newToken) {
+    isLoggedIn.value = true;
+    _token.value = newToken;
+    box.write('auth', true);
+    box.write('token', newToken);
+  }
+
+  void logout(String logoutURL) {
+    isLoggedIn.value = false;
+    box.write('auth', false);
+    _token.value = '';
+    box.write('token', '');
+
+    Get.offAllNamed(logoutURL);
+  }
+}
+
+final authService = Get.put(AuthService());

+ 66 - 0
lib/clip_shadow/clip_shadow.dart

@@ -0,0 +1,66 @@
+library clip_shadow;
+
+import 'package:flutter/widgets.dart';
+
+class _ClipShadowPainter extends CustomPainter {
+  /// If non-null, determines which clip to use.
+  final CustomClipper<Path> clipper;
+
+  /// A list of shadows cast by this box behind the box.
+  final List<BoxShadow> clipShadow;
+
+  _ClipShadowPainter({
+    required this.clipper,
+    required this.clipShadow
+  });
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    clipShadow.forEach((BoxShadow shadow) {
+      var paint = shadow.toPaint();
+      var spreadSize = Size(size.width + shadow.spreadRadius * 2, size.height + shadow.spreadRadius * 2);
+      var clipPath = clipper.getClip(spreadSize).shift(Offset(
+          shadow.offset.dx - shadow.spreadRadius,
+          shadow.offset.dy - shadow.spreadRadius
+      ));
+      canvas.drawPath(clipPath, paint);
+//      canvas.drawShadow(clipper.getClip(size), shadow.color, shadow.spreadRadius, true);
+    });
+  }
+
+  @override
+  bool shouldRepaint(CustomPainter oldDelegate) {
+    return true;
+  }
+}
+
+class ClipShadow extends StatelessWidget {
+  /// A list of shadows cast by this box behind the box.
+  final List<BoxShadow> boxShadow;
+
+  /// If non-null, determines which clip to use.
+  final CustomClipper<Path> clipper;
+
+  /// The [Widget] below this widget in the tree.
+  final Widget child;
+
+  ClipShadow({
+    required this.boxShadow,
+    required this.clipper,
+    required this.child
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return CustomPaint(
+      painter: _ClipShadowPainter(
+          clipShadow: boxShadow,
+          clipper: clipper
+      ),
+      child: ClipPath(
+        clipper: clipper,
+        child: child,
+      ),
+    );
+  }
+}

+ 38 - 0
lib/coloredcontainer/coloredcontainer.dart

@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+
+class ColoredContainer extends StatefulWidget {
+  ColoredContainer({Key? key, this.child, this.containerColor,this.containerGradient,this.width,this.height,this.padding,this.margin})
+      : super(key: key);
+
+  final Color? containerColor;
+  final Gradient? containerGradient;
+  final double? width;
+  final double? height;
+  final Widget? child;
+  EdgeInsetsGeometry? padding;
+  EdgeInsetsGeometry? margin;
+
+  @override
+  State<ColoredContainer> createState() => _ColoredContainerState();
+}
+
+class _ColoredContainerState extends State<ColoredContainer> {
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: widget.padding,
+      margin: widget.margin,
+      width: widget.width,
+      height: widget.height,
+      decoration: BoxDecoration(
+        borderRadius: BorderRadius.circular(10.0),
+        color: widget.containerColor,
+        gradient: widget.containerGradient
+      ),
+      child: Padding(
+        padding: const EdgeInsets.all(10.00),
+        child: widget.child,
+      ),
+    );
+  }
+}

+ 44 - 0
lib/constants/constants.dart

@@ -0,0 +1,44 @@
+import 'package:flutter/material.dart';
+
+class GeneralConstants {
+  static GeneralConstants? _instance;
+  static GeneralConstants get instance => _instance ??= GeneralConstants._init();
+  // static double get baseWidth => 360;
+  // static Size get screenSize => WidgetsBinding.instance.window.physicalSize;
+  // static double get fem => screenSize.width / baseWidth;
+  // static double get ffem => fem * 0.97;
+  // static EdgeInsets get padding => const EdgeInsets.all(10.0);
+  GeneralConstants._init();
+  static get(BuildContext context) {
+    EdgeInsets padding = const EdgeInsets.all(10.0);
+    double baseWidth = 360;
+    double fem = MediaQuery.of(context).size.width / baseWidth;
+    double ffem = fem * 0.97;
+  }
+  var padding5 = const EdgeInsets.all(5.0);
+  var padding10 = const EdgeInsets.all(10.0);
+  var padding15 = const EdgeInsets.all(15.0);
+  var padding20 = const EdgeInsets.all(20.0);
+  var paddingSymmetric5 = const EdgeInsets.symmetric(vertical:5.0 ,horizontal :2.0);
+  var paddingSymmetric10 = const EdgeInsets.symmetric(vertical:10.0 ,horizontal :5.0);
+  var paddingSymmetric20 = const EdgeInsets.symmetric(vertical:20.0 ,horizontal :10.0);
+  var paddingSymmetricN5 = const EdgeInsets.symmetric(vertical:2.5 ,horizontal :5.0);
+  var paddingSymmetricN10 = const EdgeInsets.symmetric(vertical:5.0 ,horizontal :10.0);
+  var paddingSymmetricN20 = const EdgeInsets.symmetric(vertical:10.0 ,horizontal :20.0);
+  var margin5 = const EdgeInsets.all(5.0);
+  var margin10 = const EdgeInsets.all(10.0);
+  var margin20 = const EdgeInsets.all(20.0);
+  var marginSymmetric5 = const EdgeInsets.symmetric(vertical:5.0 ,horizontal :2.5);
+  var marginSymmetric10 = const EdgeInsets.symmetric(vertical:10.0 ,horizontal :5.0);
+  var marginSymmetric20 = const EdgeInsets.symmetric(vertical:20.0 ,horizontal :10.0);
+  var marginSymmetricN5 = const EdgeInsets.symmetric(vertical:2.5 ,horizontal :5.0);
+  var marginSymmetricN10 = const EdgeInsets.symmetric(vertical:5.0 ,horizontal :10.0);
+  var marginSymmetricN20 = const EdgeInsets.symmetric(vertical:10.0 ,horizontal :20.0);
+  var sizedBoxHeight5 = const SizedBox(height: 5);
+  var sizedBoxHeight10 = const SizedBox(height: 10);
+  var sizedBoxHeight20 = const SizedBox(height: 20);
+  var sizedBoxWidth5 = const SizedBox(width: 5);
+  var sizedBoxWidth10 = const SizedBox(width: 10);
+  var sizedBoxWidth20 = const SizedBox(width: 20);
+  var onBoardScreenShowedKey="onBoardScreenShowedKey";
+}

+ 4 - 0
lib/coupon_uikit/coupon_uikit.dart

@@ -0,0 +1,4 @@
+library coupon_uikit;
+
+export 'src/clippers/coupon_clipper.dart';
+export 'src/widgets/coupon_card.dart';

+ 105 - 0
lib/coupon_uikit/horizontal_coupon.dart

@@ -0,0 +1,105 @@
+
+import 'coupon_uikit.dart';
+import 'package:flutter/material.dart';
+
+class HorizontalCouponExample1 extends StatelessWidget {
+  const HorizontalCouponExample1({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    const Color secondaryColor = Color(0xffcbf3f0);
+    const Color primaryColor = Color(0xff368f8b);
+
+    return CouponCard(
+      height: 150,
+      backgroundColor: secondaryColor,
+      curveAxis: Axis.vertical,
+      firstChild: Container(
+        decoration: const BoxDecoration(
+          color: primaryColor,
+        ),
+        child: Column(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: [
+            Expanded(
+              child: Center(
+                child: Column(
+                  mainAxisSize: MainAxisSize.min,
+                  children: const [
+                    Text(
+                      '23%',
+                      style: TextStyle(
+                        color: Colors.white,
+                        fontSize: 24,
+                        fontWeight: FontWeight.bold,
+                      ),
+                    ),
+                    Text(
+                      'OFF',
+                      style: TextStyle(
+                        color: Colors.white,
+                        fontSize: 16,
+                        fontWeight: FontWeight.bold,
+                      ),
+                    ),
+                  ],
+                ),
+              ),
+            ),
+            const Divider(color: Colors.white54, height: 0),
+            const Expanded(
+              child: Center(
+                child: Text(
+                  'WINTER IS\nHERE',
+                  textAlign: TextAlign.center,
+                  style: TextStyle(
+                    color: Colors.white,
+                    fontSize: 12,
+                    fontWeight: FontWeight.bold,
+                  ),
+                ),
+              ),
+            ),
+          ],
+        ),
+      ),
+      secondChild: Container(
+        width: double.maxFinite,
+        padding: const EdgeInsets.all(18),
+        child: Column(
+          mainAxisSize: MainAxisSize.min,
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: const [
+            Text(
+              'Coupon Code',
+              textAlign: TextAlign.center,
+              style: TextStyle(
+                fontSize: 13,
+                fontWeight: FontWeight.bold,
+                color: Colors.black54,
+              ),
+            ),
+            SizedBox(height: 4),
+            Text(
+              'FREESALES',
+              textAlign: TextAlign.center,
+              style: TextStyle(
+                fontSize: 24,
+                color: primaryColor,
+                fontWeight: FontWeight.bold,
+              ),
+            ),
+            Spacer(),
+            Text(
+              'Valid Till - 30 Jan 2022',
+              textAlign: TextAlign.center,
+              style: TextStyle(
+                color: Colors.black45,
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 145 - 0
lib/coupon_uikit/src/clippers/coupon_clipper.dart

@@ -0,0 +1,145 @@
+import 'package:flutter/material.dart';
+
+/// Clips a widget to the form of a coupon card shape
+class CouponClipper extends CustomClipper<Path> {
+  /// Paints a coupon shape around any widget.
+  ///
+  /// Usage:
+  /// ```dart
+  /// ClipPath(
+  ///   clipper: CouponClipper(
+  ///     // optional (defaults to TextDirection.ltr), works when
+  ///     // curveAxis set to Axis.vertical
+  ///     direction: Directionality.of(context),
+  ///   ),
+  ///   // width and height are important depending on the type
+  ///   // of the text direction
+  ///   child: Container(
+  ///     width: 350,
+  ///     height: 400,
+  ///     color: Colors.purple,
+  ///   ),
+  /// ),
+  /// ```
+  const CouponClipper({
+    this.borderRadius = 8,
+    this.curveRadius = 20,
+    this.curvePosition = 100,
+    this.curveAxis = Axis.horizontal,
+    this.direction = TextDirection.ltr,
+    this.clockwise = false,
+  }) : assert(
+          curvePosition > borderRadius,
+          "'curvePosition' should be greater than the 'borderRadius'",
+        );
+
+  /// Border radius value.
+  final double borderRadius;
+
+  /// The curve radius value, which specifies its size.
+  final double curveRadius;
+
+  /// The curve position, which specifies the curve position depending
+  /// on the its child's size.
+  final double curvePosition;
+
+  /// The direction of the curve, whether it's set vertically or
+  /// horizontally.
+  final Axis curveAxis;
+
+  /// If `curveAxis` set to `Axis.vertical`, then direction is useful
+  /// for languages like (Ar, Fa, ...).
+  final TextDirection direction;
+
+  /// If `false` (by default), then the border radius will be drawn
+  /// inside the child, otherwise outside.
+  final bool clockwise;
+
+  @override
+  Path getClip(Size size) {
+    double directionalCurvePosition = curvePosition;
+
+    if (curveAxis == Axis.vertical && direction == TextDirection.rtl) {
+      directionalCurvePosition = size.width - curvePosition - curveRadius;
+    }
+
+    final Radius arcRadius = Radius.circular(borderRadius);
+
+    // border radius arc points
+    final Offset bottomLeftArc = Offset(borderRadius, size.height);
+    final Offset bottomRightArc =
+        Offset(size.width, size.height - borderRadius);
+    final Offset topRightArc = Offset(size.width - borderRadius, 0);
+    final Offset topLeftArc = Offset(0, borderRadius);
+
+    final Path path = Path();
+
+    // starting point
+    path.moveTo(0, borderRadius);
+
+    // left curve
+    if (curveAxis == Axis.horizontal) {
+      path.lineTo(0, directionalCurvePosition);
+      path.quadraticBezierTo(
+        curveRadius / 1.5,
+        directionalCurvePosition + (curveRadius / 2),
+        0,
+        directionalCurvePosition + curveRadius,
+      );
+    }
+
+    // left line, bottom left arc
+    path.lineTo(0, size.height - borderRadius);
+    path.arcToPoint(bottomLeftArc, radius: arcRadius, clockwise: clockwise);
+
+    // bottom cuve
+    if (curveAxis == Axis.vertical) {
+      path.lineTo(directionalCurvePosition, size.height);
+      path.quadraticBezierTo(
+        directionalCurvePosition + (curveRadius / 2),
+        size.height - (curveRadius / 1.5),
+        directionalCurvePosition + curveRadius,
+        size.height,
+      );
+    }
+
+    // bottom line, bottom right arc
+    path.lineTo(size.width - borderRadius, size.height);
+    path.arcToPoint(bottomRightArc, radius: arcRadius, clockwise: clockwise);
+
+    // right curve
+    if (curveAxis == Axis.horizontal) {
+      path.lineTo(size.width, directionalCurvePosition + curveRadius);
+      path.quadraticBezierTo(
+        size.width - (curveRadius / 1.5),
+        directionalCurvePosition + (curveRadius / 2),
+        size.width,
+        directionalCurvePosition,
+      );
+    }
+
+    // right line, top right arc
+    path.lineTo(size.width, borderRadius);
+    path.arcToPoint(topRightArc, radius: arcRadius, clockwise: clockwise);
+
+    // top curve
+    if (curveAxis == Axis.vertical) {
+      path.lineTo(directionalCurvePosition + curveRadius, 0);
+      path.quadraticBezierTo(
+        (directionalCurvePosition - (curveRadius / 2)) + curveRadius,
+        curveRadius / 1.5,
+        directionalCurvePosition - curveRadius + curveRadius,
+        0,
+      );
+    }
+
+    // top line, top left arc
+    path.lineTo(borderRadius, 0);
+    path.arcToPoint(topLeftArc, radius: arcRadius, clockwise: clockwise);
+
+    return path;
+  }
+
+  @override
+  bool shouldReclip(CustomClipper<Path> oldClipper) => oldClipper != this;
+}

+ 24 - 0
lib/coupon_uikit/src/painters/coupon_with_shadow_painter.dart

@@ -0,0 +1,24 @@
+import 'package:flutter/material.dart';
+
+class CouponWithShadowPainter extends CustomPainter {
+  final Shadow shadow;
+  final CustomClipper<Path> clipper;
+
+  CouponWithShadowPainter({
+    required this.shadow,
+    required this.clipper,
+  });
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    final paint = shadow.toPaint();
+    final path = clipper.getClip(size).shift(shadow.offset);
+    canvas.drawPath(path, paint);
+  }
+
+  @override
+  bool shouldRepaint(CouponWithShadowPainter oldDelegate) => false;
+
+  @override
+  bool shouldRebuildSemantics(CouponWithShadowPainter oldDelegate) => false;
+}

+ 128 - 0
lib/coupon_uikit/src/widgets/coupon_card.dart

@@ -0,0 +1,128 @@
+import 'package:flutter/material.dart';
+
+import '../clippers/coupon_clipper.dart';
+import '../painters/coupon_with_shadow_painter.dart';
+
+/// Provides a coupon card widget
+class CouponCard extends StatelessWidget {
+  /// Creates a vertical coupon card widget that takes two children
+  /// with the properties that defines the shape of the card.
+  const CouponCard({
+    Key? key,
+    required this.firstChild,
+    required this.secondChild,
+    this.width,
+    this.height = 150,
+    this.borderRadius = 8,
+    this.curveRadius = 20,
+    this.curvePosition = 100,
+    this.curveAxis = Axis.horizontal,
+    this.clockwise = false,
+    this.backgroundColor,
+    this.decoration,
+    this.shadow,
+  }) : super(key: key);
+
+  /// The small child or first.
+  final Widget firstChild;
+
+  /// The big child or second.
+  final Widget secondChild;
+
+  final double? width;
+
+  final double height;
+
+  /// Border radius value.
+  final double borderRadius;
+
+  /// The curve radius value, which specifies its size.
+  final double curveRadius;
+
+  /// The curve position, which specifies the curve position depending
+  /// on the its child's size.
+  final double curvePosition;
+
+  /// The direction of the curve, whether it's set vertically or
+  /// horizontally.
+  final Axis curveAxis;
+
+  /// If `false` (by default), then the border radius will be drawn
+  /// inside the child, otherwise outside.
+  final bool clockwise;
+
+  /// The background color value.
+  ///
+  /// Ignored if `decoration` property is used.
+  final Color? backgroundColor;
+
+  /// The decoration of the entire widget
+  ///
+  /// Note: `boxShadow` property in the `BoxDecoration` won't do an effect,
+  /// and you should use the `shadow` property of `CouponCard` itself instead.
+  final Decoration? decoration;
+
+  /// A shadow applied to the widget.
+  ///
+  /// Usage
+  /// ```dart
+  /// CouponCard(
+  ///   shadow: BoxShadow(
+  ///     color: Colors.black56,
+  ///     blurRadius: 10,
+  ///   ),
+  /// )
+  /// ```
+  final Shadow? shadow;
+
+  @override
+  Widget build(BuildContext context) {
+    final List<Widget> children = [
+      if (curveAxis == Axis.horizontal)
+        SizedBox(
+          width: double.maxFinite,
+          height: curvePosition + (curveRadius / 2),
+          child: firstChild,
+        )
+      else
+        SizedBox(
+          width: curvePosition + (curveRadius / 2),
+          height: double.maxFinite,
+          child: firstChild,
+        ),
+      Expanded(child: secondChild),
+    ];
+
+    final clipper = CouponClipper(
+      borderRadius: borderRadius,
+      curveRadius: curveRadius,
+      curvePosition: curvePosition,
+      curveAxis: curveAxis,
+      direction: Directionality.of(context),
+      clockwise: clockwise,
+    );
+
+    const defaultShadow = Shadow(
+      color: Colors.transparent,
+      blurRadius: 0,
+    );
+
+    return CustomPaint(
+      painter: CouponWithShadowPainter(
+        shadow: shadow ?? defaultShadow,
+        clipper: clipper,
+      ),
+      child: ClipPath(
+        clipper: clipper,
+        child: Container(
+          width: width,
+          height: height,
+          decoration: decoration ?? BoxDecoration(color: backgroundColor),
+          child: curveAxis == Axis.horizontal
+              ? Column(children: children)
+              : Row(children: children),
+        ),
+      ),
+    );
+  }
+}

+ 91 - 0
lib/coupon_uikit/vertical_coupen.dart

@@ -0,0 +1,91 @@
+
+import 'package:flutter/material.dart';
+
+import 'coupon_uikit.dart';
+
+class VerticalCouponExample extends StatelessWidget {
+  const VerticalCouponExample({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return CouponCard(
+      height: 300,
+      curvePosition: 180,
+      curveRadius: 30,
+      borderRadius: 10,
+      decoration: BoxDecoration(
+        gradient: LinearGradient(
+          colors: [
+            Colors.purple,
+            Colors.purple.shade700,
+          ],
+          begin: Alignment.topLeft,
+          end: Alignment.bottomRight,
+        ),
+      ),
+      firstChild: Column(
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: const [
+          Text(
+            'CHIRISTMAS SALES',
+            style: TextStyle(
+              color: Colors.white54,
+              fontSize: 20,
+              fontWeight: FontWeight.bold,
+            ),
+          ),
+          SizedBox(height: 10),
+          Text(
+            '16%',
+            style: TextStyle(
+              color: Colors.white,
+              fontSize: 56,
+              fontWeight: FontWeight.bold,
+            ),
+          ),
+          Text(
+            'OFF',
+            style: TextStyle(
+              color: Colors.white,
+              fontSize: 26,
+              fontWeight: FontWeight.bold,
+            ),
+          ),
+        ],
+      ),
+      secondChild: Container(
+        width: double.maxFinite,
+        decoration: const BoxDecoration(
+          border: Border(
+            top: BorderSide(color: Colors.white),
+          ),
+        ),
+        padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 42),
+        child: ElevatedButton(
+          style: ButtonStyle(
+            shape: MaterialStateProperty.all<RoundedRectangleBorder>(
+              RoundedRectangleBorder(
+                borderRadius: BorderRadius.circular(60),
+              ),
+            ),
+            padding: MaterialStateProperty.all<EdgeInsetsGeometry>(
+              const EdgeInsets.symmetric(horizontal: 80),
+            ),
+            backgroundColor: MaterialStateProperty.all<Color>(
+              Colors.white,
+            ),
+          ),
+          onPressed: () {},
+          child: const Text(
+            'REDEEM',
+            style: TextStyle(
+              fontSize: 16,
+              fontWeight: FontWeight.bold,
+              color: Colors.purple,
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}

+ 213 - 0
lib/dotted_line/dotted_line.dart

@@ -0,0 +1,213 @@
+library dotted_line;
+
+import 'package:flutter/material.dart';
+
+/// Draw a dotted line.
+///
+/// Basic line settings
+/// * [direction]
+/// * [lineLength]
+/// * [lineThickness]
+/// Dash settings
+/// * [dashLength]
+/// * [dashColor]
+/// * [dashGradient]
+/// * [dashRadius]
+/// Dash gap settings
+/// * [dashGapLength]
+/// * [dashGapColor]
+/// * [dashGapRadius]
+/// * [dashGapGradient]
+class DottedLine extends StatelessWidget {
+  /// Creates dotted line with the given parameters
+  const DottedLine({
+    Key? key,
+    this.direction = Axis.horizontal,
+    this.lineLength = double.infinity,
+    this.lineThickness = 1.0,
+    this.dashLength = 4.0,
+    this.dashColor = Colors.black,
+    this.dashGradient,
+    this.dashGapLength = 4.0,
+    this.dashGapColor = Colors.transparent,
+    this.dashGapGradient,
+    this.dashRadius = 0.0,
+    this.dashGapRadius = 0.0,
+  })  : assert(
+            dashGradient == null || dashGradient.length == 2,
+            'The dashGradient must have only two colors.\n'
+            'The beginning color and the ending color of the gradient.'),
+        assert(
+            dashGapGradient == null || dashGapGradient.length == 2,
+            'The dashGapGradient must have only two colors.\n'
+            'The beginning color and the ending color of the gradient.'),
+        super(key: key);
+
+  /// The direction of the entire dotted line. Default [Axis.horizontal].
+  final Axis direction;
+
+  /// The length of the entire dotted line. Default [double.infinity].
+  final double lineLength;
+
+  /// The thickness of the entire dotted line. Default (1.0).
+  final double lineThickness;
+
+  /// The length of the dash. Default (4.0).
+  final double dashLength;
+
+  /// The color of the dash. Default [Colors.black].
+  ///
+  /// This is ignored if [dashGradient] is non-null.
+  final Color dashColor;
+
+  /// The gradient colors of the dash. Default null.
+  /// The first color is beginning color, the second one is ending color.
+  ///
+  /// If this is specified, [dashColor] has no effect.
+  final List<Color>? dashGradient;
+
+  /// The radius of the dash. Default (0.0).
+  final double dashRadius;
+
+  /// The length of the dash gap. Default (4.0).
+  final double dashGapLength;
+
+  /// The color of the dash gap. Default [Colors.transparent].
+  ///
+  /// This is ignored if [dashGapGradient] is non-null.
+  final Color dashGapColor;
+
+  /// The gradient colors of the dash gap. Default null.
+  /// The first color is beginning color, the second one is ending color.
+  ///
+  /// If this is specified, [dashGapColor] has no effect.
+  final List<Color>? dashGapGradient;
+
+  /// The radius of the dash gap. Default (0.0).
+  final double dashGapRadius;
+
+  @override
+  Widget build(BuildContext context) {
+    final isHorizontal = direction == Axis.horizontal;
+
+    return SizedBox(
+      width: isHorizontal ? lineLength : lineThickness,
+      height: isHorizontal ? lineThickness : lineLength,
+      child: LayoutBuilder(builder: (context, constraints) {
+        final lineLength = _getLineLength(constraints, isHorizontal);
+        final dashAndDashGapCount = _calculateDashAndDashGapCount(lineLength);
+        final dashCount = dashAndDashGapCount[0];
+        final dashGapCount = dashAndDashGapCount[1];
+
+        return Wrap(
+          direction: direction,
+          children: List.generate(dashCount + dashGapCount, (index) {
+            if (index % 2 == 0) {
+              final dashColor = _getDashColor(dashCount, index ~/ 2);
+              final dash = _buildDash(isHorizontal, dashColor);
+              return dash;
+            } else {
+              final dashGapColor = _getDashGapColor(dashGapCount, index ~/ 2);
+              final dashGap = _buildDashGap(isHorizontal, dashGapColor);
+              return dashGap;
+            }
+          }).toList(growable: false),
+        );
+      }),
+    );
+  }
+
+  /// If [lineLength] is [double.infinity],
+  /// get the maximum value of the parent widget.
+  /// And if the value is specified, use the specified value.
+  double _getLineLength(BoxConstraints constraints, bool isHorizontal) {
+    return lineLength == double.infinity
+        ? isHorizontal
+            ? constraints.maxWidth
+            : constraints.maxHeight
+        : lineLength;
+  }
+
+  /// Calculate the count of (dash + dashGap).
+  ///
+  /// example1) [lineLength] is 10, [dashLength] is 1, [dashGapLength] is 1.
+  /// "- - - - - "
+  /// example2) [lineLength] is 10, [dashLength] is 1, [dashGapLength] is 2.
+  /// "-  -  -  -"
+  List<int> _calculateDashAndDashGapCount(double lineLength) {
+    var dashAndDashGapLength = dashLength + dashGapLength;
+    var dashCount = lineLength ~/ dashAndDashGapLength;
+    var dashGapCount = lineLength ~/ dashAndDashGapLength;
+    if (dashLength <= lineLength % dashAndDashGapLength) {
+      dashCount += 1;
+    }
+    return [dashCount, dashGapCount];
+  }
+
+  Widget _buildDash(bool isHorizontal, Color color) {
+    return Container(
+      decoration: BoxDecoration(
+        color: color,
+        borderRadius: BorderRadius.circular(dashRadius),
+      ),
+      width: isHorizontal ? dashLength : lineThickness,
+      height: isHorizontal ? lineThickness : dashLength,
+    );
+  }
+
+  Color _getDashColor(int maxDashCount, int index) {
+    return dashGradient == null
+        ? dashColor
+        : _calculateGradientColor(
+            dashGradient![0],
+            dashGradient![1],
+            maxDashCount,
+            index,
+          );
+  }
+
+  Widget _buildDashGap(bool isHorizontal, Color color) {
+    return Container(
+      decoration: BoxDecoration(
+        color: color,
+        borderRadius: BorderRadius.circular(dashGapRadius),
+      ),
+      width: isHorizontal ? dashGapLength : lineThickness,
+      height: isHorizontal ? lineThickness : dashGapLength,
+    );
+  }
+
+  Color _getDashGapColor(int maxDashGapCount, int index) {
+    return dashGapGradient == null
+        ? dashGapColor
+        : _calculateGradientColor(
+            dashGapGradient![0],
+            dashGapGradient![1],
+            maxDashGapCount,
+            index,
+          );
+  }
+
+  Color _calculateGradientColor(
+    Color startColor,
+    Color endColor,
+    int maxItemCount,
+    int index,
+  ) {
+    var diffAlpha = (endColor.alpha - startColor.alpha);
+    var diffRed = (endColor.red - startColor.red);
+    var diffGreen = (endColor.green - startColor.green);
+    var diffBlue = (endColor.blue - startColor.blue);
+
+    var amountOfChangeInAlphaPerItem = diffAlpha ~/ maxItemCount;
+    var amountOfChangeInRedPerItem = diffRed ~/ maxItemCount;
+    var amountOfChangeInGreenPerItem = diffGreen ~/ maxItemCount;
+    var amountOfChangeInBluePerItem = diffBlue ~/ maxItemCount;
+
+    return startColor
+        .withAlpha(startColor.alpha + amountOfChangeInAlphaPerItem * index)
+        .withRed(startColor.red + amountOfChangeInRedPerItem * index)
+        .withGreen(startColor.green + amountOfChangeInGreenPerItem * index)
+        .withBlue(startColor.blue + amountOfChangeInBluePerItem * index);
+  }
+}

+ 158 - 0
lib/draggable_fab/draggable_fab.dart

@@ -0,0 +1,158 @@
+// ignore_for_file: library_private_types_in_public_api
+
+library draggable_fab;
+
+import 'dart:math';
+
+import 'package:flutter/material.dart';
+
+/// Draggable FAB widget which is always aligned to
+/// the edge of the screen - be it left,top, right,bottom
+class DraggableFab extends StatefulWidget {
+  final Widget child;
+  final Offset? initPosition;
+  final double securityBottom;
+
+  const DraggableFab(
+      {Key? key, required this.child, this.initPosition, this.securityBottom: 0})
+      : super(key: key);
+
+  @override
+  _DraggableFabState createState() => _DraggableFabState();
+}
+
+class _DraggableFabState extends State<DraggableFab> {
+  late Size _widgetSize;
+  double? _left, _top;
+  double _screenWidth = 0.0, _screenHeight = 0.0;
+  double? _screenWidthMid, _screenHeightMid;
+
+  @override
+  void initState() {
+    super.initState();
+    WidgetsBinding.instance
+        .addPostFrameCallback((_) => _getWidgetSize(context));
+  }
+
+  void _getWidgetSize(BuildContext context) {
+    _widgetSize = context.size!;
+
+    if (widget.initPosition != null) {
+      _calculatePosition(widget.initPosition!);
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Stack(children: [
+      Positioned(
+        left: this._left,
+        top: this._top,
+        child: Draggable(
+          child: widget.child,
+          feedback: widget.child,
+          onDragEnd: _handleDragEnded,
+          childWhenDragging: Container(
+            width: 0.0,
+            height: 0.0,
+          ),
+        ),
+      )
+    ]);
+  }
+
+  void _handleDragEnded(DraggableDetails draggableDetails) {
+    this._calculatePosition(draggableDetails.offset);
+  }
+
+  void _calculatePosition(Offset targetOffset) {
+    if (_screenWidthMid == null || _screenHeightMid == null) {
+      Size screenSize = MediaQuery.of(context).size;
+      _screenWidth = screenSize.width;
+      _screenHeight = screenSize.height;
+      _screenWidthMid = _screenWidth / 2;
+      _screenHeightMid = _screenHeight / 2;
+    }
+
+    switch (_getAnchor(targetOffset)) {
+      case Anchor.LEFT_FIRST:
+        this._left = _widgetSize.width / 4;
+        this._top = max(_widgetSize.height / 4, targetOffset.dy);
+        break;
+      case Anchor.TOP_FIRST:
+        this._left = max(_widgetSize.width / 4, targetOffset.dx);
+        this._top = _widgetSize.height / 4;
+        break;
+      case Anchor.RIGHT_SECOND:
+        this._left = _screenWidth - _widgetSize.width;
+        this._top = max(_widgetSize.height, targetOffset.dy);
+        break;
+      case Anchor.TOP_SECOND:
+        this._left = min(_screenWidth - _widgetSize.width, targetOffset.dx);
+        this._top = _widgetSize.height / 2;
+        break;
+      case Anchor.LEFT_THIRD:
+        this._left = _widgetSize.width / 4;
+        this._top = min(
+            _screenHeight - _widgetSize.height - widget.securityBottom,
+            targetOffset.dy);
+        break;
+      case Anchor.BOTTOM_THIRD:
+        this._left = _widgetSize.width / 2;
+        this._top = _screenHeight - _widgetSize.height - widget.securityBottom;
+        break;
+      case Anchor.RIGHT_FOURTH:
+        this._left = _screenWidth - _widgetSize.width;
+        this._top = min(
+            _screenHeight - _widgetSize.height - widget.securityBottom,
+            targetOffset.dy);
+        break;
+      case Anchor.BOTTOM_FOURTH:
+        this._left = _screenWidth - _widgetSize.width;
+        this._top = _screenHeight - _widgetSize.height - widget.securityBottom;
+        break;
+    }
+    setState(() {});
+  }
+
+  /// Computes the appropriate anchor screen edge for the widget
+  Anchor _getAnchor(Offset position) {
+    if (position.dx < _screenWidthMid! && position.dy < _screenHeightMid!) {
+      return position.dx < position.dy ? Anchor.LEFT_FIRST : Anchor.TOP_FIRST;
+    } else if (position.dx >= _screenWidthMid! &&
+        position.dy < _screenHeightMid!) {
+      return _screenWidth - position.dx < position.dy
+          ? Anchor.RIGHT_SECOND
+          : Anchor.TOP_SECOND;
+    } else if (position.dx < _screenWidthMid! &&
+        position.dy >= _screenHeightMid!) {
+      return position.dx < _screenHeight - position.dy
+          ? Anchor.LEFT_THIRD
+          : Anchor.BOTTOM_THIRD;
+    } else {
+      return _screenWidth - position.dx < _screenHeight - position.dy
+          ? Anchor.RIGHT_FOURTH
+          : Anchor.BOTTOM_FOURTH;
+    }
+  }
+}
+
+/// #######################################
+/// #       |          #        |         #
+/// #    TOP_FIRST     #  TOP_SECOND      #
+/// # - LEFT_FIRST     #  RIGHT_SECOND -  #
+/// #######################################
+/// # - LEFT_THIRD     #   RIGHT_FOURTH - #
+/// #  BOTTOM_THIRD    #   BOTTOM_FOURTH  #
+/// #     |            #       |          #
+/// #######################################
+enum Anchor {
+  LEFT_FIRST,
+  TOP_FIRST,
+  RIGHT_SECOND,
+  TOP_SECOND,
+  LEFT_THIRD,
+  BOTTOM_THIRD,
+  RIGHT_FOURTH,
+  BOTTOM_FOURTH
+}

+ 3 - 0
lib/dynamic_form/dynamic_form.dart

@@ -0,0 +1,3 @@
+library dynamic_form;
+
+export 'src/model/dynamic_form_model.dart';

+ 617 - 0
lib/dynamic_form/src/model/dynamic_form_model.dart

@@ -0,0 +1,617 @@
+// ignore_for_file: non_constant_identifier_names
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:general_package/dynamic_form/dynamic_form.dart';
+import 'package:general_package/enum_to_string/enum_to_string.dart';
+
+bool boolFromInt(int done) => done == 1;
+
+enum DynamicFormFieldTypeEnum {
+  text,
+  email,
+  phoneNumber,
+  password,
+  radio,
+  radioModern,
+  dropdown,
+  date,
+  time,
+  dateTime,
+  dateRange,
+  dateTimeRange,
+  rangeSlider,
+  switchInput,
+  checkbox,
+  segmented,
+  chipsSingle,
+  chipsMultiple,
+  timeSlot,
+  tab,
+  valueAddService,
+  connectors,
+  dateSlider,
+  otp,
+  multipleImageUpload,
+  singleImageUpload,
+  rating
+}
+
+class ValueAddService {
+  int id;
+  String title;
+  String description;
+  String price;
+  String value;
+  bool isChecked;
+
+  ValueAddService({
+    required this.id,
+    required this.title,
+    required this.description,
+    required this.price,
+    required this.value,
+    required this.isChecked,
+  });
+
+  static Map<String, dynamic> toMap(ValueAddService form) {
+    var map = <String, dynamic>{};
+    map['id'] = form.id;
+    map['title'] = form.title;
+    map['description'] = form.description;
+    map['price'] = form.price;
+    map['value'] = form.value;
+    map['isChecked'] = form.isChecked;
+    return map;
+  }
+
+  factory ValueAddService.fromJson(dynamic json) {
+    return ValueAddService(
+      id: json['id'],
+      title: json['title'],
+      description: json['description'],
+      price: json['price'],
+      value: json['value'],
+      isChecked: json['isChecked'],
+    );
+  }
+}
+
+class Connectors {
+  late int id;
+  late int subscriptionId;
+  late String adapterName;
+  late int adapterId;
+  late String adapterModel;
+  late int plugPinPoints;
+  late String adapterDescription;
+  late String dispesingUnits;
+  late String price;
+  late dynamic value;
+  late bool isChecked;
+
+  Connectors(
+      {required this.id,
+      required this.subscriptionId,
+      required this.adapterName,
+      required this.adapterId,
+      required this.adapterModel,
+      required this.plugPinPoints,
+      required this.adapterDescription,
+      required this.dispesingUnits,
+      required this.price,
+      required this.value,
+      required this.isChecked});
+
+  Connectors.fromJson(Map<String, dynamic> json) {
+    id = json['id'];
+    subscriptionId = json['subscriptionId'];
+    adapterName = json['adapterName'];
+    adapterId = json['adapterId'];
+    adapterModel = json['adapterModel'];
+    plugPinPoints = json['plugPinPoints'];
+    adapterDescription = json['adapterDescription'];
+    dispesingUnits = json['dispesingUnits'];
+    price = json['price'];
+    value = json['value'];
+    isChecked = json['isChecked'];
+  }
+
+  static Map<String, dynamic> toJson(Connectors  connector) {
+    final Map<String, dynamic> data = {};
+    data['id'] = connector.id;
+    data['subscriptionId'] = connector.subscriptionId;
+    data['adapterName'] = connector.adapterName;
+    data['adapterId'] = connector.adapterId;
+    data['adapterModel'] = connector.adapterModel;
+    data['plugPinPoints'] = connector.plugPinPoints;
+    data['adapterDescription'] = connector.adapterDescription;
+    data['dispesingUnits'] = connector.dispesingUnits;
+    data['price'] = connector.price;
+    data['value'] = connector.value;
+    data['isChecked'] = connector.isChecked;
+    return data;
+  }
+}
+
+
+class FieldCondition {
+  int conditionFieldId;
+  String conditionFieldName;
+  String equalValue;
+  String fieldIdType;
+  String equalValueType;
+
+  FieldCondition({
+    required this.conditionFieldId,
+    required this.conditionFieldName,
+    required this.equalValue,
+    required this.fieldIdType,
+    required this.equalValueType,
+  });
+
+  static Map<String, dynamic> toMap(FieldCondition form) {
+    var map = <String, dynamic>{};
+    map['conditionFieldId'] = form.conditionFieldId;
+    map['conditionFieldName'] = form.conditionFieldName;
+    map['equalValue'] = form.equalValue;
+    map['fieldIdType'] = form.fieldIdType;
+    map['equalValueType'] = form.equalValueType;
+    return map;
+  }
+
+  factory FieldCondition.fromJson(dynamic json) {
+    return FieldCondition(
+      conditionFieldId: json['conditionFieldId'],
+      conditionFieldName: json['conditionFieldName'],
+      equalValue: json['equalValue'],
+      fieldIdType: json['fieldIdType'],
+      equalValueType: json['equalValueType'],
+    );
+  }
+}
+
+class DateFieldCondition {
+  int conditionFieldId;
+  String conditionFieldName;
+  bool? greaterThanValue;
+  bool? lesserThanValue;
+
+  DateFieldCondition({
+    required this.conditionFieldId,
+    required this.conditionFieldName,
+    this.greaterThanValue,
+    this.lesserThanValue,
+  });
+
+  static Map<String, dynamic> toMap(DateFieldCondition form) {
+    var map = <String, dynamic>{};
+    map['conditionFieldId'] = form.conditionFieldId;
+    map['conditionFieldName'] = form.conditionFieldName;
+    map['greaterThanValue'] = form.greaterThanValue;
+    map['lesserThanValue'] = form.lesserThanValue;
+    return map;
+  }
+
+  factory DateFieldCondition.fromJson(dynamic json) {
+    return DateFieldCondition(
+      conditionFieldId: json['conditionFieldId'],
+      conditionFieldName: json['conditionFieldName'],
+      greaterThanValue: json['greaterThanValue'],
+      lesserThanValue: json['lesserThanValue'],
+    );
+  }
+}
+
+class DynamicFormFieldModel {
+  int id;
+  String name;
+  String? title;
+  bool visible = true;
+  bool readOnly;
+  String? placeHolder;
+  double? padding;
+  bool? isRequired = false;
+  dynamic value;
+  int? divisions;
+  double? max;
+  double? min;
+  List<dynamic>? option;
+  DynamicFormFieldTypeEnum type;
+  List<String>? tabsMenu;
+  List<List<DynamicFormFieldModel>>? inputs;
+  List<ValueAddService>? valueAddService;
+  List<Connectors>? connectors;
+
+  int? dateSliderCount;
+  DynamicFormButtonModel? resendOTPButton;
+  List<DynamicFormFieldModel>? filesUpload;
+  FieldCondition? onCondition;
+  DateFieldCondition? onConditionForDate;
+
+  DynamicFormFieldModel({
+    required this.name,
+    required this.id,
+    required this.title,
+    required this.type,
+    required this.visible,
+    required this.readOnly,
+    this.padding,
+    this.isRequired,
+    this.placeHolder,
+    this.value,
+    this.option,
+    this.tabsMenu,
+    this.inputs,
+    this.valueAddService,
+    this.connectors,
+    this.dateSliderCount,
+    this.resendOTPButton,
+    this.filesUpload,
+    this.onCondition,
+    this.onConditionForDate,
+  });
+
+  static Map<String, dynamic> toMap(DynamicFormFieldModel form) {
+    var map = <String, dynamic>{};
+    map['id'] = form.id;
+    map['name'] = form.name;
+    map['title'] = form.title;
+    map['placeHolder'] = form.placeHolder;
+    map['padding'] = form.padding;
+    map['type'] = EnumToString.convertToString(form.type);
+    map['value'] = form.value;
+    map['isRequired'] = form.isRequired;
+    map['value'] = form.value;
+    map['option'] = form.option;
+    map['connectors'] = form.connectors != null
+        ? form.connectors!.map((e) => Connectors.toJson(e)).toList()
+        : null;
+    map['resendOTPButton'] = form.resendOTPButton;
+    return map;
+  }
+
+  factory DynamicFormFieldModel.fromJson(dynamic json) {
+    // (json['inputs'] != null)? json['inputs'].map<List<List<DynamicFormFieldModel>>>((DynamicFormFieldInputsList) => DynamicFormFieldInputsList.map<List<DynamicFormFieldModel>>((DynamicFormFieldInputs)=> DynamicFormFieldInputs.map<DynamicFormFieldModel>((dynamicFormFieldInput)=>DynamicFormFieldModel.fromJson(dynamicFormFieldInput)).toList()).toList).toList() :
+
+    // json['inputs'].map((DynamicFormFieldInputsList) {
+    //   DynamicFormFieldInputsList.map((DynamicFormFieldInputs) {
+    //     print(DynamicFormFieldInputs);
+    //     // var dummy = DynamicFormFieldModel(id: 1,name: "hours_booking_start",type: DynamicFormFieldTypeEnum.date,title: "Select start Date", placeHolder: "Select start Date",visible: true, readOnly: false);
+    //     try{
+
+    //     }catch(e){
+    //       print(e);
+    //     }
+    //   }).toList();
+    // }).toList();
+
+    // json['inputs'].map<List<List<DynamicFormFieldModel>>>((DynamicFormFieldInputsList) {
+    //         print(DynamicFormFieldInputsList);
+    //     return DynamicFormFieldInputsList.map<List<DynamicFormFieldModel>>((DynamicFormFieldInputs){
+    //         print(DynamicFormFieldInputs);
+    //       return DynamicFormFieldInputs.map<DynamicFormFieldModel>((dynamicFormFieldInput) {
+    //         print(dynamicFormFieldInput);
+    //         return DynamicFormFieldModel.fromJson(dynamicFormFieldInput);
+    //       }).toList();
+    //     }
+    //   ).toList();
+    // }).toList();
+    List<List<DynamicFormFieldModel>> inputsList = [];
+    if (json["inputs"] != null) {
+      json["inputs"].map<List<List<DynamicFormFieldModel>>>((data) {
+        List<DynamicFormFieldModel> dummy2 = [];
+        List<dynamic> mapData = data;
+        mapData.map((data2) {
+          var dynamicFormFieldModelData = DynamicFormFieldModel.fromJson(data2);
+          print(dynamicFormFieldModelData.name);
+          dummy2.add(dynamicFormFieldModelData);
+        }).toList();
+        inputsList.add(dummy2);
+        print(inputsList.length);
+        return inputsList;
+      }).toList();
+    }
+    return DynamicFormFieldModel(
+      id: json['id'] ?? 0,
+      name: json['name'],
+      title: json['title'],
+      visible: json['visible'] ?? true,
+      readOnly: json['readOnly'] ?? false,
+      placeHolder: json['placeHolder'],
+      padding: json['padding'],
+      type: EnumToString.fromString(
+              DynamicFormFieldTypeEnum.values, json['type']) ??
+          DynamicFormFieldTypeEnum.text,
+      value: json['value'],
+      option: (json['option'] != null)
+          ? List<dynamic>.from(json['option'] as List)
+          : null,
+      isRequired: json['isRequired'],
+      tabsMenu: (json['tabMenu'] != null)
+          ? List<String>.from(json['tabMenu'] as List)
+          : null,
+      // inputs: (json['inputs'] != null)
+      //     ? json['inputs']
+      //         .map<List<List<DynamicFormFieldModel>>>((DynamicFormFieldInputsList) => DynamicFormFieldInputsList.map(
+      //                 (DynamicFormFieldInputs) =>
+      //                     DynamicFormFieldModel.fromJson(DynamicFormFieldInputs))
+      //             .toList())
+      //         .toList()
+      //     : null,
+      inputs: inputsList,
+      valueAddService: (json['valueAddService'] != null)
+          ? json['valueAddService']
+              .map((valueAddService) =>
+                  ValueAddService.fromJson(valueAddService))
+              .toList()
+          : null,
+      connectors: (json['connectors'] != null)
+          ? json['connectors']
+              .map<Connectors>((connector) => Connectors.fromJson(connector))
+              .toList()
+          : null,
+      dateSliderCount: json["dateSliderCount"],
+      resendOTPButton: (json['resendOtpButton'] != null)
+          ? DynamicFormButtonModel.fromJson(json["resendOtpButton"])
+          : null,
+      filesUpload: (json['filesUpload'] != null)
+          ? json['filesUpload']
+              .map<DynamicFormFieldModel>(
+                  (filesUpload) => DynamicFormFieldModel.fromJson(filesUpload))
+              .toList()
+          : null,
+      onCondition: (json['onCondition'] != null)
+          ? FieldCondition.fromJson(json['onCondition'])
+          : null,
+      onConditionForDate: (json['onConditionForDate'] != null)
+          ? DateFieldCondition.fromJson(json['onConditionForDate'])
+          : null,
+    );
+  }
+}
+
+enum DynamicFormButtonTypeEnum { bg, boarder, text }
+
+enum DynamicFormButtonOnPressEnum {
+  postData,
+  backPage,
+  movePage,
+  scanAndPostData,
+  disable,
+}
+
+class DynamicFormButtonModel {
+  int id;
+  String? onSubmit;
+  // String name;
+  String title;
+  DynamicFormButtonTypeEnum type;
+  DynamicFormButtonOnPressEnum onPressed;
+  EdgeInsetsGeometry? padding;
+  double? width;
+  bool? isDisabled = false;
+  Color? backgroundColor;
+  Color? foregroundColor;
+  Color? color;
+  double? borderRadius;
+  double? fontSize;
+  FontWeight? fontWeight;
+  double? elevation;
+  Map<String, dynamic> postData;
+
+  DynamicFormButtonModel({
+    this.onSubmit,
+    required this.id,
+    // required this.name,
+    required this.type,
+    required this.title,
+    required this.onPressed,
+    required this.postData,
+    this.isDisabled,
+    this.padding,
+    this.width,
+    this.backgroundColor,
+    this.foregroundColor,
+    this.color,
+    this.borderRadius,
+    this.fontSize,
+    this.fontWeight,
+    this.elevation,
+  });
+  static Map<String, dynamic> toMap(DynamicFormButtonModel form) {
+    var map = <String, dynamic>{};
+    map['onSubmit'] = form.onSubmit;
+    map['id'] = form.id;
+    // map['name'] = form.name;
+    map['type'] = EnumToString.convertToString(form.type);
+    map['onPressed'] = EnumToString.convertToString(form.onPressed);
+    map['title'] = form.title;
+    map['padding'] = form.padding;
+    map['width'] = double.parse(form.width.toString());
+    map['backgroundColor'] = form.backgroundColor;
+    map['foregroundColor'] = form.foregroundColor;
+    map['color'] = form.color;
+    map['fontSize'] = form.fontSize;
+    map['fontWeight'] = form.fontWeight;
+    map['elevation'] = form.elevation;
+    return map;
+  }
+
+  factory DynamicFormButtonModel.fromJson(dynamic json) {
+    // var dummy={};
+    //   Map.from(json).forEach((key, value) {
+    //     if(value==null){
+    //       dummy.addAll({key:value});
+    //     }
+    //   });
+    //  List newList = dummy.keys.toList();
+    //  print(newList);
+    return DynamicFormButtonModel(
+      id: json['id'] ?? 0,
+      // name: json['name'],
+      type: EnumToString.fromString(
+              DynamicFormButtonTypeEnum.values, json['type']) ??
+          DynamicFormButtonTypeEnum.bg,
+      title: json['title'],
+      onPressed: json['onPressed'] != null
+          ? EnumToString.fromString(
+                  DynamicFormButtonOnPressEnum.values, json['onPressed']) ??
+              DynamicFormButtonOnPressEnum.postData
+          : DynamicFormButtonOnPressEnum.postData,
+      padding: json['padding'] != null
+          ? EdgeInsets.all(double.parse(json['padding'].toString()))
+          : null,
+      width:
+          json['width'] != null ? double.parse(json['width'].toString()) : null,
+      backgroundColor: json['backgroundColor'],
+      foregroundColor: json['foregroundColor'],
+      isDisabled: json['isDisabled'] ?? false,
+      color: json['color'],
+      fontSize: json['fontSize'],
+      fontWeight: json['fontWeight'],
+      elevation: json['elevation'],
+      postData: json['postData'] ?? {},
+      onSubmit: json['onSubmit'],
+    );
+  }
+}
+
+class DynamicFromSectionModel {
+  int sectionId;
+  String? title;
+  String? subTitle;
+  String? prefixTitle;
+  Color? prefixTitleColor;
+  List<DynamicFormFieldModel> fields;
+  DynamicFromSectionModel({
+    required this.sectionId,
+    this.title,
+    this.subTitle,
+    this.prefixTitle,
+    this.prefixTitleColor,
+    required this.fields,
+  });
+
+  static Map<String, dynamic> toMap(DynamicFromSectionModel form) {
+    var map = <String, dynamic>{};
+    map['sectionId'] = form.sectionId;
+    map['title'] = form.title;
+    map['subTitle'] = form.subTitle;
+    map['prefixTitle'] = form.prefixTitle;
+    map['prefixTitleColor'] = form.prefixTitleColor;
+    map['fields'] = form.fields;
+    return map;
+  }
+
+  factory DynamicFromSectionModel.fromJson(dynamic json) {
+    List<DynamicFormFieldModel> sectionFields = [];
+    for (var element in json["fields"]) {
+      sectionFields.add(DynamicFormFieldModel.fromJson(element));
+    }
+    return DynamicFromSectionModel(
+      sectionId: json['sectionId'],
+      title: json['title'],
+      subTitle: json['subTitle'],
+      prefixTitle: json['prefixTitle'],
+      prefixTitleColor: json['prefixTitleColor'],
+      fields: sectionFields,
+    );
+  }
+}
+
+class DynamicFormModel {
+  // int id;
+  String slug;
+  String? title;
+  String? description;
+  bool isBackButton;
+  String? image;
+  double? imageWidth;
+  double? imageHeight;
+  String? bottomImage;
+  double? bottomImageWidth;
+  double? bottomImageHeight;
+  List<DynamicFormFieldModel> fields;
+  List<DynamicFromSectionModel> sections;
+  List<DynamicFormButtonModel> buttons;
+
+  DynamicFormModel({
+    // required this.id,
+    required this.slug,
+    this.title,
+    this.description,
+    this.isBackButton = false,
+    this.bottomImage,
+    this.bottomImageWidth,
+    this.bottomImageHeight,
+    this.image,
+    this.imageWidth,
+    this.imageHeight,
+    required this.fields,
+    required this.sections,
+    required this.buttons,
+  });
+
+  factory DynamicFormModel.fromJson(dynamic json) {
+    debugPrint("$json - DynamicFormModel");
+    List<DynamicFormFieldModel> fields = [];
+    for (var element in json["fields"] ?? []) {
+      fields.add(DynamicFormFieldModel.fromJson(element));
+      try {
+        // fields.add(DynamicFormFieldModel.fromJson(element));
+      } catch (e) {
+        if (kDebugMode) {
+          debugPrint("$e - Error on fields - ${element['name']}");
+        }
+      }
+    }
+    List<DynamicFromSectionModel> sections = [];
+    for (var element in json["sections"] ?? []) {
+      try {
+        sections.add(DynamicFromSectionModel.fromJson(element));
+      } on Exception catch (e) {
+        if (kDebugMode) {
+          debugPrint("$e - Error on sections");
+        }
+      }
+    }
+
+    List<DynamicFormButtonModel> buttons = [];
+    for (var element in json["buttons"] ?? []) {
+      try {
+        buttons.add(DynamicFormButtonModel.fromJson(element));
+      } catch (e) {
+        if (kDebugMode) {
+          debugPrint("$e - Error on buttons");
+        }
+      }
+    }
+    buttons = buttons.map<DynamicFormButtonModel>((element) {
+      if (element.onPressed == DynamicFormButtonOnPressEnum.postData) {
+        fields.map((e) {
+          if (e.value != null) {
+            element.postData.addAll({e.name: e.value});
+          }
+        }).toList();
+      }
+      return element;
+    }).toList();
+
+    return DynamicFormModel(
+        // id: json['id'],
+        slug: json['slug'],
+        title: json['title'],
+        description: json['description'],
+        isBackButton: json['isBackButton'],
+        image: json['image'],
+        imageWidth: json['imageWidth'],
+        imageHeight: json['imageHeight'],
+        bottomImage: json['bottomImage'],
+        bottomImageWidth: json['bottomImageWidth'],
+        bottomImageHeight: json['bottomImageHeight'],
+        fields: fields,
+        sections: sections,
+        buttons: buttons);
+  }
+}

+ 336 - 0
lib/dynamic_form/src/view/dynamic_form.dart

@@ -0,0 +1,336 @@
+// ignore_for_file: non_constant_identifier_names, must_be_immutable
+
+import 'dart:convert';
+
+import 'package:cached_memory_image/cached_memory_image.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_form_builder/flutter_form_builder.dart';
+import 'package:general_package/constants/constants.dart';
+import 'package:general_package/dynamic_form/src/model/dynamic_form_model.dart';
+import 'package:general_package/dynamic_form/src/view/dynamic_form_button.dart';
+import 'package:general_package/dynamic_form/src/view/dynamic_form_input.dart';
+import 'package:general_package/themes/themes.dart';
+import 'package:get/get.dart';
+
+class DynamicForm extends StatefulWidget {
+  DynamicForm({super.key, required this.dynamicForm});
+  DynamicFormModel dynamicForm;
+
+  @override
+  State<DynamicForm> createState() => _DynamicFormState();
+}
+
+class _DynamicFormState extends State<DynamicForm> {
+  final _globalFormKey = GlobalKey<FormBuilderState>();
+  bool doneInit = false;
+  @override
+  void initState() {
+    super.initState();
+    for (var field in widget.dynamicForm.fields) {
+      if (field.value != null) {
+        _globalFormKey.currentState!.fields[field.name]!.didChange(field.value);
+      }
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    var dynamicForm = widget.dynamicForm;
+    if (!doneInit) {
+      for (var element in dynamicForm.fields) {
+        if (element.onCondition != null) {
+          var keyName = element.onCondition!.conditionFieldName.toString();
+          var keyValue = element.onCondition!.equalValue.toString();
+          var indexFelid = dynamicForm.fields
+              .indexWhere((element) => element.name == keyName);
+          // print("have condition on init");
+          // print(indexFelid);
+          if (keyValue == dynamicForm.fields[indexFelid].value) {
+            setState(() {
+              element.visible = true;
+              doneInit = true;
+            });
+          } else {
+            setState(() {
+              element.visible = false;
+              doneInit = true;
+            });
+          }
+        } else {
+          // print(element.name);
+        }
+      }
+      for (var dynamicFormData in dynamicForm.sections) {
+        for (var element in dynamicFormData.fields) {
+          if (element.onCondition != null) {
+            var keyName = element.onCondition!.conditionFieldName.toString();
+            var keyValue = element.onCondition!.equalValue.toString();
+            var indexSection = dynamicForm.sections.indexOf(dynamicFormData);
+            var indexFelid = dynamicForm.sections[indexSection].fields
+                .indexWhere((element) => element.name == keyName);
+
+            // print("have condition on init sections");
+            // print(indexFelid);
+            if (keyValue ==
+                dynamicForm.sections[indexSection].fields[indexFelid].value) {
+              setState(() {
+                element.visible = true;
+                doneInit = true;
+              });
+            } else {
+              setState(() {
+                element.visible = false;
+                doneInit = true;
+              });
+            }
+          } else {
+            // print(element.name);
+          }
+        }
+      }
+    }
+    return FormBuilder(
+      key: _globalFormKey,
+      onChanged: () {
+        _globalFormKey.currentState!.save();
+        if (kDebugMode) {
+          print(_globalFormKey.currentState!.value);
+        }
+        for (var element in dynamicForm.buttons) {
+          Map<String, dynamic> tempPostDate = Map.from(element.postData);
+          _globalFormKey.currentState!.value.forEach((key, value) {
+            element.postData.forEach((keyPostData, valuePostData) {
+              if (keyPostData != key) {
+                tempPostDate.addAll({key: value});
+              }
+            });
+          });
+          setState(() {
+            element.postData = tempPostDate;
+          });
+        }
+        for (var element in dynamicForm.fields) {
+          if (element.onCondition != null) {
+            if (_globalFormKey.currentState!
+                        .value[element.onCondition!.conditionFieldName] !=
+                    null ||
+                _globalFormKey.currentState!
+                        .value[element.onCondition!.conditionFieldName] !=
+                    '') {
+              if (_globalFormKey.currentState!
+                      .value[element.onCondition!.conditionFieldName] ==
+                  element.onCondition!.equalValue) {
+                setState(() {
+                  element.visible = true;
+                });
+              } else {
+                setState(() {
+                  element.visible = false;
+                });
+              }
+            } else {
+              setState(() {
+                element.visible = false;
+              });
+            }
+          } else {
+            print(element.name);
+          }
+        }
+
+        for (var dynamicFormData in dynamicForm.sections) {
+          for (var element in dynamicFormData.fields) {
+            if (element.onCondition != null) {
+              // print("have condition on change sections");
+              // print(indexFelid);
+              // if (keyValue == dynamicForm.sections[indexSection].fields[indexFelid].value)
+              if (_globalFormKey.currentState!
+                          .value[element.onCondition!.conditionFieldName] !=
+                      null ||
+                  _globalFormKey.currentState!
+                          .value[element.onCondition!.conditionFieldName] !=
+                      '') {
+                if (_globalFormKey.currentState!
+                        .value[element.onCondition!.conditionFieldName] ==
+                    element.onCondition!.equalValue) {
+                  setState(() {
+                    print(element.onCondition!.equalValue);
+                    element.visible = true;
+                    doneInit = true;
+                  });
+                } else {
+                  setState(() {
+                    element.visible = false;
+                    doneInit = true;
+                  });
+                }
+              } else {
+                // print(element.name);
+              }
+            } else {
+              // print("don't have condition on change sections");
+            }
+          }
+        }
+      },
+      child: Container(
+        padding: GeneralConstants.instance.padding20,
+        child: Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          mainAxisAlignment: MainAxisAlignment.start,
+          children: [
+            if (dynamicForm.isBackButton)
+              SizedBox(
+                height: 100,
+                child: InkWell(
+                    onTap: () {
+                      Get.back();
+                    },
+                    child: const Icon(
+                      Icons.arrow_back,
+                      size: 32,
+                    )),
+              ),
+            if (dynamicForm.image != null)
+              Center(
+                child: CachedMemoryImage(
+                  uniqueKey: dynamicForm.image!,
+                  base64: dynamicForm.image,
+                  width: dynamicForm.imageWidth,
+                  height: dynamicForm.imageHeight,
+                ),
+                // child: Image.memory(
+                //   base64Decode(dynamicForm.image!),
+                //   width: dynamicForm.imageWidth,
+                //   height: dynamicForm.imageHeight,
+                // ),
+              ),
+            if (dynamicForm.title != null)
+              const SizedBox(
+                height: 20,
+              ),
+            if (dynamicForm.title != null)
+              Container(
+                padding: GeneralConstants.instance.padding5,
+                child: Text(
+                  dynamicForm.title!,
+                  style: Theme.of(context).textTheme.headline3,
+                  textAlign: TextAlign.left,
+                ),
+              ),
+            if (dynamicForm.description != null)
+              const SizedBox(
+                height: 20,
+              ),
+            if (dynamicForm.description != null)
+              Container(
+                padding: GeneralConstants.instance.padding5,
+                child: Text(
+                  dynamicForm.description!,
+                  style: Theme.of(context).textTheme.subtitle1,
+                ),
+              ),
+            const SizedBox(
+              height: 20,
+            ),
+            Column(
+              children: dynamicForm.fields
+                  .map((dynamicFormField) => DynamicFormInput(
+                        dynamicFormFieldModel: dynamicFormField,
+                      ))
+                  .toList(),
+            ),
+            Column(
+              children: dynamicForm.sections
+                  .map((DynamicFormSection) => Container(
+                        margin: GeneralConstants.instance.margin5,
+                        padding: GeneralConstants.instance.padding10,
+                        decoration: BoxDecoration(
+                          color: AppTheme.whiteColor,
+                          borderRadius: BorderRadius.circular(20),
+                        ),
+                        child: Column(
+                          children: [
+                            Padding(
+                              padding: GeneralConstants.instance.padding5,
+                              child: Row(
+                                mainAxisAlignment:
+                                    MainAxisAlignment.spaceBetween,
+                                children: [
+                                  if (DynamicFormSection.title != null)
+                                    Text(DynamicFormSection.title!,
+                                        style: Theme.of(context)
+                                            .textTheme
+                                            .headline3),
+                                  if (DynamicFormSection.prefixTitle != null)
+                                    Text(DynamicFormSection.prefixTitle!,
+                                        style: Theme.of(context)
+                                            .textTheme
+                                            .bodyText2!
+                                            .copyWith(
+                                                color: DynamicFormSection
+                                                    .prefixTitleColor)),
+                                ],
+                              ),
+                            ),
+                            if (DynamicFormSection.subTitle != null)
+                              Padding(
+                                padding: GeneralConstants.instance.padding5,
+                                child: Row(
+                                  mainAxisAlignment: MainAxisAlignment.start,
+                                  children: [
+                                    Text(DynamicFormSection.subTitle!,
+                                        style: Theme.of(context)
+                                            .textTheme
+                                            .bodyText1),
+                                  ],
+                                ),
+                              ),
+                            Column(
+                              children: DynamicFormSection.fields
+                                  .map((dynamicFormField) => DynamicFormInput(
+                                        dynamicFormFieldModel: dynamicFormField,
+                                      ))
+                                  .toList(),
+                            ),
+                          ],
+                        ),
+                      ))
+                  .toList(),
+            ),
+            if (dynamicForm.bottomImage != null)
+              SizedBox(
+                width: double.infinity,
+                child: Center(
+                  child: CachedMemoryImage(
+                    uniqueKey: dynamicForm.bottomImage!,
+                    base64: dynamicForm.bottomImage,
+                    width: dynamicForm.bottomImageWidth,
+                    height: dynamicForm.bottomImageHeight,
+                  ),
+                ),
+              ),
+            const SizedBox(
+              height: 20,
+            ),
+            Center(
+              child: Column(
+                  children: dynamicForm.buttons
+                      .map((dynamicFormButton) => Padding(
+                            padding: GeneralConstants.instance.padding10,
+                            child: DynamicFormButton(
+                              dynamicFormButtonModel: dynamicFormButton,
+                            ),
+                          ))
+                      .toList()),
+            ),
+            const SizedBox(
+              height: 20,
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 301 - 0
lib/dynamic_form/src/view/dynamic_form_button.dart

@@ -0,0 +1,301 @@
+// ignore_for_file: must_be_immutable
+
+import 'dart:convert';
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:general_package/apiservices/apiservices.dart';
+import 'package:general_package/authservices/auth_service.dart';
+import 'package:general_package/responsive/responsive.dart';
+import 'package:general_package/themes/themes.dart';
+import 'package:general_package/dynamic_form/dynamic_form.dart';
+import 'package:get/get.dart';
+import 'package:get_storage/get_storage.dart';
+import 'package:simple_barcode_scanner/simple_barcode_scanner.dart';
+
+class DynamicFormButton extends StatefulWidget {
+  DynamicFormButton({super.key, required this.dynamicFormButtonModel});
+  DynamicFormButtonModel dynamicFormButtonModel;
+  static bgButton(BuildContext context, String text,
+      {EdgeInsetsGeometry? padding,
+      double? width,
+      Color? backgroundColor,
+      Gradient? gradient,
+      Color? color,
+      double? borderRadius,
+      double? fontSize,
+      FontWeight? fontWeight,
+      double? elevation,
+      bool? isDisabled,
+      Function()? onPressed}) {
+    return Container(
+      width: (width != null) ? width : ScreenTypeData.fullWidth(context) * .7,
+      decoration: BoxDecoration(
+          borderRadius:
+              BorderRadius.circular((borderRadius != null) ? borderRadius : 29),
+          color: backgroundColor,
+          gradient: (backgroundColor != null)
+              ? null
+              : (gradient != null)
+                  ? gradient
+                  : (isDisabled!=null&&isDisabled)
+                      ? AppTheme.disableGradientColor
+                      : AppTheme.primaryGradientColor),
+      child: TextButton(
+          onPressed:(isDisabled!=null&&isDisabled)? null:onPressed,
+          style: TextButton.styleFrom(
+              elevation: (elevation != null) ? elevation : 0,
+              padding: (padding != null)
+                  ? padding
+                  : const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
+              textStyle: TextStyle(
+                  fontSize: (fontSize != null) ? fontSize : 18,
+                  fontWeight:
+                      (fontWeight != null) ? fontWeight : FontWeight.bold)),
+          child: Text(
+            text,
+            textAlign: TextAlign.center,
+            style:
+                TextStyle(color: (color != null) ? color : AppTheme.whiteColor),
+          )),
+    );
+  }
+
+  static boarderButton(BuildContext context, String text,
+      {EdgeInsetsGeometry? padding,
+      double? width,
+      Color? backgroundColor,
+      Color? foregroundColor,
+      Color? color,
+      double? borderRadius,
+      double? fontSize,
+      FontWeight? fontWeight,
+      double? elevation,
+      Function()? onPressed}) {
+    return SizedBox(
+      width: (width != null) ? width : ScreenTypeData.fullWidth(context) * .7,
+      child: TextButton(
+          onPressed: onPressed,
+          style: TextButton.styleFrom(
+              elevation: (elevation != null) ? elevation : 0,
+              backgroundColor: (backgroundColor != null)
+                  ? backgroundColor
+                  : AppTheme.whiteColor,
+              foregroundColor: (foregroundColor != null)
+                  ? foregroundColor
+                  : AppTheme.primaryColor,
+              padding: (padding != null)
+                  ? padding
+                  : const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
+              shape: RoundedRectangleBorder(
+                borderRadius: BorderRadius.circular(
+                    (borderRadius != null) ? borderRadius : 29),
+              ),
+              side: BorderSide(
+                  color: (foregroundColor != null)
+                      ? foregroundColor
+                      : AppTheme.primaryColor,
+                  width: 2),
+              textStyle: TextStyle(
+                  fontSize: (fontSize != null) ? fontSize : 18,
+                  fontWeight:
+                      (fontWeight != null) ? fontWeight : FontWeight.bold)),
+          child: Text(
+            text,
+            textAlign: TextAlign.center,
+            style:
+                TextStyle(color: (color != null) ? color : AppTheme.blackColor),
+          )),
+    );
+  }
+
+  static textButton(BuildContext context, String text,
+      {EdgeInsetsGeometry? padding,
+      Color? color,
+      double? fontSize,
+      FontWeight? fontWeight,
+      Function()? onPressed}) {
+    return Container(
+      padding: padding,
+      child: InkWell(
+          onTap: onPressed,
+          // onPressed: onPressed,
+          // style: TextButton.styleFrom(
+          //     padding: (padding != null)
+          //         ? padding
+          //         : const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
+          //     textStyle: TextStyle(
+          //         fontSize: (fontSize != null) ? fontSize : 18,
+          //         fontWeight:
+          //             (fontWeight != null) ? fontWeight : FontWeight.bold)),
+          child: Text(
+            text,
+            textAlign: TextAlign.center,
+            style: TextStyle(
+                color: (color != null) ? color : AppTheme.primaryColor,
+                fontSize: (fontSize != null) ? fontSize : 16,
+                fontWeight: (fontWeight != null) ? fontWeight : FontWeight.bold),
+          )),
+    );
+  }
+
+  @override
+  State<DynamicFormButton> createState() => _DynamicFormButton();
+}
+
+class _DynamicFormButton extends State<DynamicFormButton> {
+  @override
+  Widget build(BuildContext context) {
+    Function() onPressFunction(DynamicFormButtonOnPressEnum onPressedEnum) {
+      switch (onPressedEnum) {
+        case DynamicFormButtonOnPressEnum.postData:
+          return () {
+            if (widget.dynamicFormButtonModel.onSubmit != null) {
+              APIService(context)
+                  .postData(widget.dynamicFormButtonModel.onSubmit!,
+                      widget.dynamicFormButtonModel.postData)
+                  .then((value) {
+                if (value != null) {
+                  final box = GetStorage();
+                  if (value["token"] != null) {
+                    // box.write('token', value["token"]);
+                    authService.login(value["token"]);
+                  }
+                  if (value["redirectUrl"] != null) {
+                    if (value["token"] != null) {
+                      Get.offAllNamed(value["redirectUrl"]);
+                    } else {
+                      Get.toNamed(value["redirectUrl"]);
+                    }
+                  }
+                }
+              });
+            } else {
+              if (kDebugMode) {
+                print("Please provide URL");
+              }
+            }
+            return "Done";
+          };
+        case DynamicFormButtonOnPressEnum.scanAndPostData:
+          return () async {
+            if (widget.dynamicFormButtonModel.onSubmit != null) {
+              var res = await Navigator.push(
+                  context,
+                  MaterialPageRoute(
+                    builder: (context) => const SimpleBarcodeScannerPage(),
+                  ));
+              widget.dynamicFormButtonModel.postData
+                  .addAll({'scanData': res.toString()});
+              APIService(context)
+                  .postData(widget.dynamicFormButtonModel.onSubmit!,
+                      widget.dynamicFormButtonModel.postData)
+                  .then((value) {
+                if (value != null) {
+                  final box = GetStorage();
+                  if (value["token"] != null) {
+                    // box.write('token', value["token"]);
+                    authService.login(value["token"]);
+                  }
+                  if (value["redirectUrl"] != null) {
+                    if (value["token"] != null) {
+                      Get.offAllNamed(value["redirectUrl"]);
+                    } else {
+                      Get.toNamed(value["redirectUrl"]);
+                    }
+                  }
+                }
+              });
+            } else {
+              if (kDebugMode) {
+                print("Please provide URL");
+              }
+            }
+            return "Done";
+          };
+
+        case DynamicFormButtonOnPressEnum.backPage:
+          return () {
+            Get.back();
+            return "Done";
+          };
+        case DynamicFormButtonOnPressEnum.movePage:
+          return () {
+            Get.toNamed(widget.dynamicFormButtonModel.onSubmit!);
+            return "Done";
+          };
+        case DynamicFormButtonOnPressEnum.disable:
+          print(widget.dynamicFormButtonModel.title);
+          return () => null;
+        // Navigator.pushNamed(
+        // context, widget.dynamicFormButtonModel.onSubmit!);
+        default:
+          return () {
+            APIService(context).postData(
+                widget.dynamicFormButtonModel.onSubmit!,
+                widget.dynamicFormButtonModel.postData);
+            return "Done";
+          };
+      }
+    }
+
+    Widget formTypes(onPressedEnum) {
+      switch (onPressedEnum) {
+        case DynamicFormButtonTypeEnum.bg:
+          return DynamicFormButton.bgButton(
+              context, widget.dynamicFormButtonModel.title,
+              isDisabled: widget.dynamicFormButtonModel.isDisabled,
+              padding: widget.dynamicFormButtonModel.padding,
+              width: widget.dynamicFormButtonModel.width,
+              backgroundColor: widget.dynamicFormButtonModel.backgroundColor,
+              color: widget.dynamicFormButtonModel.color,
+              borderRadius: widget.dynamicFormButtonModel.borderRadius,
+              fontSize: widget.dynamicFormButtonModel.fontSize,
+              fontWeight: widget.dynamicFormButtonModel.fontWeight,
+              elevation: widget.dynamicFormButtonModel.elevation,
+              onPressed:
+                  onPressFunction(widget.dynamicFormButtonModel.onPressed));
+        case DynamicFormButtonTypeEnum.boarder:
+          return DynamicFormButton.boarderButton(
+              context, widget.dynamicFormButtonModel.title,
+              padding: widget.dynamicFormButtonModel.padding,
+              width: widget.dynamicFormButtonModel.width,
+              backgroundColor: widget.dynamicFormButtonModel.backgroundColor,
+              foregroundColor: widget.dynamicFormButtonModel.foregroundColor,
+              color: widget.dynamicFormButtonModel.color,
+              borderRadius: widget.dynamicFormButtonModel.borderRadius,
+              fontSize: widget.dynamicFormButtonModel.fontSize,
+              fontWeight: widget.dynamicFormButtonModel.fontWeight,
+              elevation: widget.dynamicFormButtonModel.elevation,
+              onPressed:
+                  onPressFunction(widget.dynamicFormButtonModel.onPressed));
+        case DynamicFormButtonTypeEnum.text:
+          return DynamicFormButton.textButton(
+              context, widget.dynamicFormButtonModel.title,
+              color: widget.dynamicFormButtonModel.color,
+              fontSize: widget.dynamicFormButtonModel.fontSize,
+              fontWeight: widget.dynamicFormButtonModel.fontWeight,
+              padding:  widget.dynamicFormButtonModel.padding,
+              onPressed:
+                  onPressFunction(widget.dynamicFormButtonModel.onPressed));
+
+        default:
+          return DynamicFormButton.bgButton(
+              context, widget.dynamicFormButtonModel.title,
+              isDisabled: widget.dynamicFormButtonModel.isDisabled,
+              padding: widget.dynamicFormButtonModel.padding,
+              width: widget.dynamicFormButtonModel.width,
+              backgroundColor: widget.dynamicFormButtonModel.backgroundColor,
+              color: widget.dynamicFormButtonModel.color,
+              borderRadius: widget.dynamicFormButtonModel.borderRadius,
+              fontSize: widget.dynamicFormButtonModel.fontSize,
+              fontWeight: widget.dynamicFormButtonModel.fontWeight,
+              elevation: widget.dynamicFormButtonModel.elevation,
+              onPressed:
+                  onPressFunction(widget.dynamicFormButtonModel.onPressed));
+      }
+    }
+
+    return formTypes(widget.dynamicFormButtonModel.type);
+  }
+}

+ 165 - 0
lib/dynamic_form/src/view/dynamic_form_connectors.dart

@@ -0,0 +1,165 @@
+// ignore_for_file: must_be_immutable
+
+import 'package:flutter/material.dart';
+import 'package:flutter_form_builder/flutter_form_builder.dart';
+import 'package:general_package/constants/constants.dart';
+import 'package:general_package/dynamic_form/src/model/dynamic_form_model.dart';
+import 'package:general_package/responsive/responsive.dart';
+import 'package:general_package/themes/themes.dart';
+
+class DynamicFormConnectors extends StatefulWidget {
+  DynamicFormConnectors({
+    super.key,
+    required this.name,
+    this.title,
+    this.padding,
+    this.options,
+  });
+  String name;
+  String? title;
+  EdgeInsetsGeometry? padding;
+  List<Connectors>? options;
+  String? initialValue;
+
+  @override
+  State<DynamicFormConnectors> createState() =>
+      _DynamicFormConnectorsState();
+}
+
+class _DynamicFormConnectorsState
+    extends State<DynamicFormConnectors> {
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: widget.padding,
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisAlignment: MainAxisAlignment.start,
+        children: [
+          if(widget.title!=null)Text(widget.title!, style: Theme.of(context).textTheme.headline3),
+          GeneralConstants.instance.sizedBoxHeight10,
+          FormBuilderField<String?>(
+              name: widget.name,
+              initialValue: widget.initialValue,
+              builder: (FormFieldState field) {
+                return SingleChildScrollView(
+                  scrollDirection: Axis.horizontal,
+                  child: Row(
+                    children: widget.options!
+                        .map(
+                          (option) => Container(
+                            margin: GeneralConstants.instance.marginSymmetric10,
+                            width: ScreenTypeData.fullWidth(context) * .3,
+                            decoration: BoxDecoration(
+                              color: AppTheme.whiteColor,
+                              borderRadius: BorderRadius.circular(12),
+                              boxShadow: [
+                                BoxShadow(
+                                  color: AppTheme.blackColor.withOpacity(0.4),
+                                  offset: const Offset(0, 4),
+                                  blurRadius: 2,
+                                ),
+                              ],
+                            ),
+                            child: Column(
+                              children: [
+                                Container(
+                                  padding: GeneralConstants.instance.paddingSymmetric5,
+                                  decoration: BoxDecoration(
+                                    color: AppTheme.primaryColor,
+                                    borderRadius: const BorderRadius.only(
+                                      topLeft: Radius.circular(12),
+                                      topRight: Radius.circular(12),
+                                    ),
+                                  ),
+                                  child: Center(
+                                    child: Text(option.adapterName,
+                                        style: Theme.of(context)
+                                            .textTheme
+                                            .bodyText2!
+                                            .copyWith(
+                                                color: AppTheme.whiteColor)),
+                                  ),
+                                ),
+                                Padding(
+                                  padding:
+                                      GeneralConstants.instance.paddingSymmetric10,
+                                  child: Column(
+                                    crossAxisAlignment:
+                                        CrossAxisAlignment.center,
+                                    children: [
+                                      Text(option.id.toString(),
+                                          style: Theme.of(context)
+                                              .textTheme
+                                              .bodyText2!
+                                              .copyWith(
+                                                  fontWeight: FontWeight.w700)),
+                                      Container(
+                                        padding: GeneralConstants.instance.padding10,
+                                        child: Text(option.adapterDescription,
+                                            textAlign: TextAlign.center,
+                                            style: Theme.of(context)
+                                                .textTheme
+                                                .caption),
+                                      ),
+                                      Text(option.price,
+                                          textAlign: TextAlign.center,
+                                          style: Theme.of(context)
+                                              .textTheme
+                                              .caption!
+                                              .copyWith(
+                                                  fontWeight: FontWeight.w700)),
+                                    ],
+                                  ),
+                                ),
+                                Container(
+                                  // line49u7J (2:1919)
+                                  margin: GeneralConstants.instance.marginSymmetric5,
+                                  width: double.infinity,
+                                  height: 1,
+                                  decoration: BoxDecoration(
+                                    color: AppTheme.grayColor,
+                                  ),
+                                ),
+                                GestureDetector(
+                                  onTap: () {
+                                    setState((() {
+                                      if (widget.options!=null) {
+                                        var index=widget.options!.indexOf(option);
+                                        option.isChecked = !option.isChecked;
+                                        widget.options!.forEach((element) {
+                                          setState(() {
+                                          element.isChecked=false;
+                                          });
+                                        });
+                                        widget.options![index].isChecked=true;
+                                    field.didChange(widget.options![index].value.toString());
+                                      }
+                                    }));
+                                  },
+                                  child: Container(
+                                    padding: GeneralConstants.instance.padding10,
+                                    child: Text(
+                                        option.isChecked ? "Selected" : 'Select',
+                                        textAlign: TextAlign.center,
+                                        style: Theme.of(context)
+                                            .textTheme
+                                            .caption!
+                                            .copyWith(
+                                                fontWeight: FontWeight.w700,
+                                                color: AppTheme.primaryColor)),
+                                  ),
+                                ),
+                              ],
+                            ),
+                          ),
+                        )
+                        .toList(),
+                  ),
+                );
+              }),
+        ],
+      ),
+    );
+  }
+}

+ 129 - 0
lib/dynamic_form/src/view/dynamic_form_date_slider.dart

@@ -0,0 +1,129 @@
+// ignore_for_file: must_be_immutable
+
+import 'package:flutter/material.dart';
+import 'package:flutter_form_builder/flutter_form_builder.dart';
+import 'package:general_package/coloredcontainer/coloredcontainer.dart';
+import 'package:general_package/constants/constants.dart';
+import 'package:general_package/dynamic_form/src/model/dynamic_form_model.dart';
+import 'package:general_package/responsive/responsive.dart';
+import 'package:general_package/themes/themes.dart';
+import 'package:intl/intl.dart';
+
+class DynamicFormDateSlider extends StatefulWidget {
+  DynamicFormDateSlider({
+    super.key,
+    required this.name,
+    this.title,
+    this.dateCount = 30,
+    this.padding,
+    this.initialValue,
+  });
+  String name;
+  String? title;
+  int dateCount;
+  EdgeInsetsGeometry? padding;
+  DateTime? initialValue;
+
+  @override
+  State<DynamicFormDateSlider> createState() => _DynamicFormDateSliderState();
+}
+
+class _DynamicFormDateSliderState extends State<DynamicFormDateSlider> {
+  DateTime? selectedDate;
+  @override
+  void initState() {
+    // TODO: implement initState
+    super.initState();
+    setState(() {
+      selectedDate = widget.initialValue ??
+          DateTime(
+            DateTime.now().year,
+            DateTime.now().month,
+            DateTime.now().day,
+          );
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final DateList = List<DateTime>.generate(
+        widget.dateCount,
+        (i) => DateTime(
+              DateTime.now().year,
+              DateTime.now().month,
+              DateTime.now().day,
+            ).add(Duration(days: i)));
+    return Container(
+      padding: widget.padding,
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisAlignment: MainAxisAlignment.start,
+        children: [
+          Row(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            children: [
+              if(widget.title!=null)Text(widget.title!, style: Theme.of(context).textTheme.headline3),
+              Text(DateFormat('MMMM').format(selectedDate ?? DateList[0]),
+                  style: Theme.of(context).textTheme.headline5),
+            ],
+          ),
+          GeneralConstants.instance.sizedBoxHeight10,
+          FormBuilderField<DateTime>(
+              name: widget.name,
+              initialValue: selectedDate,
+              builder: (FormFieldState field) {
+                print("selectedDate ${field.value}");
+                return SingleChildScrollView(
+                  scrollDirection: Axis.horizontal,
+                  child: Row(
+                      children: DateList.map(
+                    (Date) => GestureDetector(
+                      onTap: () {
+                        setState(() {
+                          selectedDate = Date;
+                        });
+                        field.didChange(selectedDate);
+                      },
+                      child: Column(
+                        crossAxisAlignment: CrossAxisAlignment.center,
+                        children: [
+                          Container(
+                            // monMSU (2:1977)
+                            margin: GeneralConstants.instance.margin10,
+                            child: Text(DateFormat('EE').format(Date),
+                                textAlign: TextAlign.center,
+                                style: Theme.of(context).textTheme.bodyText1),
+                          ),
+                          ColoredContainer(
+                            padding: GeneralConstants.instance.padding10,
+                            containerGradient: selectedDate == Date
+                                ? LinearGradient(colors: [
+                                    AppTheme.primaryColor,
+                                    AppTheme.primaryDarkColor
+                                  ])
+                                : null,
+                            child: Text(
+                                // digitQfe (2:1978)
+                                Date.day.toString(),
+                                textAlign: TextAlign.center,
+                                style: Theme.of(context)
+                                    .textTheme
+                                    .headline5!
+                                    .copyWith(
+                                        color: selectedDate == Date
+                                            ? AppTheme.whiteColor
+                                            : Date == DateList[0]
+                                                ? AppTheme.primaryColor
+                                                : null)),
+                          ),
+                        ],
+                      ),
+                    ),
+                  ).toList()),
+                );
+              }),
+        ],
+      ),
+    );
+  }
+}

+ 64 - 0
lib/dynamic_form/src/view/dynamic_form_date_time_range.dart

@@ -0,0 +1,64 @@
+// ignore_for_file: must_be_immutable
+
+import 'package:flutter/material.dart';
+import 'package:general_package/constants/constants.dart';
+import 'package:general_package/responsive/responsive.dart';
+import 'package:general_package/themes/themes.dart';
+import 'package:get/get_rx/src/rx_typedefs/rx_typedefs.dart';
+
+import 'f_datetimerangepicker.dart';
+
+class DynamicFormDateTimeRange extends StatefulWidget {
+  DynamicFormDateTimeRange({
+    super.key,
+    this.title,
+    required this.onChanged,
+    this.padding,
+  });
+  String? title;
+  EdgeInsetsGeometry? padding;
+  final void Function(String) onChanged;
+  @override
+  State<DynamicFormDateTimeRange> createState() =>
+      _DynamicFormDateTimeRangeState();
+}
+
+class _DynamicFormDateTimeRangeState extends State<DynamicFormDateTimeRange> {
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: widget.padding,
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisAlignment: MainAxisAlignment.start,
+        children: [
+          if(widget.title!=null)Text(widget.title!, style: Theme.of(context).textTheme.bodyText1),
+          GeneralConstants.instance.sizedBoxHeight10,
+          InkWell(
+              onTap: () {
+                DateTimeRangePicker(
+                    startText: "From",
+                    endText: "To",
+                    doneText: "Yes",
+                    cancelText: "Cancel",
+                    // interval: 1,
+                    // initialStartTime: DateTime.now(),
+                    // initialEndTime: DateTime.now().add(Duration(days: 20)),
+                    mode: DateTimeRangePickerMode.dateAndTime,
+                    minimumTime: DateTime.now(),
+                    maximumTime: DateTime.now().add(Duration(days: 25)),
+                    use24hFormat: false,
+                    onConfirm: (start, end) {
+                      print(start);
+                      print(end);
+                      widget.onChanged("$start - $end");
+                    }).showPicker(context);
+              },
+              child: Container(
+                child: Text("Date Time Range"),
+              ))
+        ],
+      ),
+    );
+  }
+}

+ 171 - 0
lib/dynamic_form/src/view/dynamic_form_image_upload.dart

@@ -0,0 +1,171 @@
+// ignore_for_file: must_be_immutable, no_leading_underscores_for_local_identifiers, use_build_context_synchronously
+
+import 'dart:convert';
+import 'dart:developer' as logDev;
+import 'package:cached_memory_image/cached_memory_image.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_form_builder/flutter_form_builder.dart';
+import 'package:fluttertoast/fluttertoast.dart';
+import 'package:general_package/coloredcontainer/coloredcontainer.dart';
+import 'package:general_package/constants/constants.dart';
+import 'package:general_package/dynamic_form/src/model/dynamic_form_model.dart';
+import 'package:general_package/responsive/responsive.dart';
+import 'package:general_package/themes/themes.dart';
+import 'package:image_picker/image_picker.dart';
+import 'package:intl/intl.dart';
+
+class DynamicFormImageUpload extends StatefulWidget {
+  DynamicFormImageUpload({
+    super.key,
+    required this.name,
+    this.title,
+    this.placeHolder,
+    this.initialValue,
+    this.padding,
+  });
+
+  String name;
+  String? title;
+  String? placeHolder;
+  String? initialValue;
+  EdgeInsetsGeometry? padding;
+
+  @override
+  State<DynamicFormImageUpload> createState() => _DynamicFormImageUploadState();
+}
+
+class _DynamicFormImageUploadState extends State<DynamicFormImageUpload> {
+  DateTime? selectedDate;
+  static imagePickerFromGallery(BuildContext context,FormFieldState fieldState) async {
+    final ImagePicker picker = ImagePicker();
+    final XFile? image = await picker.pickImage(source: ImageSource.gallery);
+    if (image != null) {
+      Navigator.of(context).pop();
+      var imageBytes = await image.readAsBytes();
+      fieldState.didChange(base64Encode(imageBytes));
+      // logDev.log(fieldState.value);
+    } else {
+      Fluttertoast.showToast(
+          msg: "Error",
+          toastLength: Toast.LENGTH_LONG,
+          gravity: ToastGravity.BOTTOM,
+          timeInSecForIosWeb: 1,
+          backgroundColor: Colors.red,
+          textColor: Colors.white,
+          webPosition: "center",
+          webBgColor: "#FF0000",
+          fontSize: 16.0);
+    }
+  }
+
+  static imagePickerFromCamera(BuildContext context,FormFieldState fieldState) async {
+    final ImagePicker picker = ImagePicker();
+    final XFile? image = await picker.pickImage(source: ImageSource.camera);
+    if (image != null) {
+      Navigator.of(context).pop();
+      var imageBytes = await image.readAsBytes();
+      fieldState.didChange(base64Encode(imageBytes));
+    } else {
+      Fluttertoast.showToast(
+          msg: "Error",
+          toastLength: Toast.LENGTH_LONG,
+          gravity: ToastGravity.BOTTOM,
+          timeInSecForIosWeb: 1,
+          backgroundColor: Colors.red,
+          textColor: Colors.white,
+          webPosition: "center",
+          webBgColor: "#FF0000",
+          fontSize: 16.0);
+    }
+  }
+
+  static showModalBottomSheetFormImageUpload(BuildContext context,FormFieldState field) {
+    showModalBottomSheet(
+      context: context,
+      builder: (context) {
+        return Container(
+          width: double.infinity,
+          color: AppTheme.lightWhiteColor,
+          child: Column(mainAxisSize: MainAxisSize.min, children: [
+            GestureDetector(
+              onTap: () => imagePickerFromCamera(context, field),
+              child: Container(
+                padding: GeneralConstants.instance.margin10,
+                child: Row(
+                  children: [
+                    const Icon(Icons.camera),
+                    Container(
+                        padding: GeneralConstants.instance.margin10,
+                        child: const Text("Camera"))
+                  ],
+                ),
+              ),
+            ),
+            GestureDetector(
+              onTap: () => imagePickerFromGallery(context, field),
+              child: Container(
+                padding: GeneralConstants.instance.margin10,
+                child: Row(
+                  children: [
+                    const Icon(Icons.image),
+                    Container(
+                        padding: GeneralConstants.instance.margin10,
+                        child: const Text("Gallery"))
+                  ],
+                ),
+              ),
+            )
+          ]),
+        );
+      },
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return FormBuilderField<String?>(
+        name: widget.name,
+        initialValue: widget.initialValue,
+        builder: (FormFieldState field) {
+          return GestureDetector(
+            onTap: () => showModalBottomSheetFormImageUpload(context, field),
+            child: Container(
+              margin: GeneralConstants.instance.margin10,
+              padding: widget.padding,
+              height: 110,
+              constraints: BoxConstraints(
+                  maxWidth: ScreenTypeData.fullWidth(context) * .35,
+                  minWidth: ScreenTypeData.fullWidth(context) * .35),
+              decoration: BoxDecoration(
+                  color: AppTheme.whiteColor,
+                  borderRadius: BorderRadius.circular(15.0),
+                  border: Border.all(width: 1, color: AppTheme.secondaryColor)),
+              child: (field.value != null)
+                  // ? Image.memory(base64Decode(field.value))
+                  ? CachedMemoryImage(uniqueKey: field.value,base64: field.value,height: 110,fit: BoxFit.cover,)
+                  : Column(
+                      mainAxisAlignment: MainAxisAlignment.center,
+                      children: [
+                          const SizedBox(
+                            height: 10,
+                          ),
+                          const Icon(Icons.image),
+                          const SizedBox(
+                            height: 20,
+                          ),
+                          if (widget.title != null) Text(widget.title!),
+                          if (widget.title != null)
+                            const SizedBox(
+                              height: 5,
+                            ),
+                          if (widget.placeHolder != null)
+                            Text(
+                              widget.placeHolder!,
+                              style: Theme.of(context).textTheme.caption,
+                            ),
+                        ]),
+            ),
+          );
+        });
+  }
+}

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1847 - 0
lib/dynamic_form/src/view/dynamic_form_input.dart


+ 112 - 0
lib/dynamic_form/src/view/dynamic_form_otp.dart

@@ -0,0 +1,112 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_form_builder/flutter_form_builder.dart';
+import 'package:general_package/apiservices/apiservices.dart';
+import 'package:general_package/constants/constants.dart';
+import 'package:general_package/dynamic_form/dynamic_form.dart';
+import 'package:general_package/dynamic_form/src/view/dynamic_form_button.dart';
+import 'package:general_package/themes/themes.dart';
+import 'package:pinput/pinput.dart';
+
+/// This is the basic usage of Pinput
+/// For more examples check out the demo directory
+class DynamicFormOTPWidget extends StatefulWidget {
+  DynamicFormOTPWidget({
+    Key? key,
+    required this.dynamicFormButtonModel,
+    required this.name,
+  }) : super(key: key);
+  String name;
+  DynamicFormButtonModel dynamicFormButtonModel;
+  @override
+  State<DynamicFormOTPWidget> createState() => _DynamicFormOTPWidgetState();
+}
+
+class _DynamicFormOTPWidgetState extends State<DynamicFormOTPWidget> {
+  final pinController = TextEditingController();
+  final focusNode = FocusNode();
+  final formKey = GlobalKey<FormState>();
+
+  bool showError = false;
+  @override
+  void dispose() {
+    pinController.dispose();
+    focusNode.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final defaultPinTheme = PinTheme(
+      height: 78,
+      width: 74,
+      textStyle: Theme.of(context).textTheme.headline6,
+      decoration: BoxDecoration(
+        color: AppTheme.lightWhiteColor,
+        borderRadius: BorderRadius.circular(4),
+        boxShadow: [
+          BoxShadow(
+            color: AppTheme.blackColor.withOpacity(0.2),
+            offset: const Offset(0, 2),
+            blurRadius: 4,
+          ),
+        ],
+      ),
+    );
+    return Center(
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: [
+          GeneralConstants.instance.sizedBoxHeight20,
+          FormBuilderField(
+              name: widget.name,
+              builder: (FormFieldState field) {
+                return Pinput(
+                  controller: pinController,
+                  focusNode: focusNode,
+                  androidSmsAutofillMethod:
+                      AndroidSmsAutofillMethod.smsUserConsentApi,
+                  hapticFeedbackType: HapticFeedbackType.lightImpact,
+                  listenForMultipleSmsOnAndroid: true,
+                  defaultPinTheme: defaultPinTheme,
+                  onCompleted: ((value) => field.didChange(value)),
+                  cursor: Column(
+                    mainAxisAlignment: MainAxisAlignment.end,
+                    children: [
+                      Container(
+                        margin: const EdgeInsets.only(bottom: 9),
+                        width: 22,
+                        height: 1,
+                        color: AppTheme.primaryColor,
+                      ),
+                    ],
+                  ),
+                  focusedPinTheme: defaultPinTheme.copyWith(
+                    height: 78,
+                    width: 74,
+                    decoration: defaultPinTheme.decoration!.copyWith(
+                      border: Border.all(color: AppTheme.lightWhiteColor),
+                    ),
+                  ),
+                  errorPinTheme: defaultPinTheme.copyBorderWith(
+                    border: Border.all(color: AppTheme.redColor),
+                  ),
+                );
+              }),
+          GeneralConstants.instance.sizedBoxHeight20,
+          GeneralConstants.instance.sizedBoxHeight10,
+          Padding(
+            padding: GeneralConstants.instance.padding10,
+            child: Text(
+              "Didn’t receive the code?",
+              style: Theme.of(context).textTheme.bodyText1,
+            ),
+          ),
+          DynamicFormButton(
+              dynamicFormButtonModel: widget.dynamicFormButtonModel),
+          GeneralConstants.instance.sizedBoxHeight20,
+          GeneralConstants.instance.sizedBoxHeight20,
+        ],
+      ),
+    );
+  }
+}

+ 90 - 0
lib/dynamic_form/src/view/dynamic_form_radio.dart

@@ -0,0 +1,90 @@
+// ignore_for_file: must_be_immutable
+
+import 'package:flutter/material.dart';
+import 'package:general_package/constants/constants.dart';
+import 'package:general_package/responsive/responsive.dart';
+import 'package:general_package/themes/themes.dart';
+import 'package:get/get_rx/src/rx_typedefs/rx_typedefs.dart';
+
+class DynamicFormRadio extends StatefulWidget {
+  DynamicFormRadio({
+    super.key,
+    this.title,
+    required this.options,
+    required this.onChanged,
+    this.padding,
+    this.initialValue,
+  });
+  String? title;
+  EdgeInsetsGeometry? padding;
+  List<dynamic> options;
+  String? initialValue;
+  final void Function(String) onChanged;
+  @override
+  State<DynamicFormRadio> createState() => _DynamicFormRadioState();
+}
+
+class _DynamicFormRadioState extends State<DynamicFormRadio> {
+  String? value;
+
+  @override
+  void initState() {
+    super.initState();
+    if (widget.initialValue!=null) {
+      value=widget.initialValue;
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: widget.padding,
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisAlignment: MainAxisAlignment.start,
+        children: [
+          if(widget.title!=null)Text(widget.title!, style: Theme.of(context).textTheme.bodyText1),
+          GeneralConstants.instance.sizedBoxHeight10,
+          Container(
+              padding: GeneralConstants.instance.paddingSymmetric10,
+              decoration: BoxDecoration(
+                borderRadius: BorderRadius.circular(90),
+                color: AppTheme.secondaryColor.withOpacity(0.4),
+              ),
+              child: Row(
+                children: widget.options
+                    .map(
+                      (option) => Expanded(
+                        child: InkWell(
+                          onTap: () {
+                            widget.onChanged(option);
+                            setState(() {
+                              value=option;
+                            });
+                          },
+                          child: Container(
+                            constraints: const BoxConstraints(
+                              minHeight: 30,
+                            ),
+                            decoration: BoxDecoration(
+                              gradient: (value==option)?LinearGradient(colors: [
+                                AppTheme.primaryColor,
+                                AppTheme.primaryDarkColor,
+                              ]):null,
+                              borderRadius: BorderRadius.circular(90),
+                            ),
+                            child: Align(
+                              alignment: Alignment.center,
+                              child: Text(option,style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: (value==option)?AppTheme.whiteColor:AppTheme.blackColor),),
+                            ),
+                          ),
+                        ),
+                      ),
+                    )
+                    .toList(),
+              )),
+        ],
+      ),
+    );
+  }
+}

+ 126 - 0
lib/dynamic_form/src/view/dynamic_form_rating.dart

@@ -0,0 +1,126 @@
+// ignore_for_file: must_be_immutable
+
+import 'package:flutter/material.dart';
+
+class DynamicFormRatingWidget extends StatefulWidget {
+  DynamicFormRatingWidget(
+      {super.key, required this.field,this.onChanged, this.selectedRate = 0});
+  FormFieldState field;
+  int selectedRate = 0;
+  final void Function(int selectedLenght)? onChanged;
+  @override
+  State<DynamicFormRatingWidget> createState() =>
+      _DynamicFormRatingWidgetState();
+}
+
+class _DynamicFormRatingWidgetState extends State<DynamicFormRatingWidget> {
+  int selectedRate= 0;
+  @override
+  void initState() {
+    // TODO: implement initState
+    selectedRate= widget.selectedRate;
+  }
+  @override
+  Widget build(BuildContext context) {
+    return StarsWidget(
+      selectedColor: Colors.amber,
+      selectedLength: selectedRate,
+      unselectedColor: Colors.grey,
+      length: 5,
+      iconSize: 50,
+      onChanged: (count) {
+        setState(() {
+          selectedRate = count;
+          widget.onChanged!(selectedRate);
+        });
+      },
+    );
+    ;
+  }
+}
+
+class StarsWidget extends StatefulWidget {
+  final int length;
+  final String? title;
+  final bool enabled;
+  final double iconSize;
+  final int selectedLength;
+  final Color? selectedColor;
+  final Color? unselectedColor;
+  final void Function(int selectedLenght)? onChanged;
+
+  const StarsWidget({
+    Key? key,
+    this.title,
+    required this.length,
+    this.enabled = true,
+    this.selectedLength = 0,
+    this.selectedColor,
+    this.unselectedColor,
+    this.onChanged,
+    this.iconSize = 28,
+  })  : assert(length > 0),
+        assert(length >= selectedLength),
+        super(key: key);
+
+  @override
+  _StarsWidgetState createState() => _StarsWidgetState();
+}
+
+class _StarsWidgetState extends State<StarsWidget> {
+  @override
+  Widget build(BuildContext context) {
+    var selectedLength = widget.selectedLength;
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: <Widget>[
+        if (widget.title != null)
+          Padding(
+            padding: const EdgeInsets.only(bottom: 5),
+            child: Text(
+              widget.title!,
+              style: Theme.of(context).textTheme.headline6,
+            ),
+          ),
+        Row(
+          mainAxisSize: MainAxisSize.min,
+          children: List.generate(
+            widget.length,
+            (index) {
+              final selected = selectedLength > index;
+              return GestureDetector(
+                onTap: () {
+                  if (widget.enabled) {
+                    var isRepeat = selectedLength != index + 1;
+                    if (isRepeat) {
+                      if (selectedLength == 1 && index == 0) {
+                        setState(() => selectedLength = 0);
+                      } else {
+                        setState(() => selectedLength = index + 1);
+                      }
+                      if (widget.onChanged != null) {
+                        widget.onChanged?.call(selectedLength);
+                      }
+                    }
+                  }
+                },
+                child: Padding(
+                  padding: const EdgeInsets.symmetric(horizontal: 2),
+                  child: Icon(
+                    Icons.star_rounded,
+                    size: widget.iconSize,
+                    color: selected
+                        ? (widget.selectedColor ??
+                            Theme.of(context).colorScheme.secondary)
+                        : widget.unselectedColor ??
+                            Theme.of(context).textTheme.headline5?.color,
+                  ),
+                ),
+              );
+            },
+          ),
+        ),
+      ],
+    );
+  }
+}

+ 108 - 0
lib/dynamic_form/src/view/dynamic_form_tab.dart

@@ -0,0 +1,108 @@
+// ignore_for_file: must_be_immutable
+
+import 'package:flutter/material.dart';
+import 'package:general_package/constants/constants.dart';
+import 'package:general_package/responsive/responsive.dart';
+import 'package:general_package/themes/themes.dart';
+
+class DynamicFormTab extends StatefulWidget {
+  DynamicFormTab(
+      {super.key,
+      required this.title,
+      this.padding,
+      this.inputs,
+      this.tabsMenu});
+  String title;
+  EdgeInsetsGeometry? padding;
+  List<List<Widget>>? inputs;
+  List<String>? tabsMenu;
+  @override
+  State<DynamicFormTab> createState() => _DynamicFormTabState();
+}
+
+class _DynamicFormTabState extends State<DynamicFormTab>
+    with SingleTickerProviderStateMixin {
+  late TabController controller;
+
+  @override
+  void initState() {
+    super.initState();
+    controller = TabController(length: widget.tabsMenu!.length, vsync: this);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: widget.padding,
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisAlignment: MainAxisAlignment.start,
+        children: [
+          Text(widget.title, style: Theme.of(context).textTheme.headline3),
+          GeneralConstants.instance.sizedBoxHeight10,
+          Container(
+            padding: GeneralConstants.instance.paddingSymmetric10,
+            decoration: BoxDecoration(
+              borderRadius: BorderRadius.circular(90),
+              color: AppTheme.secondaryColor.withOpacity(0.4),
+            ),
+            child: TabBar(
+              unselectedLabelColor: AppTheme.grayColor,
+              labelColor: AppTheme.whiteColor,
+              indicatorSize: TabBarIndicatorSize.tab,
+              indicator: BoxDecoration(
+                gradient: LinearGradient(colors: [
+                  AppTheme.primaryColor,
+                  AppTheme.primaryDarkColor,
+                ]),
+                borderRadius: BorderRadius.circular(50),
+              ),
+              tabs: widget.tabsMenu!
+                  .map(
+                    (tabMenu) => Container(
+                      constraints: const BoxConstraints(
+                        minHeight: 30,
+                      ),
+                      decoration: BoxDecoration(
+                        borderRadius: BorderRadius.circular(90),
+                      ),
+                      child: Align(
+                        alignment: Alignment.center,
+                        child: Text(tabMenu),
+                      ),
+                    ),
+                  )
+                  .toList(),
+              controller: controller,
+            ),
+          ),
+          // SingleChildScrollView(
+          //   child: SizedBox(
+          //     height: ScreenTypeData.fullHeight(context) * .20,
+          //     child: TabBarView(
+          //         controller: controller,
+          //         // children: widget.inputs!
+          //         //     .map((input) => Column(
+          //         //           children: input.toList(),
+          //         //         ))
+          //         //     .toList()
+          //             ),
+          //   ),
+          // )
+          SizedBox(
+            height: ScreenTypeData.fullHeight(context)*.20,
+            child: TabBarView(
+                controller: controller,
+                children: widget.inputs!.map((input) {
+                  return SingleChildScrollView(
+                    child: Column(
+                      children: input.toList(),
+                    ),
+                  );
+                }).toList()),
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 161 - 0
lib/dynamic_form/src/view/dynamic_form_value_add_service.dart

@@ -0,0 +1,161 @@
+// ignore_for_file: must_be_immutable
+
+import 'package:flutter/material.dart';
+import 'package:flutter_form_builder/flutter_form_builder.dart';
+import 'package:general_package/constants/constants.dart';
+import 'package:general_package/dynamic_form/src/model/dynamic_form_model.dart';
+import 'package:general_package/responsive/responsive.dart';
+import 'package:general_package/themes/themes.dart';
+
+class DynamicFormValueAddService extends StatefulWidget {
+  DynamicFormValueAddService({
+    super.key,
+    required this.name,
+    this.title,
+    this.padding,
+    this.options,
+  });
+  String name;
+  String? title;
+  EdgeInsetsGeometry? padding;
+  List<ValueAddService>? options;
+  List<String>? initialValue;
+
+  @override
+  State<DynamicFormValueAddService> createState() =>
+      _DynamicFormValueAddServiceState();
+}
+
+class _DynamicFormValueAddServiceState
+    extends State<DynamicFormValueAddService> {
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: widget.padding,
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisAlignment: MainAxisAlignment.start,
+        children: [
+          if(widget.title!=null)Text(widget.title!, style: Theme.of(context).textTheme.headline3),
+          GeneralConstants.instance.sizedBoxHeight10,
+          FormBuilderField<List<String>?>(
+              name: widget.name,
+              initialValue: widget.initialValue,
+              builder: (FormFieldState field) {
+                return SingleChildScrollView(
+                  scrollDirection: Axis.horizontal,
+                  child: Row(
+                    children: widget.options!
+                        .map(
+                          (option) => Container(
+                            margin: GeneralConstants.instance.marginSymmetric10,
+                            width: ScreenTypeData.fullWidth(context) * .3,
+                            decoration: BoxDecoration(
+                              color: AppTheme.whiteColor,
+                              borderRadius: BorderRadius.circular(12),
+                              boxShadow: [
+                                BoxShadow(
+                                  color: AppTheme.blackColor.withOpacity(0.4),
+                                  offset: const Offset(0, 4),
+                                  blurRadius: 2,
+                                ),
+                              ],
+                            ),
+                            child: Column(
+                              children: [
+                                Container(
+                                  padding: GeneralConstants.instance.paddingSymmetric5,
+                                  decoration: BoxDecoration(
+                                    color: AppTheme.primaryColor,
+                                    borderRadius: const BorderRadius.only(
+                                      topLeft: Radius.circular(12),
+                                      topRight: Radius.circular(12),
+                                    ),
+                                  ),
+                                  child: Center(
+                                    child: Text(option.title,
+                                        style: Theme.of(context)
+                                            .textTheme
+                                            .bodyText2!
+                                            .copyWith(
+                                                color: AppTheme.whiteColor)),
+                                  ),
+                                ),
+                                Padding(
+                                  padding:
+                                      GeneralConstants.instance.paddingSymmetric10,
+                                  child: Column(
+                                    crossAxisAlignment:
+                                        CrossAxisAlignment.center,
+                                    children: [
+                                      Text(option.id.toString(),
+                                          style: Theme.of(context)
+                                              .textTheme
+                                              .bodyText2!
+                                              .copyWith(
+                                                  fontWeight: FontWeight.w700)),
+                                      Container(
+                                        padding: GeneralConstants.instance.padding10,
+                                        child: Text(option.description,
+                                            textAlign: TextAlign.center,
+                                            style: Theme.of(context)
+                                                .textTheme
+                                                .caption),
+                                      ),
+                                      Text(option.price,
+                                          textAlign: TextAlign.center,
+                                          style: Theme.of(context)
+                                              .textTheme
+                                              .caption!
+                                              .copyWith(
+                                                  fontWeight: FontWeight.w700)),
+                                    ],
+                                  ),
+                                ),
+                                Container(
+                                  // line49u7J (2:1919)
+                                  margin: GeneralConstants.instance.marginSymmetric5,
+                                  width: double.infinity,
+                                  height: 1,
+                                  decoration: BoxDecoration(
+                                    color: AppTheme.grayColor,
+                                  ),
+                                ),
+                                GestureDetector(
+                                  onTap: () {
+                                    setState((() {
+                                      option.isChecked = !option.isChecked;
+                                    }));
+                                    var data=widget.options!.where((option) => option.isChecked==true).toList();
+                                    List<String> valuesList=[];
+                                    data.forEach((element) {
+                                      valuesList.add(element.value);
+                                    });
+                                    field.didChange(valuesList);
+                                  },
+                                  child: Container(
+                                    padding: GeneralConstants.instance.padding10,
+                                    child: Text(
+                                        option.isChecked ? "Remove" : 'Add',
+                                        textAlign: TextAlign.center,
+                                        style: Theme.of(context)
+                                            .textTheme
+                                            .caption!
+                                            .copyWith(
+                                                fontWeight: FontWeight.w700,
+                                                color: AppTheme.primaryColor)),
+                                  ),
+                                ),
+                              ],
+                            ),
+                          ),
+                        )
+                        .toList(),
+                  ),
+                );
+              }),
+        ],
+      ),
+    );
+  }
+}

+ 260 - 0
lib/dynamic_form/src/view/f_datetimerangepicker.dart

@@ -0,0 +1,260 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/cupertino.dart';
+
+typedef PickerConfirmCallback = void Function(DateTime start, DateTime end);
+
+enum DateTimeRangePickerMode {
+  time,
+  date,
+  dateAndTime,
+}
+
+class DateTimeRangePicker {
+  final startText;
+  final endText;
+  final doneText;
+  final cancelText;
+  final bool use24hFormat;
+  final DateTimeRangePickerMode mode;
+
+  DateTime? initialStartTime;
+  DateTime? initialEndTime;
+  DateTime? minimumTime;
+  DateTime? maximumTime;
+
+  final VoidCallback? onCancel;
+  final PickerConfirmCallback? onConfirm;
+
+  final int interval;
+
+  DateTimeRangePicker({
+    Key? key,
+    this.startText = "Start",
+    this.endText = "End",
+    this.doneText = "Done",
+    this.cancelText = "Cancel",
+    this.mode = DateTimeRangePickerMode.dateAndTime,
+    this.interval = 15,
+    this.use24hFormat = false,
+    this.minimumTime,
+    this.maximumTime,
+    this.initialStartTime,
+    this.initialEndTime,
+    this.onCancel,
+    this.onConfirm,
+  });
+
+  void showPicker(BuildContext context) {
+    if (initialStartTime == null) {
+      initialStartTime = DateTime.now();
+    }
+
+    // Remove minutes and seconds to prevent exception of cupertino picker: initial minute is not divisible by minute interval
+    initialStartTime = initialStartTime!.subtract(Duration(
+        minutes: initialStartTime!.minute, seconds: initialStartTime!.second));
+
+    if (initialEndTime == null) {
+      initialEndTime = initialStartTime!.add(Duration(
+          days: mode == DateTimeRangePickerMode.time ? 0 : 1,
+          hours: mode == DateTimeRangePickerMode.time ? 2 : 0));
+    }
+
+    initialEndTime = initialEndTime!.subtract(Duration(
+        minutes: initialEndTime!.minute, seconds: initialEndTime!.second));
+
+    if (minimumTime != null) {
+      minimumTime = minimumTime!.subtract(
+          Duration(minutes: minimumTime!.minute, seconds: minimumTime!.second));
+    }
+
+    if (maximumTime != null) {
+      maximumTime = maximumTime!.subtract(
+          Duration(minutes: maximumTime!.minute, seconds: maximumTime!.second));
+    }
+
+    var pickerMode = CupertinoDatePickerMode.dateAndTime;
+
+    switch (mode) {
+      case DateTimeRangePickerMode.date:
+        {
+          pickerMode = CupertinoDatePickerMode.date;
+        }
+        break;
+
+      case DateTimeRangePickerMode.time:
+        {
+          pickerMode = CupertinoDatePickerMode.time;
+        }
+        break;
+
+      default:
+        {
+          pickerMode = CupertinoDatePickerMode.dateAndTime;
+        }
+        break;
+    }
+
+    showDialog(
+        context: context,
+        builder: (BuildContext context) {
+          return FractionallySizedBox(
+            widthFactor: 0.8,
+            heightFactor: 0.5,
+            child: PickerWidget([
+              Tab(text: startText),
+              Tab(text: endText),
+            ],
+                initialStartTime!,
+                initialEndTime!,
+                interval,
+                this.onCancel,
+                this.onConfirm,
+                pickerMode,
+                this.doneText,
+                this.cancelText,
+                this.minimumTime!,
+                this.maximumTime!,
+                this.use24hFormat),
+          );
+        });
+  }
+}
+
+class PickerWidget extends StatefulWidget {
+  final List<Tab> _tabs;
+  final int _interval;
+  final VoidCallback? _onCancel;
+  final PickerConfirmCallback? _onConfirm;
+
+  final DateTime _initStart;
+  final DateTime _initEnd;
+  final CupertinoDatePickerMode _mode;
+
+  final String _doneText;
+  final String _cancelText;
+  final DateTime _minimumTime;
+  final DateTime _maximumTime;
+  final bool _use24hFormat;
+
+  PickerWidget(
+      this._tabs,
+      this._initStart,
+      this._initEnd,
+      this._interval,
+      this._onCancel,
+      this._onConfirm,
+      this._mode,
+      this._doneText,
+      this._cancelText,
+      this._minimumTime,
+      this._maximumTime,
+      this._use24hFormat,
+      {Key? key})
+      : super(key: key);
+
+  _PickerWidgetState createState() => _PickerWidgetState();
+}
+
+class _PickerWidgetState extends State<PickerWidget>
+    with SingleTickerProviderStateMixin {
+  TabController? _tabController;
+  DateTime? _start;
+  DateTime? _end;
+
+  @override
+  void initState() {
+    super.initState();
+    _start = widget._initStart;
+    _end = widget._initEnd;
+
+    _tabController = TabController(vsync: this, length: widget._tabs.length);
+  }
+
+  @override
+  void dispose() {
+    _tabController?.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+        backgroundColor: Colors.white,
+        appBar: AppBar(
+          automaticallyImplyLeading: false,
+          backgroundColor: Colors.white,
+          title: Container(
+            child: TabBar(
+              controller: _tabController,
+              tabs: widget._tabs,
+              labelColor: Theme.of(context).primaryColor,
+            ),
+          ),
+        ),
+        body: Stack(
+          children: <Widget>[
+            Container(
+              height: 320,
+              alignment: Alignment.topCenter,
+              child: TabBarView(
+                controller: _tabController,
+                children: widget._tabs.map((Tab tab) {
+                  return CupertinoDatePicker(
+                    mode: widget._mode,
+                    use24hFormat: widget._use24hFormat,
+                    minuteInterval: widget._interval,
+                    minimumDate: widget._minimumTime != null &&
+                            tab.text == widget._tabs.first.text
+                        ? widget._minimumTime
+                        : DateTime.now(),
+                    maximumDate: widget._maximumTime != null &&
+                            tab.text == widget._tabs.last.text
+                        ? widget._maximumTime
+                        : null,
+                    initialDateTime:
+                        tab.text == widget._tabs.first.text ? _start : _end,
+                    onDateTimeChanged: (DateTime newDateTime) {
+                      if (tab.text == widget._tabs.first.text) {
+                        setState(() {
+                          _start = newDateTime;
+                        });
+                      } else {
+                        setState(() {
+                          _end = newDateTime;
+                        });
+                      }
+                    },
+                  );
+                }).toList(),
+              ),
+            ),
+            Container(
+              alignment: Alignment.bottomCenter,
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.end,
+                children: [
+                  TextButton(
+                    onPressed: () {
+                      Navigator.pop(context);
+                      if (widget._onCancel != null) {
+                        widget._onCancel!();
+                      }
+                    },
+                    child: Text(widget._cancelText),
+                  ),
+                  TextButton(
+                    onPressed: () {
+                      Navigator.of(context).pop();
+                      if (widget._onConfirm != null) {
+                        widget._onConfirm!(_start!, _end!);
+                      }
+                    },
+                    child: Text(widget._doneText),
+                  )
+                ],
+              ),
+            )
+          ],
+        ));
+  }
+}

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 50 - 0
lib/enum_to_string/camel_case_to_words.dart


+ 105 - 0
lib/enum_to_string/enum_to_string.dart

@@ -0,0 +1,105 @@
+library enum_to_string;
+
+import 'camel_case_to_words.dart';
+
+class EnumToString {
+  static bool _isEnumItem(enumItem) {
+    final split_enum = enumItem.toString().split('.');
+    return split_enum.length > 1 &&
+        split_enum[0] == enumItem.runtimeType.toString();
+  }
+
+  /// Convert an enum to a string
+  ///
+  /// Pass in the enum value, so TestEnum.valueOne into [enumItem]
+  /// It will return the striped off value so "valueOne".
+  ///
+  /// If you pass in the option [camelCase]=true it will convert it to words
+  /// So TestEnum.valueOne will become Value One
+  static String convertToString(dynamic enumItem, {bool camelCase = false}) {
+    assert(enumItem != null);
+    assert(_isEnumItem(enumItem),
+        '$enumItem of type ${enumItem.runtimeType.toString()} is not an enum item');
+    final _tmp = enumItem.toString().split('.')[1];
+    return !camelCase ? _tmp : camelCaseToWords(_tmp);
+  }
+
+  @Deprecated(
+      'Renamed function to EnumToString.convertToString to make it clearer')
+  static String parse(enumItem, {bool camelCase = false}) =>
+      convertToString(enumItem, camelCase: camelCase);
+
+  /// An alias for parse(item, camelCase: true)
+  ///
+  @Deprecated(
+      'Deprecated in favour of using convertToString(item, camelCase: true)')
+  static String parseCamelCase(enumItem) {
+    return EnumToString.convertToString(enumItem, camelCase: true);
+  }
+
+  /// Given a string, find and return its matching enum value
+  ///
+  /// You need to pass in the values of the enum object. So TestEnum.values
+  /// in the first argument. The matching value is the second argument.
+  ///
+  /// Example final result = EnumToString.fromString(TestEnum.values, "valueOne")
+  /// result == TestEnum.valueOne //true
+  ///
+  static T? fromString<T>(List<T> enumValues, String value,
+      {bool camelCase = false}) {
+    try {
+      return enumValues.singleWhere((enumItem) =>
+          EnumToString.convertToString(enumItem, camelCase: camelCase)
+              .toLowerCase() ==
+          value.toLowerCase());
+    } on StateError catch (_) {
+      return null;
+    }
+  }
+
+  /// Get the index of the enum value
+  ///
+  /// Pass in the enum values to argument one, so TestEnum.values
+  /// Pass in the matching string to argument 2, so "valueOne"
+  ///
+  /// Eg. final index = EnumToString.indexOf(TestEnum.values, "valueOne")
+  /// index == 0 //true
+  static int indexOf<T>(List<T> enumValues, String value) {
+    final fromStringResult = fromString<T>(enumValues, value);
+    if (fromStringResult == null) {
+      return -1;
+    } else {
+      return enumValues.indexOf(fromStringResult);
+    }
+  }
+
+  /// Bulk convert enum values to a list
+  ///
+  static List<String> toList<T>(List<T> enumValues, {bool camelCase = false}) {
+    final _enumList = enumValues
+        .map((t) => !camelCase
+            ? EnumToString.convertToString(t)
+            : EnumToString.convertToString(t, camelCase: true))
+        .toList();
+
+    // I am sure there is a better way to convert a nullable list to a
+    // non-nullable one, but this will do until I find out how. Happy if
+    // someone want to do a PR in the meantime to correct this.
+    var output = <String>[];
+    for (var value in _enumList) {
+      output.add(value);
+    }
+    return output;
+  }
+
+  /// Get a list of enums given a list of strings.
+  /// Basically just EnumToString.fromString, but using lists
+  ///
+  /// As with fromString it is not case sensitive
+  ///
+  /// Eg. EnumToString.fromList(TestEnum.values, ["valueOne", "value2"]
+  static List<T?> fromList<T>(List<T> enumValues, List valueList) {
+    return List<T?>.from(
+        valueList.map<T?>((item) => fromString(enumValues, item)));
+  }
+}

+ 1 - 0
lib/general_package.dart

@@ -0,0 +1 @@
+library general_package;

+ 159 - 0
lib/get_device_info/get_device_info.dart

@@ -0,0 +1,159 @@
+// ignore_for_file: use_build_context_synchronously, equal_keys_in_map
+
+import 'dart:async';
+import 'dart:io';
+import 'package:device_info_plus/device_info_plus.dart';
+import 'package:firebase_core/firebase_core.dart';
+import 'package:firebase_messaging/firebase_messaging.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:get/get.dart';
+import 'package:dart_ipify/dart_ipify.dart';
+
+class DeviceInfo extends GetxController {
+  static final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
+  DateTime _dateTime = DateTime.now();
+  DateTime get dateTime => _dateTime;
+  final List<Map<String, Object?>> _deviceInfo = [];
+  List<Map<String, Object?>> get deviceInfo => _deviceInfo;
+
+  DeviceInfo();
+  Future<Map<String, String>> getDeviceInfo(
+    // BuildContext context,
+    String pageUrl,
+    String? previousPageUrl,
+  ) async {
+    _dateTime = DateTime.now();
+    final mediaQueryData =
+        MediaQueryData.fromWindow(WidgetsBinding.instance.window);
+    final size = mediaQueryData.size;
+    var deviceInfo = await initPlatformState();
+    // final ipv4 = await Ipify.ipv4();
+    // final ipv6 = await Ipify.ipv64();
+    String? token;
+    if (Firebase.apps.isNotEmpty) {
+      token = await FirebaseMessaging.instance.getToken();
+    } 
+    var mapData = {
+      'token': token.toString(),
+      'screenResolution': "${size.width} X ${size.height}",
+      'platform': deviceInfo["platform"].toString(),
+      'modelName': deviceInfo["model"].toString(),
+      'version': deviceInfo["version"].toString(),
+      'manufacturer': deviceInfo["manufacturer"].toString(),
+      'isPhysicalDevice': deviceInfo["isPhysicalDevice"].toString(),
+      // "ipv4": ipv4.toString(),
+      // "ipv6": ipv6.toString(),
+      "deviceId":deviceInfo["deviceId"].toString(),
+      'visitedAt': _dateTime.toString(),
+      'pageUrl': pageUrl.toString(),
+      'previousPageUrl': previousPageUrl.toString(),
+      // 'duration': null,
+      // 'existedAt': null,
+    };
+
+    _deviceInfo.add(mapData);
+    print(mapData);
+    return mapData;
+  }
+
+  static initPlatformState() async {
+    var deviceData = <String, dynamic>{};
+    try {
+      if (kIsWeb) {
+        deviceData = _readWebBrowserInfo(await deviceInfoPlugin.webBrowserInfo);
+      } else {
+        if (Platform.isAndroid) {
+          deviceData =
+              _readAndroidBuildData(await deviceInfoPlugin.androidInfo);
+        } else if (Platform.isIOS) {
+          deviceData = _readIosDeviceInfo(await deviceInfoPlugin.iosInfo);
+        }
+      }
+    } on PlatformException {
+      deviceData = <String, dynamic>{
+        'Error:': 'Failed to get platform version.'
+      };
+    }
+    return deviceData;
+  }
+
+  static Map<String, dynamic> _readAndroidBuildData(AndroidDeviceInfo build) {
+    return <String, dynamic>{
+      "platform": "Android",
+      'version.securityPatch': build.version.securityPatch,
+      'version.sdkInt': build.version.sdkInt,
+      // 'version.release': build.version.release,
+      'version': build.version.release,
+      'version.previewSdkInt': build.version.previewSdkInt,
+      'version.incremental': build.version.incremental,
+      'version.codename': build.version.codename,
+      'version.baseOS': build.version.baseOS,
+      'board': build.board,
+      'bootloader': build.bootloader,
+      'brand': build.brand,
+      'device': build.device,
+      'display': build.display,
+      'fingerprint': build.fingerprint,
+      'hardware': build.hardware,
+      'host': build.host,
+      'deviceId': build.id,
+      'manufacturer': build.manufacturer,
+      'model': build.model,
+      'product': build.product,
+      'supported32BitAbis': build.supported32BitAbis,
+      'supported64BitAbis': build.supported64BitAbis,
+      'supportedAbis': build.supportedAbis,
+      'tags': build.tags,
+      'type': build.type,
+      'isPhysicalDevice': build.isPhysicalDevice,
+      'androidId': build.id,
+      'systemFeatures': build.systemFeatures,
+    };
+  }
+
+  static Map<String, dynamic> _readIosDeviceInfo(IosDeviceInfo data) {
+    return <String, dynamic>{
+      "platform": "IOS",
+      'name': data.name,
+      'systemName': data.systemName,
+      // 'systemVersion': data.systemVersion,
+      'version': data.systemVersion,
+      'manufacturer': "Apple",
+      'model': data.model,
+      'localizedModel': data.localizedModel,
+      'deviceId': data.identifierForVendor,
+      'isPhysicalDevice': data.isPhysicalDevice,
+      'utsname.sysname:': data.utsname.sysname,
+      'utsname.nodename:': data.utsname.nodename,
+      'utsname.release:': data.utsname.release,
+      'utsname.version:': data.utsname.version,
+      'utsname.machine:': data.utsname.machine,
+    };
+  }
+
+  static Map<String, dynamic> _readWebBrowserInfo(WebBrowserInfo data) {
+    return <String, dynamic>{
+      "platform": "Web",
+      'isPhysicalDevice': true,
+      'model': describeEnum(data.browserName),
+      'appCodeName': data.appCodeName,
+      'appName': data.appName,
+      'manufacturer': data.appName,
+      // 'appVersion': data.appVersion,
+      'version': data.appVersion,
+      'deviceMemory': data.deviceMemory,
+      'language': data.language,
+      'languages': data.languages,
+      'platform': data.platform,
+      'product': data.product,
+      'productSub': data.productSub,
+      'userAgent': data.userAgent,
+      'vendor': data.vendor,
+      'vendorSub': data.vendorSub,
+      'hardwareConcurrency': data.hardwareConcurrency,
+      'maxTouchPoints': data.maxTouchPoints,
+    };
+  }
+}

+ 7 - 0
lib/gradients/gradients.dart

@@ -0,0 +1,7 @@
+/// Implementations of Flutter's linear, radial, and sweep gradients
+/// with support for the CMYK, HSI, HSL, HSP, HSB, LAB, Oklab, RGB,
+/// and XYZ color spaces.
+library gradient;
+
+export 'package:flutter_color_models/flutter_color_models.dart';
+export 'src/gradient_painter.dart';

+ 366 - 0
lib/gradients/src/gradient_painter.dart

@@ -0,0 +1,366 @@
+import 'dart:math' as math;
+import 'dart:typed_data';
+import 'dart:ui' as ui;
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_color_models/flutter_color_models.dart';
+import 'package:powers/powers.dart';
+
+/// The base class for [LinearGradientPainter], [RadialGradientPainter],
+/// and [SweepGradientPainter].
+///
+/// {@template gradients.GradientPainter}
+///
+/// [LinearGradientPainter], [RadialGradientPainter], and [SweepGradientPainter]
+/// can be used interchangeably in [BoxDecoration]s, or can be used to build
+/// a [Shader] to paint directly onto a [Canvas]. __See:__ [createShader].
+///
+/// {@endtemplate}
+abstract class GradientPainter implements Gradient {
+  const GradientPainter._();
+
+  /// The color space the colors of the gradient will be interpolated in.
+  ColorSpace? get colorSpace;
+
+  /// If `false`, the colors will be interpolated in the color space defined
+  /// by the starting color within any pairing, however if `true`, the colors
+  /// will be interpolated in the space defined by the ending color.
+  ///
+  /// __Note:__ [invert] will have no effect on the resulting gradient
+  /// if [colorSpace] is defined.
+  bool get invert;
+
+  /// Defines the number of steps to generate in relation to
+  /// the number of device pixels the gradient spans.
+  double get density;
+}
+
+/// A 2D linear gradient.
+///
+/// {@macro gradients.GradientPainter}
+class LinearGradientPainter extends LinearGradient implements GradientPainter {
+  /// A 2D linear gradient.
+  ///
+  /// __See:__ [LinearGradient]
+  const LinearGradientPainter({
+    AlignmentGeometry begin = Alignment.centerLeft,
+    AlignmentGeometry end = Alignment.centerRight,
+    required List<Color> colors,
+    List<double>? stops,
+    TileMode tileMode = TileMode.clamp,
+    GradientTransform? transform,
+    this.colorSpace,
+    this.invert = false,
+    this.density = 0.075,
+  })  : assert(density > 0.0 && density <= 1.0),
+        assert(stops == null || stops.length == colors.length),
+        super(
+          begin: begin,
+          end: end,
+          colors: colors,
+          stops: stops,
+          tileMode: tileMode,
+          transform: transform,
+        );
+
+  @override
+  final ColorSpace? colorSpace;
+
+  @override
+  final bool invert;
+
+  @override
+  final double density;
+
+  @override
+  Shader createShader(Rect rect, {TextDirection? textDirection}) {
+    final startPoint = begin.resolve(textDirection).withinRect(rect);
+    final endPoint = end.resolve(textDirection).withinRect(rect);
+    final span = ((startPoint.dx - endPoint.dx).squared() +
+            (startPoint.dy - endPoint.dy).squared())
+        .sqrt();
+    final size = (span * devicePixelRatio * density).ceil();
+
+    if (size < colors.length) {
+      return super.createShader(rect, textDirection: textDirection);
+    }
+
+    return ui.Gradient.linear(
+      startPoint,
+      endPoint,
+      colors.augment(size,
+          colorSpace: colorSpace, stops: stops, invert: invert),
+      buildStops(size),
+      tileMode,
+      resolveTransform(rect, textDirection),
+    );
+  }
+
+  @override
+  LinearGradientPainter scale(double factor) {
+    return LinearGradientPainter(
+      begin: begin,
+      end: end,
+      colors: colors
+          .map<Color>((Color color) => Color.lerp(null, color, factor)!)
+          .toList(),
+      stops: stops,
+      tileMode: tileMode,
+      transform: transform,
+      colorSpace: colorSpace,
+      density: density,
+    );
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    if (other.runtimeType != runtimeType) return false;
+    return other is LinearGradientPainter &&
+        begin == other.begin &&
+        end == other.end &&
+        listEquals<Color>(colors, other.colors) &&
+        listEquals<double>(stops, other.stops) &&
+        tileMode == other.tileMode &&
+        transform == other.transform &&
+        colorSpace == other.colorSpace &&
+        invert == other.invert &&
+        density == other.density;
+  }
+
+  @override
+  int get hashCode => hashValues(begin, end, hashList(colors), hashList(stops),
+      tileMode, transform, colorSpace, invert, density);
+}
+
+/// A 2D radial gradient.
+///
+/// {@macro gradients.GradientPainter}
+class RadialGradientPainter extends RadialGradient implements GradientPainter {
+  /// A 2D radial gradient.
+  ///
+  /// __See:__ [RadialGradient]
+  const RadialGradientPainter({
+    AlignmentGeometry center = Alignment.center,
+    double radius = 0.5,
+    required List<Color> colors,
+    List<double>? stops,
+    TileMode tileMode = TileMode.clamp,
+    AlignmentGeometry? focal,
+    double focalRadius = 0.0,
+    GradientTransform? transform,
+    this.colorSpace,
+    this.invert = false,
+    this.density = 0.125,
+  }) : super(
+          center: center,
+          radius: radius,
+          colors: colors,
+          stops: stops,
+          tileMode: tileMode,
+          focal: focal,
+          focalRadius: focalRadius,
+          transform: transform,
+        );
+
+  @override
+  final ColorSpace? colorSpace;
+
+  @override
+  final bool invert;
+
+  @override
+  final double density;
+
+  @override
+  Shader createShader(Rect rect, {TextDirection? textDirection}) {
+    final radius = this.radius * rect.shortestSide;
+    final size = (radius * devicePixelRatio * density).ceil();
+
+    if (size < colors.length) {
+      return super.createShader(rect, textDirection: textDirection);
+    }
+
+    return ui.Gradient.radial(
+      center.resolve(textDirection).withinRect(rect),
+      radius,
+      colors.augment(size,
+          colorSpace: colorSpace, stops: stops, invert: invert),
+      buildStops(size),
+      tileMode,
+      resolveTransform(rect, textDirection),
+      focal?.resolve(textDirection).withinRect(rect),
+      focalRadius * rect.shortestSide,
+    );
+  }
+
+  @override
+  RadialGradient scale(double factor) {
+    return RadialGradientPainter(
+      center: center,
+      radius: radius,
+      colors: colors
+          .map<Color>((Color color) => Color.lerp(null, color, factor)!)
+          .toList(),
+      stops: stops,
+      tileMode: tileMode,
+      focal: focal,
+      focalRadius: focalRadius,
+      transform: transform,
+      colorSpace: colorSpace,
+      density: density,
+    );
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    if (other.runtimeType != runtimeType) return false;
+    return other is RadialGradientPainter &&
+        center == other.center &&
+        radius == other.radius &&
+        listEquals<Color>(colors, other.colors) &&
+        listEquals<double>(stops, other.stops) &&
+        tileMode == other.tileMode &&
+        focal == other.focal &&
+        focalRadius == other.focalRadius &&
+        transform == other.transform &&
+        colorSpace == other.colorSpace &&
+        invert == other.invert &&
+        density == other.density;
+  }
+
+  @override
+  int get hashCode => hashValues(
+      center,
+      radius,
+      hashList(colors),
+      hashList(stops),
+      tileMode,
+      focal,
+      focalRadius,
+      transform,
+      colorSpace,
+      invert,
+      density);
+}
+
+/// A 2D sweep gradient.
+///
+/// {@macro gradients.GradientPainter}
+class SweepGradientPainter extends SweepGradient implements GradientPainter {
+  /// A 2D sweep gradient.
+  ///
+  /// __See:__ [SweepGradient]
+  const SweepGradientPainter({
+    AlignmentGeometry center = Alignment.center,
+    double startAngle = 0.0,
+    double endAngle = math.pi * 2,
+    required List<Color> colors,
+    List<double>? stops,
+    TileMode tileMode = TileMode.clamp,
+    GradientTransform? transform,
+    this.colorSpace,
+    this.invert = false,
+    this.density = 0.075,
+  }) : super(
+          center: center,
+          startAngle: startAngle,
+          endAngle: endAngle,
+          colors: colors,
+          stops: stops,
+          tileMode: tileMode,
+          transform: transform,
+        );
+
+  @override
+  final ColorSpace? colorSpace;
+
+  @override
+  final bool invert;
+
+  @override
+  final double density;
+
+  @override
+  Shader createShader(Rect rect, {TextDirection? textDirection}) {
+    final fullPi = math.pi * 2;
+    final slice =
+        (endAngle.clamp(0, fullPi) - startAngle.clamp(0, fullPi)) / fullPi;
+    final span =
+        (rect.longestSide.squared() + rect.shortestSide.squared()).sqrt();
+    final size = (span * slice * devicePixelRatio * density).ceil();
+
+    if (size < colors.length) {
+      return super.createShader(rect, textDirection: textDirection);
+    }
+
+    return ui.Gradient.sweep(
+      center.resolve(textDirection).withinRect(rect),
+      colors.augment(size,
+          colorSpace: colorSpace, stops: stops, invert: invert),
+      buildStops(size),
+      tileMode,
+      startAngle,
+      endAngle,
+      resolveTransform(rect, textDirection),
+    );
+  }
+
+  @override
+  SweepGradientPainter scale(double factor) {
+    return SweepGradientPainter(
+      center: center,
+      startAngle: startAngle,
+      endAngle: endAngle,
+      colors: colors
+          .map<Color>((Color color) => Color.lerp(null, color, factor)!)
+          .toList(),
+      stops: stops,
+      tileMode: tileMode,
+      transform: transform,
+      colorSpace: colorSpace,
+      density: density,
+    );
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    if (other.runtimeType != runtimeType) return false;
+    return other is SweepGradientPainter &&
+        center == other.center &&
+        startAngle == other.startAngle &&
+        endAngle == other.endAngle &&
+        listEquals<Color>(colors, other.colors) &&
+        listEquals<double>(stops, other.stops) &&
+        tileMode == other.tileMode &&
+        transform == other.transform &&
+        colorSpace == other.colorSpace &&
+        invert == other.invert &&
+        density == other.density;
+  }
+
+  @override
+  int get hashCode => hashValues(center, startAngle, endAngle, hashList(colors),
+      hashList(stops), tileMode, transform, colorSpace, invert, density);
+}
+
+extension _BuildStops on GradientPainter {
+  /// Evenly distributes the stops from `0.0` to `1.0`.
+  List<double> buildStops(int size) {
+    final slice = 1 / size;
+    return List<double>.generate(size, (index) => index * slice);
+  }
+
+  /// Resolves the transform applied to the shader.
+  Float64List? resolveTransform(Rect bounds, TextDirection? textDirection) {
+    return transform?.transform(bounds, textDirection: textDirection)?.storage;
+  }
+
+  /// Returns the number of device pixels for each logical
+  /// pixel for the screen this view is displayed on.
+  double get devicePixelRatio =>
+      WidgetsBinding.instance.window.devicePixelRatio;
+}

+ 31 - 0
lib/icon_button_widget/icon_button_widget.dart

@@ -0,0 +1,31 @@
+import 'package:flutter/material.dart';
+
+class IconButtonWidget extends StatelessWidget {
+  final IconData icon;
+  final Color? buttonColor, iconColor;
+  final Function onTap;
+  final double elevation;
+
+  const IconButtonWidget(
+      {super.key,
+      required this.icon,
+      this.buttonColor,
+      this.iconColor,
+      required this.onTap,
+      this.elevation = 5});
+
+  @override
+  Widget build(BuildContext context) {
+    return Material(
+        elevation: elevation,
+        color: buttonColor ?? Theme.of(context).primaryColor,
+        borderRadius: BorderRadius.circular(5),
+        child: InkWell(
+            borderRadius: BorderRadius.circular(5),
+            child: SizedBox(
+                width: 38,
+                height: 38,
+                child: Icon(icon, size: 25, color: iconColor ?? Colors.white)),
+            onTap: () => onTap()));
+  }
+}

+ 43 - 0
lib/icons/gozap_icons.dart

@@ -0,0 +1,43 @@
+/// Flutter icons GoZAPPIcon
+/// Copyright (C) 2022 by original authors @ fluttericon.com, fontello.com
+/// This font was generated by FlutterIcon.com, which is derived from Fontello.
+///
+/// To use this font, place it in your fonts/ directory and include the
+/// following in your pubspec.yaml
+///
+/// flutter:
+///   fonts:
+///    - family:  GoZAPPIcon
+///      fonts:
+///       - asset: fonts/GoZAPPIcon.ttf
+///
+/// 
+///
+// ignore_for_file: constant_identifier_names
+
+import 'package:flutter/widgets.dart';
+
+class GoZAPPIcon {
+  GoZAPPIcon._();
+
+  static const _kFontFam = 'GoZAPPIcon';
+  static const String? _kFontPkg = null;
+
+  static const IconData month_swaps = IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData recharged_swaps = IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData remaing_swaps = IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData free_swaps = IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData asset = IconData(0xe80d, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData asset_category_id = IconData(0xe80e, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData asset_id = IconData(0xe80f, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData payment_type = IconData(0xe810, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData returning_battery_id = IconData(0xe811, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData rider_id = IconData(0xe812, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData service = IconData(0xe813, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData service_type = IconData(0xe814, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData swap_battery_id = IconData(0xe815, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData admin_free_swaps = IconData(0xe816, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData admin_paid_swaps = IconData(0xe817, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData admin_recharge_swaps = IconData(0xe818, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData admin_total_swaps = IconData(0xe819, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+}

+ 36 - 0
lib/icons/gozap_icons_old.dart

@@ -0,0 +1,36 @@
+/// Flutter icons GoZAPPIcon
+/// Copyright (C) 2022 by original authors @ fluttericon.com, fontello.com
+/// This font was generated by FlutterIcon.com, which is derived from Fontello.
+///
+/// To use this font, place it in your fonts/ directory and include the
+/// following in your pubspec.yaml
+///
+/// flutter:
+///   fonts:
+///    - family:  GoZAPPIcon
+///      fonts:
+///       - asset: fonts/GoZAPPIcon.ttf
+///
+///
+///
+// ignore_for_file: constant_identifier_names
+
+import 'package:flutter/widgets.dart';
+
+class GoZAPPIcon {
+  GoZAPPIcon._();
+
+  static const _kFontFam = 'GoZAPPIcon';
+  static const String? _kFontPkg = null;
+
+  static const IconData month_swaps =
+      IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData recharged_swaps =
+      IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData remaing_swaps =
+      IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData free_swaps =
+      IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+  static const IconData group =
+      IconData(0xe900, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+}

+ 36 - 0
lib/localization/app_translations.dart

@@ -0,0 +1,36 @@
+import 'dart:async';
+import 'dart:convert';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart' show rootBundle;
+
+class AppTranslations {
+  Locale locale;
+  static Map<dynamic, dynamic>? _localisedValues;
+
+  AppTranslations(this.locale);
+
+  static AppTranslations? of(BuildContext context) {
+    return Localizations.of<AppTranslations>(context, AppTranslations);
+  }
+
+  static Future<AppTranslations> load(Locale locale) async {
+    late AppTranslations appTranslations = AppTranslations(locale);
+    // String path = 'packages/general_package/assets/user_state.json';
+    // String jobsString = await rootBundle.loadString(path);
+    // List<dynamic> users = await jsonDecode(jobsString);
+    String jsonContent = await rootBundle.loadString(
+        "packages/general_package/assets/locale/localization_${locale.languageCode}.json");
+    _localisedValues = json.decode(jsonContent);
+    return appTranslations;
+  }
+
+  get currentLanguage => locale.languageCode;
+
+  String text(String key) {
+    if (_localisedValues != null) {
+      return _localisedValues![key] ?? "$key not found";
+    } else {
+      return "";
+    }
+  }
+}

+ 25 - 0
lib/localization/app_translations_delegate.dart

@@ -0,0 +1,25 @@
+import 'dart:async';
+import 'package:flutter/material.dart';
+import 'package:general_package/localization/application.dart';
+import 'package:general_package/localization/app_translations.dart';
+
+class AppTranslationsDelegate extends LocalizationsDelegate<AppTranslations> {
+  final Locale? newLocale;
+
+  const AppTranslationsDelegate({this.newLocale});
+
+  @override
+  bool isSupported(Locale locale) {
+    return application.supportedLanguagesCodes.contains(locale.languageCode);
+  }
+
+  @override
+  Future<AppTranslations> load(Locale locale) {
+    return AppTranslations.load(newLocale ?? locale);
+  }
+
+  @override
+  bool shouldReload(LocalizationsDelegate<AppTranslations> old) {
+    return true;
+  }
+}

+ 28 - 0
lib/localization/application.dart

@@ -0,0 +1,28 @@
+import 'dart:ui';
+
+class Application {
+  static final Application _application = Application._internal();
+  final List<String> supportedLanguages = [
+    "English",
+    "Hindi",
+  ];
+
+  final List<String> supportedLanguagesCodes = [
+    "en",
+    "hi",
+  ];
+  factory Application() {
+    return _application;
+  }
+
+  Application._internal();
+
+  //returns the list of supported Locales
+  Iterable<Locale> supportedLocales() =>
+      supportedLanguagesCodes.map<Locale>((language) => Locale(language, ""));
+  //function to be invoked when changing the language
+  late LocaleChangeCallback onLocaleChanged;
+}
+
+Application application = Application();
+typedef LocaleChangeCallback = void Function(Locale locale);

+ 20 - 0
lib/mainUrl_provider/mainUrl_provider.dart

@@ -0,0 +1,20 @@
+// ignore_for_file: camel_case_types
+
+import 'package:flutter/material.dart';
+
+class mainURLChangeNotifier extends ChangeNotifier {
+  String _mainURL="";
+
+  String get mainURL => _mainURL;
+  
+  set(BuildContext context,String url) async {
+    _mainURL = url;
+    notifyListeners();
+  }
+  get(BuildContext context) async {
+    notifyListeners();
+  }
+  remove(BuildContext context) async {
+    notifyListeners();
+  }
+}

+ 92 - 0
lib/onboard/DymanicForms.json

@@ -0,0 +1,92 @@
+{
+    "slug":"SignUP",
+    "title":"Create New Account",
+    "description":null,
+    "image":"",
+    "onSubmit":"",
+    "fields":[
+        {
+            "id":1,
+            "name":"Category",
+            "title":null,
+            "placeHolder":null,
+            "padding":8.0,
+            "type":"Radio",
+            "option":["Individual","Corporate"],
+            "DynamicFormFieldinitialValue":"Individual",
+            "isRequired":true,
+            "DynamicFormFieldCondition":null
+        },
+        {
+            "id":2,
+            "name":"Name",
+            "title":"Name",
+            "placeHolder":"Enter here",
+            "padding":8.0,
+            "type":"Text",
+            "DynamicFormFieldinitialValue":null,
+            "isRequired":true,
+            "DynamicFormFieldCondition":null
+        },
+        {
+            "id":3,
+            "name":"PhoneNumber",
+            "title":"Phone Number",
+            "placeHolder":"Enter here",
+            "padding":8.0,
+            "type":"PhoneNumber",
+            "DynamicFormFieldinitialValue":null,
+            "isRequired":true,
+            "DynamicFormFieldCondition":null
+        },
+        {
+            "id":4,
+            "name":"EmailAddress",
+            "title":"Email Address",
+            "placeHolder":"Enter here",
+            "padding":8.0,
+            "type":"Email",
+            "DynamicFormFieldinitialValue":null,
+            "isRequired":true,
+            "DynamicFormFieldCondition":null
+        },
+        {
+            "id":5,
+            "name":"Password",
+            "title":"Password",
+            "placeHolder":"Enter here",
+            "padding":8.0,
+            "type":"Password",
+            "DynamicFormFieldinitialValue":null,
+            "isRequired":true,
+            "DynamicFormFieldCondition":null
+        },
+        {
+            "id":6,
+            "name":"DEID",
+            "title":"DE ID",
+            "placeHolder":"Enter here",
+            "padding":8.0,
+            "type":"Email",
+            "DynamicFormFieldinitialValue":null,
+            "isRequired":true,
+            "DynamicFormFieldCondition": {
+                "id":1,
+                "EqualValue":"Corporate",
+                "RunTimeTypeForID":"int",
+                "RunTimeTypeForValue":"String"
+            }
+        },
+        {
+            "id":7,
+            "name":"ReferID",
+            "title":"Refer ID",
+            "placeHolder":"Enter here",
+            "padding":8.0,
+            "type":"Text",
+            "DynamicFormFieldinitialValue":null,
+            "isRequired":true,
+            "DynamicFormFieldCondition":null
+        }
+    ]
+}

+ 4 - 0
lib/onboard/onboard.dart

@@ -0,0 +1,4 @@
+library easy_onboard;
+
+export 'src/view/onboard.dart';
+export 'src/model/onboard_model.dart';

+ 89 - 0
lib/onboard/onboard.json

@@ -0,0 +1,89 @@
+{
+
+    "ScreenID":1,
+    "AppName":"",
+    "AppIconURL":"",
+    "SplashScreenImageURL":"",
+    "OnboardList":[
+        {
+            "OnboardID":1,
+            "OnboardTitle":"",
+            "OnBoardDescription":"",
+            "OnBoardImageURL":""
+        },
+        {
+            "OnboardID":2,
+            "OnBoardTitle":"",
+            "OnBoardDescription":"",
+            "OnBoardImageURL":""
+        },
+        {
+            "OnboardID":3,
+            "OnBoardTitle":"",
+            "OnBoardDescription":"",
+            "OnBoardImageURL":""
+        }
+    ],
+    "OnboardPermissionList":[
+        {
+            "OnboardPermissionID":1,
+            "OnboardPermissionTitle":"",
+            "OnboardPermissionImageURL":"",
+            "OnboardPermissionRequest":"Location",
+            "OnboardPermissionListDescription":[
+                {
+                    "OnboardPermissionListDescriptionID":1,
+                    "OnboardOnboardPermissionListDescriptionTitle":"",
+                    "OnboardOnboardPermissionListDescriptionImageURL":""
+                },
+                {
+                    "OnboardPermissionListDescriptionID":1,
+                    "OnboardPermissionListDescriptionTitle":"",
+                    "OnboardPermissionListDescriptionImageURL":""
+                }
+            ]
+        },
+        {
+            "OnboardPermissionID":2,
+            "ScreenID":1,
+            "OnboardPermissionTitle":"",
+            "OnboardPermissionImageURL":"",
+            "OnboardPermissionRequest":"Camera",
+            "OnboardPermissionListDescription":[
+                {
+                    "OnboardPermissionListDescriptionID":3,
+                    "OnboardPermissionID":2,
+                    "OnboardPermissionListDescriptionTitle":"",
+                    "OnboardPermissionListDescriptionImageURL":""
+                },
+                {
+                    "OnboardPermissionListDescriptionID":4,
+                    "OnboardPermissionID":2,
+                    "OnboardPermissionListDescriptionTitle":"",
+                    "OnboardPermissionListDescriptionImageURL":""
+                }
+            ]
+        },
+        {
+            "OnboardPermissionID":3,
+            "ScreenID":1,
+            "OnboardPermissionTitle":"",
+            "OnboardPermissionImageURL":"",
+            "OnboardPermissionRequest":"Storage",
+            "OnboardPermissionListDescription":[
+                {
+                    "OnboardPermissionListDescriptionID":5,
+                    "OnboardPermissionID":3,
+                    "OnboardPermissionListDescriptionTitle":"",
+                    "OnboardPermissionListDescriptionImageURL":""
+                },
+                {
+                    "OnboardPermissionListDescriptionID":6,
+                    "OnboardPermissionID":3,
+                    "OnboardPermissionListDescriptionTitle":"",
+                    "OnboardPermissionListDescriptionImageURL":""
+                }
+            ]
+        }
+    ]
+}

+ 201 - 0
lib/onboard/src/model/onboard_model.dart

@@ -0,0 +1,201 @@
+// ignore_for_file: non_constant_identifier_names
+
+import 'package:flutter/material.dart';
+import 'package:general_package/enum_to_string/enum_to_string.dart';
+import 'package:general_package/permisiion_converter/permission_converter.dart';
+import 'package:get/get.dart';
+import 'package:permission_handler/permission_handler.dart';
+stringToAlignment(String? alignmentString){
+  Alignment imageAlignment=Alignment.center;
+  if (alignmentString=="bottomCenter") {
+    imageAlignment=Alignment.bottomCenter;
+  }else if (alignmentString=="bottomLeft") {
+    imageAlignment=Alignment.bottomLeft;
+  }else if (alignmentString=="bottomRight") {
+    imageAlignment=Alignment.bottomRight;
+  }else if (alignmentString=="centerLeft") {
+    imageAlignment=Alignment.centerLeft;
+  }else if (alignmentString=="centerRight") {
+    imageAlignment=Alignment.centerRight;
+  }else if (alignmentString=="topCenter") {
+    imageAlignment=Alignment.topCenter;
+  }else if (alignmentString=="topLeft") {
+    imageAlignment=Alignment.topLeft;
+  }else if (alignmentString=="topRight") {
+    imageAlignment=Alignment.topRight;
+  }
+  return imageAlignment;
+}
+class OnboardModel {
+  final int id;
+  final String title;
+  final String description;
+  final String image;
+  final Alignment imageAlignment;
+
+  OnboardModel(
+      {required this.id,
+      required this.title,
+      required this.description,
+      required this.image,
+      required this.imageAlignment,});
+
+  static Map<String, dynamic> toMap(OnboardModel form) {
+    var map = <String, dynamic>{};
+    map['id'] = form.id;
+    map['title'] = form.title;
+    map['description'] = form.description;
+    map['image'] = form.image;
+    return map;
+  }
+
+  factory OnboardModel.fromJson(dynamic json) {
+    return OnboardModel(
+      id: json['id'],
+      title: json['title'],
+      description: json['description'],
+      image: json['image'],
+      imageAlignment: stringToAlignment(json['imageAlignment']),
+    );
+  }
+}
+
+class permissionDescriptionModel {
+  final int id;
+  final String title;
+  final String image;
+
+  permissionDescriptionModel({
+    required this.id,
+    required this.title,
+    required this.image,
+  });
+  static Map<String, dynamic> toMap(
+      permissionDescriptionModel form) {
+    var map = <String, dynamic>{};
+    map['id'] =
+        form.id;
+    map['title'] =
+        form.title;
+    map['image'] =
+        form.image;
+    return map;
+  }
+
+  factory permissionDescriptionModel.fromJson(dynamic json) {
+    return permissionDescriptionModel(
+      id:
+          json["id"],
+      title:
+          json['title'],
+      image:
+          json['image'],
+    );
+  }
+}
+
+enum requestTypes { location, storage, camera, contact }
+
+class OnboardPermissionModel {
+  final int id;
+  final String title;
+  final String image;
+  final Permission request;
+  final bool requestIsGranted;
+  final List<permissionDescriptionModel>
+      permissionDescription;
+
+  OnboardPermissionModel(
+      {required this.id,
+      required this.title,
+      required this.image,
+      required this.request,
+      required this.requestIsGranted,
+      required this.permissionDescription});
+
+  static Map<String, dynamic> toMap(OnboardPermissionModel form) {
+    var map = <String, dynamic>{};
+    map['id'] = form.id;
+    map['title'] = form.title;
+    map['image'] = form.image;
+    map['request'] =
+        EnumToString.convertToString(form.request);
+    map['permissionDescription'] =
+        form.permissionDescription.map(
+            (permissionDescription) =>
+                permissionDescriptionModel.toMap(
+                    permissionDescription)).toList();
+    return map;
+  }
+
+  factory OnboardPermissionModel.fromJson(dynamic json) {
+    return OnboardPermissionModel(
+      id: json["id"],
+      title: json['title'],
+      image: json['image'],
+      request:
+          PermissionConverter.fromString(json['request']),
+      requestIsGranted: false,
+      permissionDescription: json['permissionDescription']
+          .map<permissionDescriptionModel>((permissionDescription) =>
+              permissionDescriptionModel.fromJson(
+                  permissionDescription))
+          .toList(),
+    );
+  }
+}
+
+class OnboardMainModel {
+  final String appIcon;
+  final String splashImage;
+  final List<OnboardModel> onboard;
+  final List<OnboardPermissionModel> onboardPermission;
+
+  OnboardMainModel(
+      {required this.appIcon,
+      required this.splashImage,
+      required this.onboard,
+      required this.onboardPermission});
+
+  static Map<String, dynamic> toMap(OnboardMainModel form) {
+    var map = <String, dynamic>{};
+    map['appIcon'] = form.appIcon;
+    map['splashImage'] = form.splashImage;
+    map['onboard'] =
+        form.onboard.map((Onboard) => OnboardModel.toMap(Onboard)).toList();
+    map['onboardPermission'] = form.onboardPermission.map(
+        (onboardPermission) =>
+            OnboardPermissionModel.toMap(onboardPermission)).toList();
+    return map;
+  }
+
+  factory OnboardMainModel.fromJson(dynamic json) {
+    return OnboardMainModel(
+      appIcon: json['appIcon'],
+      splashImage: json['splashImage'],
+      onboard: json['onboard']
+          .map<OnboardModel>((Onboard) => OnboardModel.fromJson(Onboard))
+          .toList(),
+      onboardPermission: json['onboardPermission']
+          .map<OnboardPermissionModel>((OnboardPermission) =>
+              OnboardPermissionModel.fromJson(OnboardPermission))
+          .toList(),
+    );
+  }
+}
+
+class OnboardController extends GetxController {
+  final onboardMainModel = Rxn<OnboardMainModel>();
+  set(data){
+    onboardMainModel.value= OnboardMainModel.fromJson(data);
+  }
+  clear(){
+    onboardMainModel.value= null;
+  }
+  @override
+  void onInit() {
+    ever(onboardMainModel, (value) => print("$value has been changed!!!"));
+    super.onInit();
+  }
+}
+final OnboardController onboardController = Get.put(OnboardController());

+ 11 - 0
lib/onboard/src/utils/constants.dart

@@ -0,0 +1,11 @@
+class StringConstants {
+  static StringConstants? _instance;
+
+  static StringConstants get instance => _instance ??= StringConstants._init();
+
+  StringConstants._init();
+
+  String get nextText => 'Next';
+  String get skipText => 'Skip';
+  String get lastPageText => 'Start';
+}

+ 9 - 0
lib/onboard/src/utils/extensions.dart

@@ -0,0 +1,9 @@
+import 'package:flutter/material.dart';
+
+extension OnboardStringExtension on String {
+  String get toPNG => 'assets/images/$this.png';
+}
+
+extension OnboardDurationExtension on BuildContext {
+  Duration get lowDuration => const Duration(milliseconds: 500);
+}

+ 11 - 0
lib/onboard/src/utils/paddings.dart

@@ -0,0 +1,11 @@
+import 'package:flutter/material.dart';
+
+class PaddingSymetric extends EdgeInsets {
+  const PaddingSymetric.horizontalLow() : super.symmetric(horizontal: 8);
+}
+
+class PaddingAll extends EdgeInsets {
+  const PaddingAll.low() : super.all(8);
+  const PaddingAll.medium() : super.all(16);
+  const PaddingAll.high() : super.all(24);
+}

+ 5 - 0
lib/onboard/src/utils/spaces.dart

@@ -0,0 +1,5 @@
+import 'package:flutter/material.dart';
+
+class SpaceBoxWidth extends SizedBox {
+  const SpaceBoxWidth.low({Key? key}) : super(key: key, width: 4);
+}

+ 162 - 0
lib/onboard/src/view/onboard.dart

@@ -0,0 +1,162 @@
+import 'package:flutter/material.dart';
+import 'package:general_package/themes/themes.dart';
+
+import '../../../constants/constants.dart';
+import '../utils/constants.dart';
+import '../utils/paddings.dart';
+import '../model/onboard_model.dart';
+import '../widgets/dots_selector.dart';
+import '../widgets/onboard_body.dart';
+import '../widgets/skip_button.dart';
+
+class Onboard extends StatefulWidget {
+  /// This color is generally used in the project.
+  final Color? primaryColor;
+
+  ///Required to create pages.
+  ///Length of the list must be more than 2.
+  final List<OnboardModel> onboardPages;
+  final List<OnboardPermissionModel> permissionOnboardPages;
+
+  ///This func works when skip button is pressed.
+  final VoidCallback skipButtonPressed;
+
+  ///This text will redirect to mentioned page
+  final String nextScreen;
+
+  ///This text will appear in the skip button.
+  final String? skipText;
+
+  ///This text will appear on the next button on all pages except the last page.
+  final String? nextText;
+
+  ///This text will appear in the next button on the last page.
+  final String? lastText;
+
+  ///Onboard Widget for use in your project.
+  Onboard(
+      {Key? key,
+      this.primaryColor,
+      required this.onboardPages,
+      required this.permissionOnboardPages,
+      required this.skipButtonPressed,
+      required this.nextScreen,
+      this.skipText,
+      this.nextText,
+      this.lastText})
+      :
+        // : assert(onboardPages.isNotEmpty),
+        //   assert(onboardPages.length > 2),
+        //   assert(nextText != null),
+        //   assert(skipText != null),
+        //   assert(lastText != null),
+        super(key: key);
+
+  @override
+  _OnboardState createState() => _OnboardState();
+}
+
+class _OnboardState extends State<Onboard> {
+  int _currentIndex = 0;
+  final PageController _pageController = PageController();
+  bool isOnBoardOpen = true;
+
+  @override
+  Widget build(BuildContext context) {
+    return SafeArea(
+      child: Scaffold(
+        backgroundColor: AppTheme.whiteColor,
+        body: Column(
+          children: [
+            const Spacer(flex: 1),
+            // Expanded(flex: 5, child: _topButtons(context)),
+            // const Spacer(flex: 1),
+            if (isOnBoardOpen) Expanded(flex: 40, child: _onBoardBodyWidget()),
+            // if (isOnBoardOpen) const Spacer(flex: 3),
+            if (isOnBoardOpen)
+              Expanded(flex: 9, child: _bottomButtons(context)),
+            if (!isOnBoardOpen)
+              Expanded(flex: 50, child: _permissionOnBoardBodyWidget()),
+          ],
+        ),
+      ),
+    );
+  }
+
+  Widget _permissionOnBoardBodyWidget() {
+    return Container(
+      padding: GeneralConstants.instance.padding15,
+      child: PageView.builder(
+        onPageChanged: (value) {
+          setState(() {
+            _currentIndex = value;
+          });
+        },
+        controller: _pageController,
+        itemCount: widget.permissionOnboardPages.length,
+        itemBuilder: (context, index) => PermissionOnboardBody(
+            onboardPermissionModel: widget.permissionOnboardPages[index],
+            removePermission: () {
+              setState(() {
+                widget.permissionOnboardPages
+                    .remove(widget.permissionOnboardPages[index]);
+              });
+            },
+            count: widget.permissionOnboardPages.length,
+            nextScreen: widget.nextScreen),
+      ),
+    );
+  }
+
+  PageView _onBoardBodyWidget() {
+    return PageView.builder(
+      onPageChanged: (value) {
+        setState(() {
+          _currentIndex = value;
+        });
+      },
+      controller: _pageController,
+      itemCount: widget.onboardPages.length,
+      itemBuilder: (context, index) => OnboardBody(
+        onboardModel: widget.onboardPages[index],
+      ),
+    );
+  }
+
+  Widget _bottomButtons(BuildContext context) {
+    return Container(
+      padding: GeneralConstants.instance.padding15,
+      child: Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: [
+          const Spacer(flex: 1),
+          Expanded(
+              flex: 10,
+              child: DotSelector(
+                primaryColor: widget.primaryColor,
+                pageCount: widget.onboardPages.length,
+                selectedPage: _currentIndex,
+              )),
+          const Spacer(flex: 30),
+          TextButton(
+            onPressed: () {
+              setState(() {
+                isOnBoardOpen = false;
+              });
+            },
+            child: Text(
+              (widget.onboardPages.length - 1 == _currentIndex)
+                  ? widget.lastText ?? StringConstants.instance.lastPageText
+                  : widget.skipText ?? StringConstants.instance.skipText,
+              style: Theme.of(context).textTheme.button,
+            ),
+          )
+          // OnboardSkipButton(
+          //   title: (widget.onboardPages.length-1==_currentIndex)? widget.lastText?? StringGeneralConstants.instance.lastPageText: widget.skipText ?? StringGeneralConstants.instance.skipText,
+          //   onPressed: widget.skipButtonPressed,
+          // )
+        ],
+      ),
+    );
+  }
+}

+ 35 - 0
lib/onboard/src/widgets/dots_selector.dart

@@ -0,0 +1,35 @@
+import 'package:flutter/material.dart';
+
+import '../utils/spaces.dart';
+
+class DotSelector extends StatelessWidget {
+  const DotSelector({Key? key, this.primaryColor, required this.pageCount, required this.selectedPage}) : super(key: key);
+
+  final Color? primaryColor;
+  final int pageCount;
+  final int selectedPage;
+
+  @override
+  Widget build(BuildContext context) {
+    const double height = 5;
+    const double width = 10;
+    const double selectedheight = 5;
+    const double selectedwidth = 17;
+    return ListView.builder(
+      scrollDirection: Axis.horizontal,
+      itemCount: pageCount,
+      itemBuilder: (context, index) {
+        return Row(
+          children: [
+            Container(
+              width: selectedPage == index ? selectedwidth : width,
+              height: selectedPage == index ? selectedheight : height,
+              decoration: BoxDecoration(color: selectedPage == index ? primaryColor??Colors.black : Colors.grey, shape: BoxShape.rectangle),
+            ),
+            const SpaceBoxWidth.low(),
+          ],
+        );
+      },
+    );
+  }
+}

+ 281 - 0
lib/onboard/src/widgets/onboard_body.dart

@@ -0,0 +1,281 @@
+// ignore_for_file: use_build_context_synchronously
+
+import 'dart:convert';
+
+import 'package:cached_memory_image/cached_memory_image.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:general_package/DB/db.dart';
+import 'package:general_package/dynamic_form/src/view/dynamic_form_button.dart';
+import 'package:general_package/responsive/responsive.dart';
+import 'package:get/get.dart';
+import 'package:permission_handler/permission_handler.dart';
+
+import '../../../constants/constants.dart';
+import '../utils/paddings.dart';
+import '../model/onboard_model.dart';
+
+class OnboardBody extends StatelessWidget {
+  final OnboardModel onboardModel;
+
+  const OnboardBody({
+    Key? key,
+    required this.onboardModel,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        Expanded(
+          flex: 6,
+          child: Padding(
+          padding: GeneralConstants.instance.padding15.copyWith(bottom: 0),
+            child: Text(
+              onboardModel.title,
+              style: Theme.of(context).textTheme.headline1,
+              textAlign: TextAlign.left,
+            ),
+          ),
+        ),
+        const SizedBox(
+          height: 10,
+        ),
+        Expanded(
+          flex: 5,
+          child: Padding(
+            padding:GeneralConstants.instance.padding15,
+            child: Text(
+              onboardModel.description,
+              style: Theme.of(context).textTheme.headline4,
+            ),
+          ),
+        ),
+        Expanded(
+          flex: 25,
+          child: CachedMemoryImage(
+            uniqueKey: onboardModel.image,
+            base64: onboardModel.image,
+            filterQuality: FilterQuality.high,
+            fit: BoxFit.cover,
+            alignment: onboardModel.imageAlignment,
+            width: double.infinity,
+          ),
+          // child: Image.memory(
+          //   base64Decode(onboardModel.image),
+          //   // onboardModel.image,
+          //   filterQuality: FilterQuality.high,
+          //   fit: BoxFit.fill,
+          // ),
+        ),
+      ],
+    );
+  }
+}
+
+class PermissionOnboardBody extends StatefulWidget {
+  final OnboardPermissionModel onboardPermissionModel;
+  final Function removePermission;
+  final int count;
+  final String nextScreen;
+  const PermissionOnboardBody({
+    Key? key,
+    required this.onboardPermissionModel,
+    required this.removePermission,
+    required this.count,
+    required this.nextScreen,
+  }) : super(key: key);
+
+  @override
+  State<PermissionOnboardBody> createState() => _PermissionOnboardBodyState();
+}
+
+class _PermissionOnboardBodyState extends State<PermissionOnboardBody> {
+  @override
+  void initState() {
+    // TODO: implement initState
+    super.initState();
+    checkPermission();
+  }
+
+  riseRemoveAndRedirect() async {
+    await widget.onboardPermissionModel.request.request().then((value) {
+      if (kDebugMode) {
+        print(
+            "${widget.onboardPermissionModel.request} - $value - after request");
+      }
+      if (value.isGranted) {
+        if (widget.count == 1) {
+          // Navigator.pushNamed(context, nextScreen);
+          LocalDB().writeData(GeneralConstants.instance.onBoardScreenShowedKey, "true");
+          Get.toNamed(widget.nextScreen);
+        } else {
+          widget.removePermission();
+        }
+      }
+    });
+  }
+
+  checkPermission() async {
+    var status = await widget.onboardPermissionModel.request.status;
+    if (kDebugMode) {
+      print("$status - ${widget.onboardPermissionModel.request}");
+    }
+    if (status.isGranted) {
+      if (widget.count == 1) {
+        // Navigator.pushNamed(context, nextScreen);
+          LocalDB().writeData(GeneralConstants.instance.onBoardScreenShowedKey, "true");
+        Get.toNamed(widget.nextScreen);
+      } else {
+        widget.removePermission();
+      }
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const PaddingAll.low(),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Expanded(
+            flex: 5,
+            child: Text(
+              widget.onboardPermissionModel.title,
+              style: Theme.of(context).textTheme.headline1,
+              textAlign: TextAlign.left,
+            ),
+          ),
+          const Spacer(flex: 2),
+          Expanded(
+            flex: 12,
+            child: Center(
+              child: CachedMemoryImage(
+                uniqueKey: widget.onboardPermissionModel.image,
+                base64: widget.onboardPermissionModel.image,
+                filterQuality: FilterQuality.high,
+                fit: BoxFit.fill,
+              ),
+              // child: Image.memory(
+              //   base64Decode(onboardPermissionModel.image),
+              //   // onboardPermissionModel.image,
+              //   filterQuality: FilterQuality.high,
+              //   fit: BoxFit.fill,
+              // ),
+            ),
+          ),
+          const Spacer(flex: 3),
+          Expanded(
+              flex: 20,
+              child: ListView.builder(
+                itemCount:
+                    widget.onboardPermissionModel.permissionDescription.length,
+                itemBuilder: (context, index) => Column(
+                  children: [
+                    Row(
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                      children: [
+                        SizedBox(
+                          width: ScreenTypeData.fullWidth(context) * .55,
+                          child: Text(
+                            widget.onboardPermissionModel
+                                .permissionDescription[index].title,
+                            style: Theme.of(context).textTheme.subtitle1,
+                            textAlign: TextAlign.left,
+                          ),
+                        ),
+                        CachedMemoryImage(
+                          uniqueKey: widget.onboardPermissionModel
+                              .permissionDescription[index].image,
+                          base64: widget.onboardPermissionModel
+                              .permissionDescription[index].image,
+                          fit: BoxFit.fill,
+                          width: 120,
+                        ),
+                        // Card(
+                        //   // elevation: 2,
+                        //   shape: RoundedRectangleBorder(
+                        //     borderRadius: BorderRadius.circular(15),
+                        //     //set border radius more than 50% of height and width to make circle
+                        //   ),
+                        //   child: ClipRRect(
+                        //     borderRadius: BorderRadius.circular(15.0),
+                        //     child: CachedMemoryImage(
+                        //       uniqueKey: onboardPermissionModel
+                        //           .permissionDescription[index].image,
+                        //       base64: onboardPermissionModel
+                        //           .permissionDescription[index].image,
+                        //       fit: BoxFit.fill,
+                        //       width: 120,
+                        //     ),
+                        //     //   child: Image.memory(
+                        //     //     base64Decode(
+                        //     //       onboardPermissionModel
+                        //     //           .permissionDescription[index].image,
+                        //     //     ),
+                        //     //     // onboardPermissionModel
+                        //     //     //     .permissionDescription[index]
+                        //     //     //     .image,
+                        //     //     width: 120,
+                        //     //     fit: BoxFit.fill,
+                        //     //   ),
+                        //   ),
+                        // ),
+                      ],
+                    ),
+                    const SizedBox(
+                      height: 5,
+                    )
+                  ],
+                ),
+              )),
+          Expanded(
+              flex: 5,
+              child: Center(
+                child: DynamicFormButton.bgButton(context, "Grant Access",
+                    onPressed: (() async {
+                  var status =
+                      await widget.onboardPermissionModel.request.status;
+                  if (kDebugMode) {
+                    print("$status - ${widget.onboardPermissionModel.request}");
+                  }
+                  if (status.isGranted) {
+                    if (widget.count == 1) {
+                      // Navigator.pushNamed(context, nextScreen);
+                      LocalDB().writeData(GeneralConstants.instance.onBoardScreenShowedKey, "true");
+                      Get.toNamed(widget.nextScreen);
+                    } else {
+                      widget.removePermission();
+                    }
+                  }
+                  if (status.isDenied) {
+                    await riseRemoveAndRedirect();
+                    if (kDebugMode) {
+                      print(
+                          "${widget.onboardPermissionModel.request} - isDenied");
+                    }
+                  }
+                  if (status.isPermanentlyDenied) {
+                    await riseRemoveAndRedirect();
+                    if (kDebugMode) {
+                      print(
+                          "${widget.onboardPermissionModel.request} - isPermanentlyDenied");
+                    }
+                  }
+                  if (await widget
+                      .onboardPermissionModel.request.isRestricted) {
+                    await riseRemoveAndRedirect();
+                    if (kDebugMode) {
+                      print(
+                          "${widget.onboardPermissionModel.request} - isRestricted");
+                    }
+                  }
+                })),
+              )),
+        ],
+      ),
+    );
+  }
+}

+ 19 - 0
lib/onboard/src/widgets/skip_button.dart

@@ -0,0 +1,19 @@
+import 'package:flutter/material.dart';
+import 'package:general_package/themes/themes.dart';
+
+class OnboardSkipButton extends StatelessWidget {
+  final VoidCallback onPressed;
+  final String title;
+  const OnboardSkipButton({Key? key, required this.onPressed, required this.title}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return TextButton(
+      onPressed: onPressed,
+      child: Text(
+        title,
+        style: Theme.of(context).textTheme.headline5!.copyWith(fontSize: 14,color: AppTheme.primaryColor),
+      ),
+    );
+  }
+}

+ 10 - 0
lib/permisiion_converter/permission_converter.dart

@@ -0,0 +1,10 @@
+import 'package:permission_handler/permission_handler.dart';
+
+extension PermissionConverter on Permission {
+  static Permission fromString(String permissionName) {
+    final matchedPermissions =
+        Permission.values.where((e) => e.toString() == "Permission.$permissionName");
+    if (matchedPermissions.isNotEmpty) return matchedPermissions.first;
+    return Permission.unknown;
+  }
+}

+ 259 - 0
lib/quantity_input/quantity_input.dart

@@ -0,0 +1,259 @@
+// ignore_for_file: library_private_types_in_public_api, depend_on_referenced_packages
+
+import 'package:intl/intl.dart';
+import '../icon_button_widget/icon_button_widget.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+
+/// quantity input type
+/// [int] default mask type, to format value as int
+/// [double] to format value as double
+enum QuantityInputType {
+  int,
+  double,
+}
+
+class QuantityInput extends StatefulWidget {
+  /// Has to be an int or double depending on QuantityInputType variable
+  final dynamic value;
+
+  /// Detects changes to the input and sends value through param
+  final Function(String) onChanged;
+
+  /// The value that is incremented or decremented each time the user presses a button
+  final dynamic step;
+
+  /// The number of decimal places that can be displayed for double input
+  final int decimalDigits;
+
+  /// Set min value to be displayed in input
+  final dynamic minValue;
+
+  /// Set max value to be displayed in input
+  final dynamic maxValue;
+
+  /// The width of the textfield input
+  final double inputWidth;
+
+  /// Sets color for increment and decrement buttons
+  final Color? buttonColor;
+
+  /// Sets color for icons inside increment and decrement buttons
+  final Color? iconColor;
+
+  /// Sets label for input
+  final String label;
+
+  /// Determines if the input will be readOnly
+  final bool readOnly;
+
+  /// If set to true, the input can accept the value 0
+  final bool acceptsZero;
+
+  /// If set to true, the input can accept negative values
+  final bool acceptsNegatives;
+
+  /// Determines if the input will manage values as int or double
+  final QuantityInputType? type;
+
+  /// Sets custom InputDecoration to the widget TextFormField
+  final InputDecoration? decoration;
+
+  /// Sets elevation to increment and decrement buttons
+  final double elevation;
+
+  /// Creates a widget that can be used to manage number inputs
+  ///
+  /// Widget can manage integer or double values
+  const QuantityInput(
+      {super.key,
+      required this.value,
+      required this.onChanged,
+      this.step = 1,
+      this.decimalDigits = 1,
+      this.buttonColor,
+      this.iconColor,
+      this.label = '',
+      this.readOnly = false,
+      this.acceptsNegatives = false,
+      this.acceptsZero = false,
+      this.minValue = 1,
+      this.maxValue = 100000,
+      this.type = QuantityInputType.int,
+      this.inputWidth = 80,
+      this.decoration,
+      this.elevation = 5})
+      : assert(decimalDigits > 0,
+            'Decimal digits cannot be set to zero or negative value'),
+        assert(!(acceptsZero && acceptsNegatives),
+            'acceptsZero and acceptsNegatives cannot be simultaneously true');
+
+  @override
+  _QuantityInputState createState() => _QuantityInputState();
+}
+
+class _QuantityInputState extends State<QuantityInput> {
+  final TextEditingController _controller = TextEditingController();
+
+  @override
+  void initState() {
+    super.initState();
+    _controller.text = valueFormatter(widget.value);
+  }
+
+  String valueFormatter(dynamic value) {
+    String extraZeros = '';
+
+    if (widget.decimalDigits > 0 && widget.type == QuantityInputType.double) {
+      extraZeros = '.';
+      extraZeros = extraZeros.padRight(widget.decimalDigits + 1, '0');
+    }
+
+    NumberFormat formatter = NumberFormat(
+        '#,###,###,###,###,###,###,###,###,##0$extraZeros', 'en_US');
+
+    return formatter.format(value);
+  }
+
+  String parseNewDouble(String value) {
+    String fullPartOfDouble =
+        value.substring(0, value.length - widget.decimalDigits);
+    String decimalPartOfDouble =
+        value.substring(value.length - widget.decimalDigits);
+    String newFullValue = '$fullPartOfDouble.$decimalPartOfDouble';
+
+    return newFullValue;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+        padding: const EdgeInsets.symmetric(vertical: 5),
+        child: Column(
+            mainAxisSize: MainAxisSize.min,
+            mainAxisAlignment: MainAxisAlignment.start,
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              Visibility(
+                  visible: widget.label.isNotEmpty,
+                  child: Padding(
+                      padding: const EdgeInsets.only(bottom: 5),
+                      child: Text(widget.label,
+                          textAlign: TextAlign.start,
+                          style: TextStyle(
+                              color: Colors.grey[500],
+                              fontSize: 13,
+                              fontWeight: FontWeight.w500)))),
+              Row(
+                  mainAxisSize: MainAxisSize.min,
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  children: [
+                    IconButtonWidget(
+                        icon: Icons.remove,
+                        iconColor: widget.iconColor,
+                        buttonColor: widget.buttonColor,
+                        elevation: widget.elevation,
+                        onTap: () {
+                          dynamic currentValue = 0;
+
+                          if (widget.acceptsNegatives ||
+                              ((widget.value - widget.step) > 0 &&
+                                  widget.type == QuantityInputType.double) ||
+                              ((widget.value - widget.step) >= 1 &&
+                                  widget.type == QuantityInputType.int) ||
+                              (widget.acceptsZero &&
+                                  (widget.value - widget.step) == 0)) {
+                            currentValue = widget.value - widget.step;
+                          } else {
+                            currentValue = widget.value;
+                          }
+
+                          String formattedValue = valueFormatter(currentValue);
+                          _controller.value = TextEditingValue(
+                              text: formattedValue,
+                              selection: TextSelection.collapsed(
+                                  offset: formattedValue.length));
+                          widget.onChanged(formattedValue);
+                        }),
+                    SizedBox(
+                        height: 38,
+                        width: widget.inputWidth,
+                        child: Padding(
+                            padding: const EdgeInsets.symmetric(horizontal: 5),
+                            child: TextFormField(
+                                controller: _controller,
+                                textAlign: TextAlign.center,
+                                decoration: widget.decoration,
+                                readOnly: widget.readOnly,
+                                keyboardType: TextInputType.number,
+                                inputFormatters: [
+                                  TextInputFormatter.withFunction(
+                                      (oldValue, newValue) {
+                                    String simpleValue = '';
+                                    String formattedValue = '';
+                                    if (newValue.text
+                                        .contains(RegExp(r'[a-zA-Z]'))) {
+                                      return oldValue;
+                                    }
+
+                                    if (widget.type ==
+                                        QuantityInputType.double) {
+                                      simpleValue = newValue.text
+                                          .replaceAll(',', '')
+                                          .replaceAll('.', '');
+
+                                      if (simpleValue.length == 1) {
+                                        simpleValue =
+                                            simpleValue.padLeft(1, '0');
+                                      }
+
+                                      formattedValue = valueFormatter(
+                                          double.parse(
+                                              parseNewDouble(simpleValue)));
+                                    } else {
+                                      if (newValue.text.isEmpty) {
+                                        formattedValue = '0';
+                                      } else {
+                                        simpleValue =
+                                            newValue.text.replaceAll(',', '');
+
+                                        formattedValue = valueFormatter(
+                                            int.parse(simpleValue));
+                                      }
+                                    }
+
+                                    return TextEditingValue(
+                                        text: formattedValue,
+                                        selection: TextSelection.collapsed(
+                                            offset: formattedValue.length));
+                                  })
+                                ],
+                                onChanged: (value) =>
+                                    widget.onChanged(value)))),
+                    IconButtonWidget(
+                        icon: Icons.add,
+                        iconColor: widget.iconColor,
+                        buttonColor: widget.buttonColor,
+                        elevation: widget.elevation,
+                        onTap: () {
+                          dynamic currentValue = 0;
+
+                          if (widget.maxValue >= widget.value &&
+                              widget.maxValue >= widget.value + widget.step) {
+                            currentValue = widget.value + widget.step;
+                          } else {
+                            currentValue = widget.value;
+                          }
+
+                          String formattedValue = valueFormatter(currentValue);
+                          _controller.value = TextEditingValue(
+                              text: formattedValue,
+                              selection: TextSelection.collapsed(
+                                  offset: formattedValue.length));
+                          widget.onChanged(formattedValue);
+                        })
+                  ])
+            ]));
+  }
+}

+ 7 - 0
lib/rating/rating.dart

@@ -0,0 +1,7 @@
+library rating;
+
+export 'src/models/rating_config_model.dart';
+export 'src/models/rating_criterion_model.dart';
+export 'src/models/rating_model.dart';
+export 'src/rating_controller.dart';
+export 'src/rating_widget.dart';

+ 40 - 0
lib/rating/src/models/rating_config_model.dart

@@ -0,0 +1,40 @@
+import 'rating_criterion_model.dart';
+
+class RatingConfigModel {
+  final int id;
+  final String ratingSurvey1;
+  final String ratingSurvey2;
+  final String ratingSurvey3;
+  final String ratingSurvey4;
+  final String ratingSurvey5;
+  final List<RatingCriterionModel> items;
+  RatingConfigModel({
+    required this.id,
+    required this.ratingSurvey1,
+    required this.ratingSurvey2,
+    required this.ratingSurvey3,
+    required this.ratingSurvey4,
+    required this.ratingSurvey5,
+    required this.items,
+  });
+
+  RatingConfigModel copyWith({
+    int? id,
+    String? ratingSurvey1,
+    String? ratingSurvey2,
+    String? ratingSurvey3,
+    String? ratingSurvey4,
+    String? ratingSurvey5,
+    List<RatingCriterionModel>? items,
+  }) {
+    return RatingConfigModel(
+      id: id ?? this.id,
+      ratingSurvey1: ratingSurvey1 ?? this.ratingSurvey1,
+      ratingSurvey2: ratingSurvey2 ?? this.ratingSurvey2,
+      ratingSurvey3: ratingSurvey3 ?? this.ratingSurvey3,
+      ratingSurvey4: ratingSurvey4 ?? this.ratingSurvey4,
+      ratingSurvey5: ratingSurvey5 ?? this.ratingSurvey5,
+      items: items ?? this.items,
+    );
+  }
+}

+ 21 - 0
lib/rating/src/models/rating_criterion_model.dart

@@ -0,0 +1,21 @@
+class RatingCriterionModel {
+  final int id;
+  final String name;
+  RatingCriterionModel({
+    required this.id,
+    required this.name,
+  });
+
+  RatingCriterionModel copyWith({
+    int? id,
+    String? name,
+  }) {
+    return RatingCriterionModel(
+      id: id ?? this.id,
+      name: name ?? this.name,
+    );
+  }
+
+  @override
+  String toString() => 'RatingCriterionModel(id: $id, name: $name)';
+}

+ 29 - 0
lib/rating/src/models/rating_model.dart

@@ -0,0 +1,29 @@
+import 'rating_config_model.dart';
+
+class RatingModel {
+  final int id;
+  final String? title;
+  final String? subtitle;
+  final RatingConfigModel ratingConfig;
+
+  RatingModel({
+    required this.id,
+    required this.title,
+    required this.subtitle,
+    required this.ratingConfig,
+  });
+
+  RatingModel copyWith({
+    int? id,
+    String? title,
+    String? subtitle,
+    RatingConfigModel? ratingConfig,
+  }) {
+    return RatingModel(
+      id: id ?? this.id,
+      title: title ?? this.title,
+      subtitle: subtitle ?? this.subtitle,
+      ratingConfig: ratingConfig ?? this.ratingConfig,
+    );
+  }
+}

+ 71 - 0
lib/rating/src/rating_controller.dart

@@ -0,0 +1,71 @@
+import 'dart:async';
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+
+import 'models/rating_criterion_model.dart';
+import 'models/rating_model.dart';
+import 'rating_cubit.dart';
+
+export 'models/rating_criterion_model.dart';
+//Exports
+export 'models/rating_model.dart';
+
+abstract class RatingController {
+  final RatingModel ratingModel;
+  RatingController(this.ratingModel);
+
+  Future<void> ignoreForEverCallback();
+  Future<void> saveRatingCallback(int rate, List<RatingCriterionModel> selectedCriterions);
+
+  late final RatingCubit ratingCubit = RatingCubit(ratingModel, ignoreForEverCallback, saveRatingCallback);
+
+  _RatingListenHelper? _ratingListenHelper;
+  void listenStateChanges(BuildContext context) {
+    _ratingListenHelper = _RatingListenHelper(context, ratingCubit);
+  }
+
+  @mustCallSuper
+  void dispose() {
+    _ratingListenHelper?.dispose();
+    ratingCubit.close();
+  }
+}
+
+class _RatingListenHelper {
+  final BuildContext context;
+  _RatingListenHelper(this.context, RatingCubit ratingCubit) {
+    // _streamSubscriptions.add(ratingCubit.stream.listen(_loadingStateListener));
+    _streamSubscriptions.add(ratingCubit.stream.listen(_closeDialogStateListener, onError: _onErrorListener));
+    // ratingCubit.stream.handleError(_onErrorListener);
+  }
+
+  final _streamSubscriptions = <StreamSubscription>[];
+
+  // void _loadingStateListener(RatingState state) {
+  //   if (state is LoadingState) {
+  //     LoaderWidget.showLoader(context, title: state.message);
+  //   } else {
+  //     LoaderWidget.hideLoader(context);
+  //   }
+  // }
+
+  void _closeDialogStateListener(RatingState state) {
+    if (state is CloseDialogState) {
+      Navigator.of(context).pop(state.isIgnored);
+    }
+  }
+
+  void _onErrorListener(Object error, StackTrace stackTrace) {
+    if (kDebugMode) {
+      debugPrint("[Person Store Rating Error] - $error");
+      ScaffoldMessenger.maybeOf(context)?.showSnackBar(SnackBar(content: Text('Error ocurred: $error')));
+    }
+  }
+
+  void dispose() {
+    for (var subscription in _streamSubscriptions) {
+      subscription.cancel();
+    }
+  }
+}

+ 53 - 0
lib/rating/src/rating_cubit.dart

@@ -0,0 +1,53 @@
+// ignore_for_file: unused_catch_stack
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'models/rating_criterion_model.dart';
+import 'models/rating_model.dart';
+import 'rating_state.dart';
+
+export 'rating_state.dart';
+
+typedef IgnoreForEverCallback = Future<void> Function();
+typedef SaveRatingCallback = Future<void> Function(int rate, List<RatingCriterionModel> selectedCriterions);
+
+class RatingCubit extends Cubit<RatingState> {
+  final IgnoreForEverCallback _ignoreForEverCallback;
+  final SaveRatingCallback _saveRatingCallback;
+  final RatingModel model;
+
+  RatingCubit(this.model, this._ignoreForEverCallback, this._saveRatingCallback) : super(IdleState());
+
+  final selectedCriterions = <RatingCriterionModel>{};
+
+  Future<void> ignoreForEver() async {
+    try {
+      emit(LoadingState("Cancelando..."));
+      await _ignoreForEverCallback.call();
+      emit(CloseDialogState(true));
+    } catch (ex, stack) {
+      debugPrint('$ex');
+      // addError(ex);
+      emit(CloseDialogState(false));
+    }
+  }
+
+  void selectedCriterionsUpdate(RatingCriterionModel criterion, bool isAdded) {
+    if (isAdded) selectedCriterions.add(criterion);
+    if (!isAdded) selectedCriterions.removeWhere((item) => item.id == criterion.id);
+    emit(SelectedCriterionsState(selectedCriterions));
+  }
+
+  void saveRate(int rate) async {
+    try {
+      emit(LoadingState("Enviando Avaliação..."));
+      await _saveRatingCallback.call(rate, selectedCriterions.toList());
+      emit(CloseDialogState(false));
+    } catch (ex, stack) {
+      debugPrint('$ex');
+      // addError(ex);
+      emit(CloseDialogState(false));
+    }
+  }
+}

+ 31 - 0
lib/rating/src/rating_state.dart

@@ -0,0 +1,31 @@
+import 'package:flutter/foundation.dart';
+
+import 'models/rating_criterion_model.dart';
+
+@immutable
+abstract class RatingState {}
+
+class IdleState extends RatingState {}
+
+class LoadingState extends RatingState {
+  final String message;
+  LoadingState(this.message);
+}
+
+class CloseDialogState extends RatingState {
+  final bool isIgnored;
+
+  CloseDialogState(this.isIgnored);
+}
+
+class SelectedCriterionsState extends RatingState {
+  final Set<RatingCriterionModel> selectedCriterions;
+  SelectedCriterionsState(this.selectedCriterions);
+}
+
+class RateState extends RatingState {
+  final int rateCount;
+  final List<RatingCriterionModel> criterions;
+
+  RateState({required this.rateCount, required this.criterions});
+}

+ 183 - 0
lib/rating/src/rating_widget.dart

@@ -0,0 +1,183 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'rating_controller.dart';
+import 'rating_cubit.dart';
+import 'widgets/criterion_button_widget.dart';
+import 'widgets/default_button.dart';
+import 'widgets/stars_widget.dart';
+
+class RatingWidget extends StatefulWidget {
+  final RatingController controller;
+  const RatingWidget({Key? key, required this.controller}) : super(key: key);
+
+  @override
+  _RatingWidgetState createState() => _RatingWidgetState();
+}
+
+class _RatingWidgetState extends State<RatingWidget> {
+  final animationDuration = const Duration(milliseconds: 800);
+  final animationCurve = Curves.ease;
+
+  int selectedRate = 0;
+  late RatingController controller = widget.controller;
+
+  @override
+  void initState() {
+    super.initState();
+    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
+      controller.listenStateChanges(context);
+    });
+  }
+
+  @override
+  void dispose() {
+    controller.dispose();
+    super.dispose();
+  }
+
+  String get ratingSurvey {
+    final options = [
+      '',
+      controller.ratingModel.ratingConfig.ratingSurvey1,
+      controller.ratingModel.ratingConfig.ratingSurvey2,
+      controller.ratingModel.ratingConfig.ratingSurvey3,
+      controller.ratingModel.ratingConfig.ratingSurvey4,
+      controller.ratingModel.ratingConfig.ratingSurvey5,
+    ];
+    return options.length > selectedRate ? options[selectedRate] : options.first;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<RatingCubit, RatingState>(
+      bloc: controller.ratingCubit,
+      buildWhen: (previous, current) => current is LoadingState || previous is LoadingState,
+      builder: (context, state) {
+        final isLoading = state is LoadingState;
+        return IgnorePointer(
+          ignoring: isLoading,
+          child: AnimatedPadding(
+            duration: animationDuration,
+            curve: animationCurve,
+            padding: EdgeInsets.symmetric(horizontal: selectedRate == 0 ? 50 : 30),
+            child: Column(
+              mainAxisSize: MainAxisSize.min,
+              children: [
+                const SizedBox(height: 10),
+                if (controller.ratingModel.title != null) ...{
+                  Text(
+                    controller.ratingModel.title!,
+                    style: const TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
+                  ),
+                },
+                const SizedBox(height: 10),
+                if (controller.ratingModel.subtitle != null) ...{
+                  Text(controller.ratingModel.subtitle!),
+                },
+                const SizedBox(height: 20),
+                AnimatedContainer(
+                  duration: animationDuration,
+                  curve: animationCurve,
+                  width: selectedRate == 0 ? MediaQuery.of(context).size.width * 0.8 : MediaQuery.of(context).size.width * 0.4,
+                  child: FittedBox(
+                    child: StarsWidget(
+                      selectedColor: Colors.amber,
+                      selectedLenght: selectedRate,
+                      unselectedColor: Colors.grey,
+                      length: 5,
+                      onChanged: (count) {
+                        setState(() => selectedRate = count);
+                      },
+                    ),
+                  ),
+                ),
+                const SizedBox(height: 10),
+                AnimatedAlign(
+                  duration: animationDuration,
+                  curve: animationCurve,
+                  alignment: Alignment.topCenter,
+                  heightFactor: selectedRate == 0 ? 0 : 1,
+                  child: AnimatedOpacity(
+                    duration: animationDuration,
+                    curve: animationCurve,
+                    opacity: selectedRate == 0 ? 0 : 1,
+                    child: Column(
+                      mainAxisSize: MainAxisSize.min,
+                      children: [
+                        const SizedBox(height: 14),
+                        Text(
+                          ratingSurvey,
+                          style: const TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
+                        ),
+                        const SizedBox(height: 20),
+                        GridView.count(
+                          crossAxisCount: 2,
+                          crossAxisSpacing: 10,
+                          mainAxisSpacing: 10,
+                          childAspectRatio: 2.9,
+                          shrinkWrap: true,
+                          physics: const NeverScrollableScrollPhysics(),
+                          children: List.from(controller.ratingModel.ratingConfig.items.map(
+                            (criterion) => CriterionButton(
+                              text: criterion.name,
+                              onSelectChange: (selected) => controller.ratingCubit.selectedCriterionsUpdate(criterion, selected),
+                            ),
+                          )),
+                        ),
+                        const SizedBox(height: 20),
+                      ],
+                    ),
+                  ),
+                ),
+                Stack(
+                  children: [
+                    AnimatedOpacity(
+                      duration: animationDuration,
+                      curve: animationCurve,
+                      opacity: selectedRate == 0 ? 0 : 1,
+                      child: Center(
+                        child: DefaultButton.text(
+                          "CONFIRMAR",
+                          textColor: Colors.white,
+                          color: Theme.of(context).colorScheme.secondary,
+                          outlineColor: Theme.of(context).colorScheme.secondary,
+                          onPressed: () => controller.ratingCubit.saveRate(selectedRate),
+                          isLoading: isLoading,
+                        ),
+                      ),
+                    ),
+                    IgnorePointer(
+                      ignoring: selectedRate != 0,
+                      child: AnimatedOpacity(
+                        duration: animationDuration,
+                        curve: animationCurve,
+                        opacity: selectedRate == 0 ? 1 : 0,
+                        child: Align(
+                          alignment: Alignment.bottomCenter,
+                          child: DefaultButton(
+                            outline: false,
+                            flat: true,
+                            color: Colors.transparent,
+                            textColor: const Color(0xFF2F333A),
+                            onPressed: () => controller.ratingCubit.ignoreForEver(),
+                            isLoading: isLoading,
+                            child: const Text(
+                              "Prefiro não classificar",
+                              style: TextStyle(decoration: TextDecoration.underline, color: Colors.black54, fontSize: 12),
+                            ),
+                          ),
+                        ),
+                      ),
+                    ),
+                  ],
+                ),
+                const SizedBox(height: 15),
+              ],
+            ),
+          ),
+        );
+      },
+    );
+  }
+}

+ 40 - 0
lib/rating/src/widgets/busy_indicator.dart

@@ -0,0 +1,40 @@
+import 'dart:math';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_spinkit/flutter_spinkit.dart';
+
+class BusyIndicator extends StatelessWidget {
+  final Widget indicator;
+
+  const BusyIndicator._(this.indicator);
+  factory BusyIndicator({Color? color, double size = 20.0}) => BusyIndicator._(SpinKitThreeBounce(color: color, size: size));
+
+  factory BusyIndicator.accent(BuildContext context, {double size = 20.0}) {
+    return BusyIndicator._(SpinKitThreeBounce(color: Theme.of(context).colorScheme.secondary, size: size));
+  }
+
+  factory BusyIndicator.round({Color color = const Color(0xFF2F333A), double size = 50.0}) {
+    return BusyIndicator._(Stack(
+      children: <Widget>[
+        Center(
+          child: SizedBox.fromSize(
+            size: Size.square(size),
+            child: CustomPaint(
+              willChange: false,
+              foregroundPainter: RingPainter(
+                paintWidth: 4,
+                trackColor: const Color(0xFFC5C5C5),
+                progressPercent: 1,
+                startAngle: pi * 0,
+              ),
+            ),
+          ),
+        ),
+        SpinKitRing(color: color, lineWidth: 4, size: size),
+      ],
+    ));
+  }
+
+  @override
+  Widget build(BuildContext context) => indicator;
+}

+ 44 - 0
lib/rating/src/widgets/criterion_button_widget.dart

@@ -0,0 +1,44 @@
+import 'package:flutter/material.dart';
+
+import 'default_button.dart';
+
+class CriterionButton extends StatefulWidget {
+  final String text;
+  final void Function(bool isSelected)? onSelectChange;
+  final bool? intialSelectedValue;
+
+  const CriterionButton({
+    Key? key,
+    required this.text,
+    this.intialSelectedValue,
+    this.onSelectChange,
+  }) : super(key: key);
+
+  @override
+  _CriterionButtonState createState() => _CriterionButtonState();
+}
+
+class _CriterionButtonState extends State<CriterionButton> {
+  late bool isSelected = widget.intialSelectedValue ?? false;
+
+  @override
+  Widget build(BuildContext context) {
+    return Stack(
+      clipBehavior: Clip.none,
+      children: [
+        DefaultButton.text(
+          widget.text,
+          width: double.infinity,
+          outlineColor: Theme.of(context).colorScheme.secondary,
+          color: isSelected ? Theme.of(context).colorScheme.secondary.withOpacity(.2) : Colors.transparent,
+          textColor: isSelected ? Theme.of(context).colorScheme.secondary : const Color(0xFF2F333A),
+          flat: true,
+          onPressed: () {
+            setState(() => isSelected = !isSelected);
+            widget.onSelectChange?.call(isSelected);
+          },
+        ),
+      ],
+    );
+  }
+}

+ 89 - 0
lib/rating/src/widgets/default_button.dart

@@ -0,0 +1,89 @@
+import 'package:flutter/material.dart';
+
+import 'busy_indicator.dart';
+
+class DefaultButton extends StatelessWidget {
+  final Widget child;
+  final VoidCallback? onPressed;
+  final double? height;
+  final double? width;
+  final bool outline;
+  final Color? color;
+  final Color textColor;
+  final Color? outlineColor;
+  final bool flat;
+  final bool isLoading;
+  final double radius;
+
+  const DefaultButton({
+    required this.child,
+    required this.onPressed,
+    Key? key,
+    this.height = 50,
+    this.width = 150,
+    this.outline = true,
+    this.color,
+    this.textColor = const Color(0xFFF8D560),
+    this.outlineColor,
+    this.flat = false,
+    this.isLoading = false,
+    this.radius = 25,
+  }) : super(key: key);
+
+  DefaultButton.text(
+    String text, {
+    required this.onPressed,
+    Key? key,
+    this.height = 50,
+    this.width = 150,
+    this.outline = true,
+    this.color,
+    this.textColor = const Color(0xFFF8D560),
+    this.outlineColor,
+    this.flat = false,
+    this.isLoading = false,
+    this.radius = 25,
+  })  : child = Text(
+          text,
+          textAlign: TextAlign.center,
+          style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 12),
+        ),
+        super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    final style = ButtonStyle(
+      elevation: MaterialStateProperty.all(flat ? 0 : 2),
+      backgroundColor: MaterialStateProperty.all(color ?? Colors.white),
+      foregroundColor: MaterialStateProperty.all(textColor),
+      shape: MaterialStateProperty.all(RoundedRectangleBorder(
+        borderRadius: BorderRadius.circular(radius),
+        side: (onPressed == null || !outline) ? BorderSide.none : BorderSide(color: outlineColor ?? textColor, width: 1),
+      )),
+    );
+
+    final content = Padding(
+      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
+      child: Stack(
+        children: [
+          if (isLoading) ...{
+            Positioned.fill(
+              child: FittedBox(
+                fit: BoxFit.none,
+                child: BusyIndicator(size: 16.0, color: onPressed != null ? textColor : const Color(0xFFC5C5C5)),
+              ),
+            ),
+          },
+          Opacity(opacity: isLoading ? 0 : 1, child: child),
+        ],
+      ),
+    );
+    return Container(
+      constraints: BoxConstraints(minWidth: width ?? double.infinity),
+      height: height ?? 45.0,
+      child: outline
+          ? OutlinedButton(onPressed: onPressed, style: style, child: content)
+          : TextButton(onPressed: onPressed, style: style, child: content),
+    );
+  }
+}

+ 112 - 0
lib/rating/src/widgets/loader_widget.dart

@@ -0,0 +1,112 @@
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+
+import 'busy_indicator.dart';
+
+typedef Loader<T> = Future<T> Function();
+
+class LoaderWidget {
+  static bool _showingLoader = false;
+//  static Completer _loader;
+
+  static Future<T?> showLoader<T>(
+    BuildContext context, {
+    required String title,
+    String? content,
+    Loader<T>? loader,
+    Duration? minDuration,
+  }) async {
+    showModalBottomSheet(
+      context: context,
+      backgroundColor: Colors.transparent,
+      isDismissible: false,
+      isScrollControlled: false,
+      enableDrag: false,
+      builder: (context) => AppBottomSheetLoader(title: title, content: content),
+    );
+
+    _showingLoader = true;
+
+    T? result;
+
+    final futures = <Future<T?>>[];
+    if (minDuration != null) {
+      futures.add(
+        Future.wait(
+          [
+            Future.delayed(minDuration, () => null),
+            if (loader != null) loader(),
+          ],
+        ).then((value) => value.firstWhere((element) => element != null, orElse: () => null)),
+      );
+
+      result = await Future.any<T?>(futures);
+      _hideLoader(context, result);
+    }
+
+    return result;
+  }
+
+  static void hideLoader(BuildContext context) {
+    _hideLoader(context, null);
+  }
+
+  static void _hideLoader<T>(BuildContext context, T result) {
+    if (!_showingLoader) return;
+    _showingLoader = false;
+    Navigator.pop(context, result);
+  }
+
+//  static Future<bool> showAlert(BuildContext context, String content, {String title, String action = "Entendi"}) async {
+//    return showOptions(context, content, title: title, defaultAction: action).then((action) => action != null);
+//  }
+//
+//  static Future<bool> showConfirm(BuildContext context, String content,
+//      {String title, String confirmAction = "Sim", String cancelAction = "Não"}) async {
+//    return showOptions(context, content, title: title, defaultAction: confirmAction, actions: [cancelAction]).then((action) => action?.isDefault);
+//  }
+
+}
+
+class AppBottomSheetLoader<T> extends StatelessWidget {
+  final String title;
+  final String? content;
+
+  const AppBottomSheetLoader({Key? key, required this.title, this.content}) : super(key: key);
+
+  final double defaultPadding = 20.0;
+  @override
+  Widget build(BuildContext context) {
+    return Align(
+      alignment: Alignment.bottomCenter,
+      child: Container(
+        color: Colors.white,
+        child: Column(
+          crossAxisAlignment: CrossAxisAlignment.stretch,
+          mainAxisSize: MainAxisSize.min,
+          children: <Widget>[
+            SizedBox(height: defaultPadding * 2),
+            BusyIndicator.round(),
+            SizedBox(height: title.isNotEmpty || (content?.isNotEmpty ?? false) ? defaultPadding * 1.5 : 0),
+            if (title.isNotEmpty)
+              Text(
+                title,
+                textAlign: TextAlign.center,
+                style: const TextStyle(color: Colors.black87, fontWeight: FontWeight.w700, fontSize: 22),
+              ),
+            SizedBox(height: title.isNotEmpty && (content?.isNotEmpty ?? false) ? defaultPadding * 0.5 : 0),
+            if (content?.isNotEmpty ?? false)
+              Text(
+                content ?? "",
+                softWrap: true,
+                textAlign: TextAlign.center,
+                style: const TextStyle(color: Colors.black54, fontSize: 15),
+              ),
+            SizedBox(height: defaultPadding * 2),
+          ],
+        ),
+      ),
+    );
+  }
+}

+ 85 - 0
lib/rating/src/widgets/stars_widget.dart

@@ -0,0 +1,85 @@
+import 'package:flutter/material.dart';
+
+class StarsWidget extends StatefulWidget {
+  final int length;
+  final String? title;
+  final bool enabled;
+  final double iconSize;
+  final int selectedLenght;
+  final Color? selectedColor;
+  final Color? unselectedColor;
+  final void Function(int selectedLenght)? onChanged;
+
+  const StarsWidget({
+    Key? key,
+    this.title,
+    required this.length,
+    this.enabled = true,
+    this.selectedLenght = 0,
+    this.selectedColor,
+    this.unselectedColor,
+    this.onChanged,
+    this.iconSize = 28,
+  })  : assert(length > 0),
+        assert(length >= selectedLenght),
+        super(key: key);
+
+  @override
+  _StarsWidgetState createState() => _StarsWidgetState();
+}
+
+class _StarsWidgetState extends State<StarsWidget> {
+  @override
+  Widget build(BuildContext context) {
+    var selectedLenght = widget.selectedLenght;
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: <Widget>[
+        if (widget.title != null)
+          Padding(
+            padding: const EdgeInsets.only(bottom: 5),
+            child: Text(
+              widget.title!,
+              style: Theme.of(context).textTheme.headline6,
+            ),
+          ),
+        Row(
+          mainAxisSize: MainAxisSize.min,
+          children: List.generate(
+            widget.length,
+            (index) {
+              final selected = selectedLenght > index;
+              return GestureDetector(
+                onTap: () {
+                  if (widget.enabled) {
+                    var isRepeat = selectedLenght != index + 1;
+                    if (isRepeat) {
+                      if (selectedLenght == 1 && index == 0) {
+                        setState(() => selectedLenght = 0);
+                      } else {
+                        setState(() => selectedLenght = index + 1);
+                      }
+                      if (widget.onChanged != null) {
+                        widget.onChanged?.call(selectedLenght);
+                      }
+                    }
+                  }
+                },
+                child: Padding(
+                  padding: const EdgeInsets.symmetric(horizontal: 2),
+                  child: Icon(
+                    Icons.star_rounded,
+                    size: widget.iconSize,
+                    color: selected
+                        ? (widget.selectedColor ?? Theme.of(context).colorScheme.secondary)
+                        : widget.unselectedColor ?? Theme.of(context).textTheme.headline5?.color,
+                  ),
+                ),
+              );
+            },
+          ),
+        ),
+      ],
+    );
+  }
+}

+ 113 - 0
lib/responsive/responsive.dart

@@ -0,0 +1,113 @@
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+
+import 'package:flutter/material.dart';
+
+class ResponsiveWidget extends StatelessWidget {
+  const ResponsiveWidget({
+    Key? key,
+    required this.mobileBody,
+    this.tabletBody,
+    this.desktopBody,
+  }) : super(key: key);
+
+  final Widget mobileBody;
+  final Widget? tabletBody;
+  final Widget? desktopBody;
+  
+  // This isMobile, isTablet, isDesktop helep us later
+  static bool isMobile(BuildContext context) =>
+      MediaQuery.of(context).size.width < 650;
+
+  static bool isTablet(BuildContext context) =>
+      MediaQuery.of(context).size.width < 1200 &&
+      MediaQuery.of(context).size.width >= 650;
+
+  static bool isDesktop(BuildContext context) =>
+      MediaQuery.of(context).size.width >= 1200;
+
+  static double fullWidth(BuildContext context) =>
+     MediaQuery.of(context).size.width;
+  
+
+  static double fullHeight(BuildContext context) =>
+     MediaQuery.of(context).size.height;
+
+  static const kTabletBreakpoint =
+      768.0; //breakpoint for a tablet (a tablet's width is 768 px)
+  static const kDesktopBreakPoint =
+      1024.0; //breakpoint for desktop (a desktop screen's width is 1440 px)
+
+  static const kSideMenuWidth = 300.0; // for sidemenu
+  static const kNavigationRailWidth = 72.0; // for navigation rail
+
+  static const kMaxWidth = 1180.0; // maximum width
+  @override
+  Widget build(BuildContext context) {
+    return LayoutBuilder(
+      builder: (context, dimens) {
+        // check if the device is a phone
+        if (dimens.maxWidth >= kDesktopBreakPoint) {
+          // returns mobileBody if desktopBody is null
+          return desktopBody ?? mobileBody;
+        } else if (dimens.maxWidth >= kTabletBreakpoint &&
+            dimens.maxWidth < kDesktopBreakPoint) {
+          // returns mobileBody if tabletBody is null
+          return tabletBody ?? mobileBody;
+        } else {
+          return mobileBody;
+        }
+      },
+    );
+  }
+}
+
+class ScreenTypeData extends StatelessWidget {
+  final Widget mobile;
+  final Widget? tablet;
+  final Widget desktop;
+
+  const ScreenTypeData({
+    required this.mobile,
+    required this.desktop,
+    Key? key,
+    this.tablet,
+  }) : super(key: key);
+
+// This size work fine on my design, maybe you need some customization depends on your design
+
+  // This isMobile, isTablet, isDesktop helep us later
+  static bool isMobile(BuildContext context) =>
+      MediaQuery.of(context).size.width < 650;
+
+  static bool isTablet(BuildContext context) =>
+      MediaQuery.of(context).size.width < 1100 &&
+      MediaQuery.of(context).size.width >= 650;
+
+  static bool isDesktop(BuildContext context) =>
+      MediaQuery.of(context).size.width >= 1100;
+
+  static double fullWidth(BuildContext context) =>
+     MediaQuery.of(context).size.width;
+  
+
+  static double fullHeight(BuildContext context) =>
+     MediaQuery.of(context).size.height;
+  
+
+  @override
+  Widget build(BuildContext context) {
+    final _size = MediaQuery.of(context).size;
+    // If our width is more than 1100 then we consider it a desktop
+    if (_size.width >= 1100) {
+      return desktop;
+    }
+    // If width it less then 1100 and more then 850 we consider it as tablet
+    else if (_size.width >= 650 && tablet != null) {
+      return tablet!;
+    }
+    // Or less then that we called it mobile
+    else {
+      return mobile;
+    }
+  }
+}

+ 64 - 0
lib/themes/themes.dart

@@ -0,0 +1,64 @@
+import 'package:flutter/animation.dart';
+import 'package:flutter/material.dart';
+
+class AppTheme {
+  static Color primaryColor = const Color(0xff06DDE2);
+  static Color primaryDarkColor = const Color(0xff09c4c9);
+  static Color secondaryColor = const Color(0xffF3F3F3);
+  static Color whiteColor = const Color(0xffffffff);
+  static Color lightWhiteColor =const Color(0xfff4f4f4);
+  static Color blackColor = const Color(0xff000000);
+  static Color grayColor = const Color(0xff808080);
+  static Color orangeColor = const Color(0xffFfa500);
+  static Color pinkColor = const Color(0xffFFC0CB);
+  static Color blueColor = const Color(0xff0000ff);
+  static Color redColor = const Color(0xffFF0000);
+  static Color purpleColor = const Color(0xff800080);
+  static Color yellowColor = const Color(0xffFFFF00);
+  static Color darkYellowColor = const Color(0xffFCDA2A);
+  static Color magentaColor = const Color(0xffFF00FF);
+  static Color brownColor = const Color(0xffA52A2A);
+  static Color cyanColor = const Color(0xff00FFFF);
+  static Color lightGrayColor = const Color(0xff7d7f88);
+  static Color lightGrayBgColor = const Color(0xffE3E3E7);
+  static Color greenColor =  Colors.green;
+  static LinearGradient primaryGradientColor = LinearGradient(
+    begin: const Alignment(-1, -0.897),
+    end: const Alignment(0.862, 1),
+    colors: <Color>[primaryColor, primaryDarkColor],
+    stops: const <double>[0.313, 1],
+  );
+  static LinearGradient disableGradientColor = LinearGradient(
+    begin: const Alignment(-1, -0.897),
+    end: const Alignment(0.862, 1),
+    colors: <Color>[grayColor.withOpacity(0.5), grayColor],
+    stops: const <double>[0.313, 1],
+  );
+
+  // AppTheme({this.secondaryColor});
+}
+
+MaterialColor buildMaterialColor(Color color) {
+  List strengths = <double>[.05];
+
+  Map<int, Color> swatch = <int, Color>{};
+
+  final int r = color.red, g = color.green, b = color.blue;
+
+  for (int i = 1; i < 10; i++) {
+    strengths.add(0.1 * i);
+  }
+
+  for (var strength in strengths) {
+    final double ds = 0.5 - strength;
+
+    swatch[(strength * 1000).round()] = Color.fromRGBO(
+      r + ((ds < 0 ? r : (255 - r)) * ds).round(),
+      g + ((ds < 0 ? g : (255 - g)) * ds).round(),
+      b + ((ds < 0 ? b : (255 - b)) * ds).round(),
+      1,
+    );
+  }
+
+  return MaterialColor(color.value, swatch);
+}

+ 79 - 0
lib/ticket_widget/ticket_widget.dart

@@ -0,0 +1,79 @@
+// ignore_for_file: library_private_types_in_public_api
+
+library ticket_widget;
+
+import 'package:flutter/material.dart';
+import 'package:general_package/clip_shadow/clip_shadow.dart';
+
+class TicketWidget extends StatefulWidget {
+  const TicketWidget({
+    Key? key,
+    required this.width,
+    required this.height,
+    required this.child,
+    this.padding,
+    this.margin,
+    this.color = Colors.white,
+    this.isCornerRounded = false,
+    required this.shadow,
+  }) : super(key: key);
+
+  final double width;
+  final double height;
+  final Widget child;
+  final Color color;
+  final bool isCornerRounded;
+  final EdgeInsetsGeometry? padding;
+  final EdgeInsetsGeometry? margin;
+  final List<BoxShadow> shadow;
+
+  @override
+  _TicketWidgetState createState() => _TicketWidgetState();
+}
+
+class _TicketWidgetState extends State<TicketWidget> {
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      margin: widget.margin,
+      child: ClipShadow(
+        boxShadow: widget.shadow,
+        clipper: TicketClipper(),
+        child: AnimatedContainer(
+          duration: const Duration(seconds: 1),
+          width: widget.width,
+          height: widget.height,
+          padding: widget.padding,
+          decoration: BoxDecoration(
+            color: widget.color,
+            borderRadius: widget.isCornerRounded
+                ? BorderRadius.circular(20.0)
+                : BorderRadius.circular(0.0),
+          ),
+          child: widget.child,
+        ),
+      ),
+    );
+  }
+}
+
+class TicketClipper extends CustomClipper<Path> {
+  @override
+  Path getClip(Size size) {
+    Path path = Path();
+
+    path.lineTo(0.0, size.height);
+    path.lineTo(size.width, size.height);
+    path.lineTo(size.width, 0.0);
+
+    path.addOval(
+        Rect.fromCircle(center: Offset(0.0, size.height / 2), radius: 20.0));
+    path.addOval(Rect.fromCircle(
+        center: Offset(size.width, size.height / 2), radius: 20.0));
+
+    return path;
+  }
+
+  @override
+  bool shouldReclip(CustomClipper<Path> oldClipper) => false;
+}

+ 437 - 0
lib/validator/validator.dart

@@ -0,0 +1,437 @@
+library validator;
+
+import 'dart:core';
+
+/// The Type enum
+///
+/// The domain type is either None, Alphabetic, Numeric or AlphaNumeric
+enum SubdomainType { None, Alphabetic, Numeric, AlphaNumeric }
+
+///The EmailValidator entry point
+///
+/// To use the EmailValidator class, call EmailValidator.methodName
+class EmailValidator {
+  // An atomic index which is reused during iterations in different methods
+  static int _index = 0;
+
+  // A string character set containing all special characters
+  static const String _atomCharacters = "!#\$%&'*+-/=?^_`{|}~";
+
+  // Sets default domainType to null on initialization
+  static SubdomainType _domainType = SubdomainType.None;
+
+  // Returns true if the first letter in string c has a 16-bit UTF-16 code unit
+  // greater than or equal to 48 and less than or equal to 57
+  // otherwise return false
+  static bool _isDigit(String c) {
+    return c.codeUnitAt(0) >= 48 && c.codeUnitAt(0) <= 57;
+  }
+
+  // Returns true if the first letter in string c has a 16-bit UTF-16 code unit
+  // greater than or equal to 65 and less than or equal to 90 (capital letters)
+  // or greater than or equal to 97 and less than or equal to 122 (lowercase letters)
+  // otherwise return false
+  static bool _isLetter(String c) {
+    return (c.codeUnitAt(0) >= 65 && c.codeUnitAt(0) <= 90) ||
+        (c.codeUnitAt(0) >= 97 && c.codeUnitAt(0) <= 122);
+  }
+
+  // Returns true if calling isLetter or isDigit with the same string returns true
+  // Only returns false if both isLetter and isDigit return false
+  static bool _isLetterOrDigit(String c) {
+    return _isLetter(c) || _isDigit(c);
+  }
+
+  // Returns value of allowInternational if the first letter in the string c isnt a
+  // number or letter or special character otherwise
+  // return the result of _isLetterOrDigit or _atomCharacters.contains(c)
+  // which only returns false if both _isLetterOrDigit and _atomCharacters.contains(c)
+  // returns false
+  static bool _isAtom(String c, bool allowInternational) {
+    return c.codeUnitAt(0) < 128
+        ? _isLetterOrDigit(c) || _atomCharacters.contains(c)
+        : allowInternational;
+  }
+
+  // First checks whether the first letter in string c is a letter, number or special
+  // character
+  // If calling isLetter returns true or c is '-',
+  // domainType is set to Alphabetic and the function returns true
+  // If calling isDigit returns true
+  // domainType is set to Numeric and the function returns true
+  // Otherwise the function returns false
+  //
+  // If the first if statement for string c being a letter, number or special character
+  // fails
+  // The value of allowInternational is checked where, if true,
+  // domainType is set to Alphabetic and the function returns true
+  // Otherwise, the function returns false
+  static bool _isDomain(String c, bool allowInternational) {
+    if (c.codeUnitAt(0) < 128) {
+      if (_isLetter(c) || c == '-') {
+        _domainType = SubdomainType.Alphabetic;
+        return true;
+      }
+
+      if (_isDigit(c)) {
+        _domainType = SubdomainType.Numeric;
+        return true;
+      }
+
+      return false;
+    }
+
+    if (allowInternational) {
+      _domainType = SubdomainType.Alphabetic;
+      return true;
+    }
+
+    return false;
+  }
+
+  // Returns true if domainType is not None
+  // Otherwise returns false
+  static bool _isDomainStart(String c, bool allowInternational) {
+    if (c.codeUnitAt(0) < 128) {
+      if (_isLetter(c)) {
+        _domainType = SubdomainType.Alphabetic;
+        return true;
+      }
+
+      if (_isDigit(c)) {
+        _domainType = SubdomainType.Numeric;
+        return true;
+      }
+
+      _domainType = SubdomainType.None;
+
+      return false;
+    }
+
+    if (allowInternational) {
+      _domainType = SubdomainType.Alphabetic;
+      return true;
+    }
+
+    _domainType = SubdomainType.None;
+
+    return false;
+  }
+
+  // TODO: Documentation for this function is required
+  static bool _skipAtom(String text, bool allowInternational) {
+    final startIndex = _index;
+
+    while (_index < text.length && _isAtom(text[_index], allowInternational)) {
+      _index++;
+    }
+
+    return _index > startIndex;
+  }
+
+  // Skips checking of subdomain and returns false if domainType is None
+  // Otherwise returns true
+  static bool _skipSubDomain(String text, bool allowInternational) {
+    final startIndex = _index;
+
+    if (!_isDomainStart(text[_index], allowInternational)) {
+      return false;
+    }
+
+    _index++;
+
+    while (
+        _index < text.length && _isDomain(text[_index], allowInternational)) {
+      _index++;
+    }
+
+    return (_index - startIndex) < 64 && text[_index - 1] != '-';
+  }
+
+  // Skips checking of domain if domainType is numeric and returns false
+  // Otherwise, return true
+  static bool _skipDomain(
+      String text, bool allowTopLevelDomains, bool allowInternational) {
+    if (!_skipSubDomain(text, allowInternational)) {
+      return false;
+    }
+
+    if (_index < text.length && text[_index] == '.') {
+      do {
+        _index++;
+
+        if (_index == text.length) {
+          return false;
+        }
+
+        if (!_skipSubDomain(text, allowInternational)) {
+          return false;
+        }
+      } while (_index < text.length && text[_index] == '.');
+    } else if (!allowTopLevelDomains) {
+      return false;
+    }
+
+    // Note: by allowing AlphaNumeric,
+    // we get away with not having to support punycode.
+    if (_domainType == SubdomainType.Numeric) {
+      return false;
+    }
+
+    return true;
+  }
+
+  // Function skips over quoted text where if quoted text is in the string
+  // the function returns true
+  // otherwise the function returns false
+  static bool _skipQuoted(String text, bool allowInternational) {
+    var escaped = false;
+
+    // skip over leading '"'
+    _index++;
+
+    while (_index < text.length) {
+      if (text[_index].codeUnitAt(0) >= 128 && !allowInternational) {
+        return false;
+      }
+
+      if (text[_index] == '\\') {
+        escaped = !escaped;
+      } else if (!escaped) {
+        if (text[_index] == '"') {
+          break;
+        }
+      } else {
+        escaped = false;
+      }
+
+      _index++;
+    }
+
+    if (_index >= text.length || text[_index] != '"') {
+      return false;
+    }
+
+    _index++;
+
+    return true;
+  }
+
+  // TODO: Documentation for this function is required
+  static bool _skipIPv4Literal(String text) {
+    var groups = 0;
+
+    while (_index < text.length && groups < 4) {
+      final startIndex = _index;
+      var value = 0;
+
+      while (_index < text.length &&
+          text[_index].codeUnitAt(0) >= 48 &&
+          text[_index].codeUnitAt(0) <= 57) {
+        value = (value * 10) + (text[_index].codeUnitAt(0) - 48);
+        _index++;
+      }
+
+      if (_index == startIndex || _index - startIndex > 3 || value > 255) {
+        return false;
+      }
+
+      groups++;
+
+      if (groups < 4 && _index < text.length && text[_index] == '.') {
+        _index++;
+      }
+    }
+
+    return groups == 4;
+  }
+
+  // Returns true if the first letter of the string is
+  // a,b,c,d,e,f,A,B,C,D,E,F,1,2,3,4,5,6,7,8,9,0
+  // otherwise, the function returns false
+  static bool _isHexDigit(String str) {
+    final c = str.codeUnitAt(0);
+    return (c >= 65 && c <= 70) ||
+        (c >= 97 && c <= 102) ||
+        (c >= 48 && c <= 57);
+  }
+
+  // This needs to handle the following forms:
+  //
+  // IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp
+  // IPv6-hex  = 1*4HEXDIG
+  // IPv6-full = IPv6-hex 7(":" IPv6-hex)
+  // IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::" [IPv6-hex *5(":" IPv6-hex)]
+  //             ; The "::" represents at least 2 16-bit groups of zeros
+  //             ; No more than 6 groups in addition to the "::" may be
+  //             ; present
+  // IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal
+  // IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::"
+  //               [IPv6-hex *3(":" IPv6-hex) ":"] IPv4-address-literal
+  //             ; The "::" represents at least 2 16-bit groups of zeros
+  //             ; No more than 4 groups in addition to the "::" and
+  //             ; IPv4-address-literal may be present
+  static bool _skipIPv6Literal(String text) {
+    var compact = false;
+    var colons = 0;
+
+    while (_index < text.length) {
+      var startIndex = _index;
+
+      while (_index < text.length && _isHexDigit(text[_index])) {
+        _index++;
+      }
+
+      if (_index >= text.length) {
+        break;
+      }
+
+      if (_index > startIndex && colons > 2 && text[_index] == '.') {
+        // IPv6v4
+        _index = startIndex;
+
+        if (!_skipIPv4Literal(text)) {
+          return false;
+        }
+
+        return compact ? colons < 6 : colons == 6;
+      }
+
+      var count = _index - startIndex;
+      if (count > 4) {
+        return false;
+      }
+
+      if (text[_index] != ':') {
+        break;
+      }
+
+      startIndex = _index;
+      while (_index < text.length && text[_index] == ':') {
+        _index++;
+      }
+
+      count = _index - startIndex;
+      if (count > 2) {
+        return false;
+      }
+
+      if (count == 2) {
+        if (compact) {
+          return false;
+        }
+
+        compact = true;
+        colons += 2;
+      } else {
+        colons++;
+      }
+    }
+
+    if (colons < 2) {
+      return false;
+    }
+
+    return compact ? colons < 7 : colons == 7;
+  }
+
+  /// Validate the specified email address.
+  ///
+  /// If [allowTopLevelDomains] is `true`, then the validator will
+  /// allow addresses with top-level domains like `email@example`.
+  ///
+  /// If [allowInternational] is `true`, then the validator
+  /// will use the newer International Email standards for validating
+  /// the email address.
+  static bool validate(String email,
+      [bool allowTopLevelDomains = false, bool allowInternational = true]) {
+    _index = 0;
+
+    if (email.isEmpty || email.length >= 255) {
+      return false;
+    }
+
+    // Local-part = Dot-string / Quoted-string
+    //       ; MAY be case-sensitive
+    //
+    // Dot-string = Atom *("." Atom)
+    //
+    // Quoted-string = DQUOTE *qcontent DQUOTE
+    if (email[_index] == '"') {
+      if (!_skipQuoted(email, allowInternational) || _index >= email.length) {
+        return false;
+      }
+    } else {
+      if (!_skipAtom(email, allowInternational) || _index >= email.length) {
+        return false;
+      }
+
+      while (email[_index] == '.') {
+        _index++;
+
+        if (_index >= email.length) {
+          return false;
+        }
+
+        if (!_skipAtom(email, allowInternational)) {
+          return false;
+        }
+
+        if (_index >= email.length) {
+          return false;
+        }
+      }
+    }
+
+    if (_index + 1 >= email.length || _index > 64 || email[_index++] != '@') {
+      return false;
+    }
+
+    if (email[_index] != '[') {
+      // domain
+      if (!_skipDomain(email, allowTopLevelDomains, allowInternational)) {
+        return false;
+      }
+
+      return _index == email.length;
+    }
+
+    // address literal
+    _index++;
+
+    // we need at least 8 more characters
+    if (_index + 8 >= email.length) {
+      return false;
+    }
+
+    final ipv6 = email.substring(_index - 1).toLowerCase();
+
+    if (ipv6.contains('ipv6:')) {
+      _index += 'IPv6:'.length;
+      if (!_skipIPv6Literal(email)) {
+        return false;
+      }
+    } else {
+      if (!_skipIPv4Literal(email)) {
+        return false;
+      }
+    }
+
+    if (_index >= email.length || email[_index++] != ']') {
+      return false;
+    }
+
+    return _index == email.length;
+  }
+}
+
+class PhoneNumberValidator {
+  String? validateMobile(String value) {
+// Indian Mobile number are of 10 digit only
+    if (value.length != 10) {
+      return 'Mobile Number must be of 10 digit';
+    } else {
+      return null;
+    }
+  }
+}

+ 88 - 0
pubspec.yaml

@@ -0,0 +1,88 @@
+name: general_package
+description: A new Flutter package project.
+version: 0.0.1
+homepage:
+
+environment:
+  # sdk: '>3.0.1 <4.0.0'
+  sdk: '>=2.18.2 <3.0.0'
+  flutter: ">=1.17.0"
+
+dependencies:
+  flutter:
+    sdk: flutter
+  cupertino_icons: ^1.0.2
+  flutter_bloc: ^8.1.1
+  flutter_spinkit: ^5.1.0
+  flutter_color_models: ^1.3.2
+  pinput: ^2.2.16
+  # pinput: ^2.2.31
+  flutter_form_builder: ^7.7.0
+  form_field_validator: ^1.1.0
+  chips_choice: ^3.0.0
+  http: ^0.13.5
+  # http: ^1.0.0
+  # google_fonts: ^4.0.5
+  google_fonts: ^6.1.0
+  # fluttertoast: ^8.1.1
+  fluttertoast: ^8.2.1
+  lottie: ^1.4.3
+  provider: ^6.0.4
+  connectivity_plus: ^2.3.9
+  animated_splash_screen: ^1.3.0
+  encrypted_shared_preferences: ^3.0.1
+  permission_handler: ^10.2.0
+  # image_picker: ^0.8.6 
+  image_picker: ^1.0.4
+  get: ^4.6.5
+  # get: ^4.6.6
+  get_storage: ^2.1.1
+  cached_memory_image: ^1.3.1
+  device_info_plus: ^9.0.1
+  dart_ipify: ^1.1.1
+  firebase_core: ^2.14.0
+  firebase_messaging: ^14.6.3
+  simple_barcode_scanner: ^0.0.6
+  geolocator: ^10.1.0
+  
+dev_dependencies:
+  flutter_test:
+    sdk: flutter
+  flutter_lints: ^2.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+
+  # To add assets to your package, add an assets section, like this:
+  # assets:
+  #   - images/a_dot_burr.jpeg
+  #   - images/a_dot_ham.jpeg
+  #
+  # For details regarding assets in packages, see
+  # https://flutter.dev/assets-and-images/#from-packages
+  #
+  # An image asset can refer to one or more resolution-specific "variants", see
+  # https://flutter.dev/assets-and-images/#resolution-aware
+
+  # To add custom fonts to your package, add a fonts section here,
+  # in this "flutter" section. Each entry in this list should have a
+  # "family" key with the font family name, and a "fonts" key with a
+  # list giving the asset and other descriptors for the font. For
+  # example:
+  # fonts:
+  #   - family: Schyler
+  #     fonts:
+  #       - asset: fonts/Schyler-Regular.ttf
+  #       - asset: fonts/Schyler-Italic.ttf
+  #         style: italic
+  #   - family: Trajan Pro
+  #     fonts:
+  #       - asset: fonts/TrajanPro.ttf
+  #       - asset: fonts/TrajanPro_Bold.ttf
+  #         weight: 700
+  #
+  # For details regarding fonts in packages, see
+  # https://flutter.dev/custom-fonts/#from-packages

+ 1 - 0
test/general_package_test.dart

@@ -0,0 +1 @@
+void main() {}