From d8fea02fcf1c5f71bbdbae93aec81f876bd522e8 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Sun, 25 Jan 2026 20:17:16 -0500 Subject: [PATCH] Delete apps/mobile/prototypes directory --- .../client_mobile_application/.gitignore | 45 - .../client_mobile_application/.metadata | 45 - .../client_mobile_application/README.md | 16 - .../analysis_options.yaml | 28 - .../android/.gitignore | 14 - .../android/app/build.gradle.kts | 45 - .../android/app/google-services.json | 68 - .../android/app/src/debug/AndroidManifest.xml | 7 - .../android/app/src/main/AndroidManifest.xml | 47 - .../example/client_app_mvp/MainActivity.kt | 5 - .../res/drawable-v21/launch_background.xml | 12 - .../main/res/drawable/launch_background.xml | 12 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 544 -> 0 bytes .../main/res/mipmap-hdpi/launcher_icon.png | Bin 2081 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 442 -> 0 bytes .../main/res/mipmap-mdpi/launcher_icon.png | Bin 1386 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 721 -> 0 bytes .../main/res/mipmap-xhdpi/launcher_icon.png | Bin 2751 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 1031 -> 0 bytes .../main/res/mipmap-xxhdpi/launcher_icon.png | Bin 4023 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 1443 -> 0 bytes .../main/res/mipmap-xxxhdpi/launcher_icon.png | Bin 5214 -> 0 bytes .../app/src/main/res/values-night/styles.xml | 18 - .../app/src/main/res/values/styles.xml | 18 - .../app/src/profile/AndroidManifest.xml | 7 - .../android/build.gradle.kts | 24 - .../android/gradle.properties | 2 - .../gradle/wrapper/gradle-wrapper.properties | 5 - .../android/settings.gradle.kts | 27 - .../client_mobile_application/assets/logo.png | Bin 8558 -> 0 bytes .../client_mobile_application/ios/.gitignore | 34 - .../ios/Flutter/AppFrameworkInfo.plist | 26 - .../ios/Flutter/Debug.xcconfig | 2 - .../ios/Flutter/Release.xcconfig | 2 - .../client_mobile_application/ios/Podfile | 43 - .../ios/Runner.xcodeproj/project.pbxproj | 728 ---- .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - .../xcshareddata/xcschemes/Runner.xcscheme | 101 - .../contents.xcworkspacedata | 10 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - .../ios/Runner/AppDelegate.swift | 13 - .../AppIcon.appiconset/Contents.json | 1 - .../Icon-App-1024x1024@1x.png | Bin 30733 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 506 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 1057 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 1604 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 765 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 1572 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 2377 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 1057 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 2135 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 3227 -> 0 bytes .../AppIcon.appiconset/Icon-App-50x50@1x.png | Bin 1303 -> 0 bytes .../AppIcon.appiconset/Icon-App-50x50@2x.png | Bin 2736 -> 0 bytes .../AppIcon.appiconset/Icon-App-57x57@1x.png | Bin 1519 -> 0 bytes .../AppIcon.appiconset/Icon-App-57x57@2x.png | Bin 3063 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 3227 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 4753 -> 0 bytes .../AppIcon.appiconset/Icon-App-72x72@1x.png | Bin 1942 -> 0 bytes .../AppIcon.appiconset/Icon-App-72x72@2x.png | Bin 3890 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 2006 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 4049 -> 0 bytes .../Icon-App-83.5x83.5@2x.png | Bin 4346 -> 0 bytes .../LaunchImage.imageset/Contents.json | 23 - .../LaunchImage.imageset/LaunchImage.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/README.md | 5 - .../Runner/Base.lproj/LaunchScreen.storyboard | 37 - .../ios/Runner/Base.lproj/Main.storyboard | 26 - .../ios/Runner/Info.plist | 49 - .../ios/Runner/Runner-Bridging-Header.h | 1 - .../ios/RunnerTests/RunnerTests.swift | 12 - .../dataconnect_generated/.guides/config.json | 9 - .../dataconnect_generated/.guides/setup.md | 15 - .../dataconnect_generated/.guides/usage.md | 31 - .../lib/dataconnect_generated/README.md | 446 --- .../lib/dataconnect_generated/add_review.dart | 139 - .../dataconnect_generated/create_movie.dart | 134 - .../dataconnect_generated/delete_review.dart | 129 - .../lib/dataconnect_generated/generated.dart | 93 - .../get_movie_by_id.dart | 297 -- .../dataconnect_generated/list_movies.dart | 105 - .../list_user_reviews.dart | 192 - .../lib/dataconnect_generated/list_users.dart | 93 - .../dataconnect_generated/search_movie.dart | 167 - .../dataconnect_generated/upsert_user.dart | 122 - .../client_mobile_application/lib/main.dart | 28 - .../client_mobile_application/lib/router.dart | 165 - .../auth/client_get_started_screen.dart | 392 -- .../screens/auth/client_sign_in_screen.dart | 384 -- .../screens/auth/client_sign_up_screen.dart | 463 --- .../screens/client/client_billing_screen.dart | 990 ------ .../client/client_coverage_screen.dart | 967 ----- .../screens/client/client_home_screen.dart | 1958 ---------- .../screens/client/client_hubs_screen.dart | 753 ---- .../screens/client/client_reports_screen.dart | 544 --- .../client/client_settings_screen.dart | 210 -- .../screens/client/client_shifts_screen.dart | 3161 ----------------- .../client/client_timesheets_screen.dart | 766 ---- .../screens/client/client_workers_screen.dart | 747 ---- .../screens/client/coverage_dashboard.dart | 330 -- .../one_time_order_flow_page.dart | 789 ---- .../permanent_order_flow_page.dart | 1222 ------- .../rapid_order_flow_page.dart | 530 --- .../recurring_order_flow_page.dart | 1352 ------- .../screens/client/create_order_screen.dart | 242 -- .../reports/coverage_report_screen.dart | 449 --- .../reports/daily_ops_report_screen.dart | 517 --- .../reports/forecast_report_screen.dart | 587 --- .../client/reports/no_show_report_screen.dart | 441 --- .../reports/performance_report_screen.dart | 523 --- .../client/reports/spend_report_screen.dart | 563 --- .../client/verify_worker_attire_screen.dart | 228 -- .../client_mobile_application/lib/theme.dart | 44 - .../lib/widgets/scaffold_with_nav_bar.dart | 137 - .../lib/widgets/web_mobile_frame.dart | 271 -- .../linux/.gitignore | 1 - .../linux/CMakeLists.txt | 128 - .../linux/flutter/CMakeLists.txt | 88 - .../flutter/generated_plugin_registrant.cc | 15 - .../flutter/generated_plugin_registrant.h | 15 - .../linux/flutter/generated_plugins.cmake | 24 - .../linux/runner/CMakeLists.txt | 26 - .../linux/runner/main.cc | 6 - .../linux/runner/my_application.cc | 148 - .../linux/runner/my_application.h | 21 - .../macos/.gitignore | 7 - .../macos/Flutter/Flutter-Debug.xcconfig | 2 - .../macos/Flutter/Flutter-Release.xcconfig | 2 - .../Flutter/GeneratedPluginRegistrant.swift | 16 - .../client_mobile_application/macos/Podfile | 42 - .../macos/Runner.xcodeproj/project.pbxproj | 705 ---- .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/xcschemes/Runner.xcscheme | 99 - .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../macos/Runner/AppDelegate.swift | 13 - .../AppIcon.appiconset/Contents.json | 68 - .../AppIcon.appiconset/app_icon_1024.png | Bin 102994 -> 0 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 5680 -> 0 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 520 -> 0 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 14142 -> 0 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 1066 -> 0 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 36406 -> 0 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 2218 -> 0 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 343 -- .../macos/Runner/Configs/AppInfo.xcconfig | 14 - .../macos/Runner/Configs/Debug.xcconfig | 2 - .../macos/Runner/Configs/Release.xcconfig | 2 - .../macos/Runner/Configs/Warnings.xcconfig | 13 - .../macos/Runner/DebugProfile.entitlements | 12 - .../macos/Runner/Info.plist | 32 - .../macos/Runner/MainFlutterWindow.swift | 15 - .../macos/Runner/Release.entitlements | 8 - .../macos/RunnerTests/RunnerTests.swift | 12 - .../client_mobile_application/pubspec.lock | 866 ----- .../client_mobile_application/pubspec.yaml | 103 - .../test/widget_test.dart | 30 - .../client_mobile_application/web/favicon.png | Bin 917 -> 0 bytes .../web/icons/Icon-192.png | Bin 5292 -> 0 bytes .../web/icons/Icon-512.png | Bin 8252 -> 0 bytes .../web/icons/Icon-maskable-192.png | Bin 5594 -> 0 bytes .../web/icons/Icon-maskable-512.png | Bin 20998 -> 0 bytes .../client_mobile_application/web/index.html | 38 - .../web/manifest.json | 35 - .../windows/.gitignore | 17 - .../windows/CMakeLists.txt | 108 - .../windows/flutter/CMakeLists.txt | 109 - .../flutter/generated_plugin_registrant.cc | 17 - .../flutter/generated_plugin_registrant.h | 15 - .../windows/flutter/generated_plugins.cmake | 25 - .../windows/runner/CMakeLists.txt | 40 - .../windows/runner/Runner.rc | 121 - .../windows/runner/flutter_window.cpp | 71 - .../windows/runner/flutter_window.h | 33 - .../windows/runner/main.cpp | 43 - .../windows/runner/resource.h | 16 - .../windows/runner/resources/app_icon.ico | Bin 33772 -> 0 bytes .../windows/runner/runner.exe.manifest | 14 - .../windows/runner/utils.cpp | 65 - .../windows/runner/utils.h | 19 - .../windows/runner/win32_window.cpp | 288 -- .../windows/runner/win32_window.h | 102 - .../staff_mobile_application/.gitignore | 45 - .../staff_mobile_application/.metadata | 45 - .../staff_mobile_application/README.md | 16 - .../analysis_options.yaml | 28 - .../android/.gitignore | 14 - .../android/app/29a493751_PNG3Krow.png | Bin 47063 -> 0 bytes .../android/app/build.gradle.kts | 45 - .../android/app/google-services.json | 39 - .../android/app/src/debug/AndroidManifest.xml | 7 - .../android/app/src/main/AndroidManifest.xml | 46 - .../com/example/staff_app_mvp/MainActivity.kt | 5 - .../res/drawable-v21/launch_background.xml | 12 - .../main/res/drawable/launch_background.xml | 12 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 2123 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 1422 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 2795 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 4117 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 5314 -> 0 bytes .../app/src/main/res/values-night/styles.xml | 18 - .../app/src/main/res/values/styles.xml | 18 - .../app/src/profile/AndroidManifest.xml | 7 - .../android/build.gradle.kts | 24 - .../android/gradle.properties | 2 - .../gradle/wrapper/gradle-wrapper.properties | 5 - .../android/settings.gradle.kts | 27 - .../staff_mobile_application/assets/logo.png | Bin 8790 -> 0 bytes .../comparation_v2_v3.md | 304 -- .../staff_mobile_application/ios/.gitignore | 34 - .../ios/Flutter/AppFrameworkInfo.plist | 26 - .../ios/Flutter/Debug.xcconfig | 2 - .../ios/Flutter/Release.xcconfig | 2 - .../staff_mobile_application/ios/Podfile | 43 - .../ios/Runner.xcodeproj/project.pbxproj | 728 ---- .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - .../xcshareddata/xcschemes/Runner.xcscheme | 101 - .../contents.xcworkspacedata | 10 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - .../ios/Runner/AppDelegate.swift | 13 - .../AppIcon.appiconset/Contents.json | 1 - .../Icon-App-1024x1024@1x.png | Bin 31482 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 521 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 1084 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 1657 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 789 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 1634 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 2462 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 1084 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 2222 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 3367 -> 0 bytes .../AppIcon.appiconset/Icon-App-50x50@1x.png | Bin 1349 -> 0 bytes .../AppIcon.appiconset/Icon-App-50x50@2x.png | Bin 2835 -> 0 bytes .../AppIcon.appiconset/Icon-App-57x57@1x.png | Bin 1567 -> 0 bytes .../AppIcon.appiconset/Icon-App-57x57@2x.png | Bin 3176 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 3367 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 4979 -> 0 bytes .../AppIcon.appiconset/Icon-App-72x72@1x.png | Bin 2024 -> 0 bytes .../AppIcon.appiconset/Icon-App-72x72@2x.png | Bin 4049 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 2120 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 4241 -> 0 bytes .../Icon-App-83.5x83.5@2x.png | Bin 4533 -> 0 bytes .../LaunchImage.imageset/Contents.json | 23 - .../LaunchImage.imageset/LaunchImage.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/README.md | 5 - .../Runner/Base.lproj/LaunchScreen.storyboard | 37 - .../ios/Runner/Base.lproj/Main.storyboard | 26 - .../ios/Runner/Info.plist | 49 - .../ios/Runner/Runner-Bridging-Header.h | 1 - .../ios/RunnerTests/RunnerTests.swift | 12 - .../dataconnect_generated/.guides/config.json | 9 - .../dataconnect_generated/.guides/setup.md | 15 - .../dataconnect_generated/.guides/usage.md | 31 - .../lib/dataconnect_generated/README.md | 446 --- .../lib/dataconnect_generated/add_review.dart | 139 - .../dataconnect_generated/create_movie.dart | 134 - .../dataconnect_generated/delete_review.dart | 129 - .../lib/dataconnect_generated/generated.dart | 93 - .../get_movie_by_id.dart | 297 -- .../dataconnect_generated/list_movies.dart | 105 - .../list_user_reviews.dart | 192 - .../lib/dataconnect_generated/list_users.dart | 93 - .../dataconnect_generated/search_movie.dart | 167 - .../dataconnect_generated/upsert_user.dart | 122 - .../staff_mobile_application/lib/main.dart | 30 - .../lib/models/shift.dart | 59 - .../staff_mobile_application/lib/router.dart | 198 -- .../lib/screens/auth/get_started_screen.dart | 182 - .../auth/phone_verification_screen.dart | 486 --- .../screens/auth/profile_setup_screen.dart | 796 ----- .../screens/worker/availability_screen.dart | 784 ---- .../lib/screens/worker/benefits_screen.dart | 534 --- .../lib/screens/worker/clock_in_screen.dart | 796 ----- .../lib/screens/worker/early_pay_screen.dart | 899 ----- .../lib/screens/worker/earnings_screen.dart | 667 ---- .../lib/screens/worker/jobs_screen.dart | 219 -- .../lib/screens/worker/payments_screen.dart | 272 -- .../screens/worker/shift_details_screen.dart | 809 ----- .../lib/screens/worker/shifts_screen.dart | 1268 ------- .../screens/worker/worker_home_screen.dart | 825 ----- .../compliance/certificates_screen.dart | 908 ----- .../compliance/documents_screen.dart | 296 -- .../compliance/tax_forms_screen.dart | 327 -- .../compliance/taxforms/form_i9_screen.dart | 905 ----- .../compliance/taxforms/form_w4_screen.dart | 1056 ------ .../finances/bank_account_screen.dart | 435 --- .../finances/time_card_screen.dart | 415 --- .../level_up/krow_university_screen.dart | 820 ----- .../level_up/leaderboard_screen.dart | 450 --- .../level_up/trainings_screen.dart | 329 -- .../onboarding/attire_screen.dart | 567 --- .../onboarding/emergency_contact_screen.dart | 318 -- .../onboarding/experience_screen.dart | 371 -- .../onboarding/personal_info_screen.dart | 334 -- .../worker_profile/support/faqs_screen.dart | 319 -- .../support/messages_screen.dart | 558 --- .../support/privacy_screen.dart | 267 -- .../screens/worker/worker_profile_screen.dart | 667 ---- .../lib/services/mock_service.dart | 78 - .../staff_mobile_application/lib/theme.dart | 44 - .../lib/widgets/clock_in/attendance_card.dart | 129 - .../lib/widgets/clock_in/commute_tracker.dart | 542 --- .../lib/widgets/clock_in/date_selector.dart | 114 - .../widgets/clock_in/lunch_break_modal.dart | 518 --- .../widgets/clock_in/swipe_to_check_in.dart | 224 -- .../payments/payment_history_item.dart | 209 -- .../widgets/payments/payment_stats_card.dart | 62 - .../widgets/payments/pending_pay_card.dart | 98 - .../lib/widgets/scaffold_with_nav_bar.dart | 138 - .../lib/widgets/shift_card.dart | 495 --- .../lib/widgets/shifts/my_shift_card.dart | 775 ---- .../widgets/shifts/shift_assignment_card.dart | 282 -- .../lib/widgets/web_mobile_frame.dart | 271 -- .../lib/widgets/worker/auto_match_toggle.dart | 166 - .../lib/widgets/worker/benefits_widget.dart | 199 -- .../worker/improve_yourself_widget.dart | 119 - .../lib/widgets/worker/more_ways_widget.dart | 102 - .../staff_mobile_application/linux/.gitignore | 1 - .../linux/CMakeLists.txt | 128 - .../linux/flutter/CMakeLists.txt | 88 - .../flutter/generated_plugin_registrant.cc | 11 - .../flutter/generated_plugin_registrant.h | 15 - .../linux/flutter/generated_plugins.cmake | 23 - .../linux/runner/CMakeLists.txt | 26 - .../linux/runner/main.cc | 6 - .../linux/runner/my_application.cc | 148 - .../linux/runner/my_application.h | 21 - .../staff_mobile_application/macos/.gitignore | 7 - .../macos/Flutter/Flutter-Debug.xcconfig | 2 - .../macos/Flutter/Flutter-Release.xcconfig | 2 - .../Flutter/GeneratedPluginRegistrant.swift | 14 - .../staff_mobile_application/macos/Podfile | 42 - .../macos/Runner.xcodeproj/project.pbxproj | 705 ---- .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/xcschemes/Runner.xcscheme | 99 - .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../macos/Runner/AppDelegate.swift | 13 - .../AppIcon.appiconset/Contents.json | 68 - .../AppIcon.appiconset/app_icon_1024.png | Bin 102994 -> 0 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 5680 -> 0 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 520 -> 0 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 14142 -> 0 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 1066 -> 0 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 36406 -> 0 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 2218 -> 0 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 343 -- .../macos/Runner/Configs/AppInfo.xcconfig | 14 - .../macos/Runner/Configs/Debug.xcconfig | 2 - .../macos/Runner/Configs/Release.xcconfig | 2 - .../macos/Runner/Configs/Warnings.xcconfig | 13 - .../macos/Runner/DebugProfile.entitlements | 12 - .../macos/Runner/Info.plist | 32 - .../macos/Runner/MainFlutterWindow.swift | 15 - .../macos/Runner/Release.entitlements | 8 - .../macos/RunnerTests/RunnerTests.swift | 12 - .../mock_staff_app_v2.md | 859 ----- .../mock_staff_data_v3_update.md | 594 ---- .../staff_mobile_application/pubspec.lock | 786 ---- .../staff_mobile_application/pubspec.yaml | 105 - .../test/widget_test.dart | 30 - .../staff_mobile_application/web/favicon.png | Bin 917 -> 0 bytes .../web/icons/Icon-192.png | Bin 5292 -> 0 bytes .../web/icons/Icon-512.png | Bin 8252 -> 0 bytes .../web/icons/Icon-maskable-192.png | Bin 5594 -> 0 bytes .../web/icons/Icon-maskable-512.png | Bin 20998 -> 0 bytes .../staff_mobile_application/web/index.html | 38 - .../web/manifest.json | 35 - .../windows/.gitignore | 17 - .../windows/CMakeLists.txt | 108 - .../windows/flutter/CMakeLists.txt | 109 - .../flutter/generated_plugin_registrant.cc | 14 - .../flutter/generated_plugin_registrant.h | 15 - .../windows/flutter/generated_plugins.cmake | 24 - .../windows/runner/CMakeLists.txt | 40 - .../windows/runner/Runner.rc | 121 - .../windows/runner/flutter_window.cpp | 71 - .../windows/runner/flutter_window.h | 33 - .../windows/runner/main.cpp | 43 - .../windows/runner/resource.h | 16 - .../windows/runner/resources/app_icon.ico | Bin 33772 -> 0 bytes .../windows/runner/runner.exe.manifest | 14 - .../windows/runner/utils.cpp | 65 - .../windows/runner/utils.h | 19 - .../windows/runner/win32_window.cpp | 288 -- .../windows/runner/win32_window.h | 102 - 396 files changed, 59414 deletions(-) delete mode 100644 apps/mobile/prototypes/client_mobile_application/.gitignore delete mode 100644 apps/mobile/prototypes/client_mobile_application/.metadata delete mode 100644 apps/mobile/prototypes/client_mobile_application/README.md delete mode 100644 apps/mobile/prototypes/client_mobile_application/analysis_options.yaml delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/.gitignore delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/build.gradle.kts delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/google-services.json delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/debug/AndroidManifest.xml delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/AndroidManifest.xml delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/kotlin/com/example/client_app_mvp/MainActivity.kt delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/drawable-v21/launch_background.xml delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/drawable/launch_background.xml delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-hdpi/launcher_icon.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-mdpi/launcher_icon.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/values-night/styles.xml delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/values/styles.xml delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/app/src/profile/AndroidManifest.xml delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/build.gradle.kts delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/gradle.properties delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/gradle/wrapper/gradle-wrapper.properties delete mode 100644 apps/mobile/prototypes/client_mobile_application/android/settings.gradle.kts delete mode 100644 apps/mobile/prototypes/client_mobile_application/assets/logo.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/.gitignore delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Flutter/AppFrameworkInfo.plist delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Flutter/Debug.xcconfig delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Flutter/Release.xcconfig delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Podfile delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.pbxproj delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner.xcworkspace/contents.xcworkspacedata delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/AppDelegate.swift delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Base.lproj/LaunchScreen.storyboard delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Base.lproj/Main.storyboard delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Info.plist delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/Runner/Runner-Bridging-Header.h delete mode 100644 apps/mobile/prototypes/client_mobile_application/ios/RunnerTests/RunnerTests.swift delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/.guides/config.json delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/.guides/setup.md delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/.guides/usage.md delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/README.md delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/add_review.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/create_movie.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/delete_review.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/generated.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/get_movie_by_id.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/list_movies.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/list_user_reviews.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/list_users.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/search_movie.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/upsert_user.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/main.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/router.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/auth/client_get_started_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/auth/client_sign_in_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/auth/client_sign_up_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_billing_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_coverage_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_home_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_hubs_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_reports_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_settings_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_shifts_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_timesheets_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_workers_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/coverage_dashboard.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/one_time_order_flow_page.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/permanent_order_flow_page.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/rapid_order_flow_page.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/recurring_order_flow_page.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/coverage_report_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/daily_ops_report_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/forecast_report_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/no_show_report_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/performance_report_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/spend_report_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/screens/client/verify_worker_attire_screen.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/theme.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/widgets/scaffold_with_nav_bar.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/lib/widgets/web_mobile_frame.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/linux/.gitignore delete mode 100644 apps/mobile/prototypes/client_mobile_application/linux/CMakeLists.txt delete mode 100644 apps/mobile/prototypes/client_mobile_application/linux/flutter/CMakeLists.txt delete mode 100644 apps/mobile/prototypes/client_mobile_application/linux/flutter/generated_plugin_registrant.cc delete mode 100644 apps/mobile/prototypes/client_mobile_application/linux/flutter/generated_plugin_registrant.h delete mode 100644 apps/mobile/prototypes/client_mobile_application/linux/flutter/generated_plugins.cmake delete mode 100644 apps/mobile/prototypes/client_mobile_application/linux/runner/CMakeLists.txt delete mode 100644 apps/mobile/prototypes/client_mobile_application/linux/runner/main.cc delete mode 100644 apps/mobile/prototypes/client_mobile_application/linux/runner/my_application.cc delete mode 100644 apps/mobile/prototypes/client_mobile_application/linux/runner/my_application.h delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/.gitignore delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Flutter/Flutter-Debug.xcconfig delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Flutter/Flutter-Release.xcconfig delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Flutter/GeneratedPluginRegistrant.swift delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Podfile delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner.xcodeproj/project.pbxproj delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner.xcworkspace/contents.xcworkspacedata delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/AppDelegate.swift delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Base.lproj/MainMenu.xib delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/AppInfo.xcconfig delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/Debug.xcconfig delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/Release.xcconfig delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/Warnings.xcconfig delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/DebugProfile.entitlements delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Info.plist delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/MainFlutterWindow.swift delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/Runner/Release.entitlements delete mode 100644 apps/mobile/prototypes/client_mobile_application/macos/RunnerTests/RunnerTests.swift delete mode 100644 apps/mobile/prototypes/client_mobile_application/pubspec.lock delete mode 100644 apps/mobile/prototypes/client_mobile_application/pubspec.yaml delete mode 100644 apps/mobile/prototypes/client_mobile_application/test/widget_test.dart delete mode 100644 apps/mobile/prototypes/client_mobile_application/web/favicon.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/web/icons/Icon-192.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/web/icons/Icon-512.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/web/icons/Icon-maskable-192.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/web/icons/Icon-maskable-512.png delete mode 100644 apps/mobile/prototypes/client_mobile_application/web/index.html delete mode 100644 apps/mobile/prototypes/client_mobile_application/web/manifest.json delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/.gitignore delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/CMakeLists.txt delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/flutter/CMakeLists.txt delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/flutter/generated_plugin_registrant.cc delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/flutter/generated_plugin_registrant.h delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/flutter/generated_plugins.cmake delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/runner/CMakeLists.txt delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/runner/Runner.rc delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/runner/flutter_window.cpp delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/runner/flutter_window.h delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/runner/main.cpp delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/runner/resource.h delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/runner/resources/app_icon.ico delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/runner/runner.exe.manifest delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/runner/utils.cpp delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/runner/utils.h delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/runner/win32_window.cpp delete mode 100644 apps/mobile/prototypes/client_mobile_application/windows/runner/win32_window.h delete mode 100644 apps/mobile/prototypes/staff_mobile_application/.gitignore delete mode 100644 apps/mobile/prototypes/staff_mobile_application/.metadata delete mode 100644 apps/mobile/prototypes/staff_mobile_application/README.md delete mode 100644 apps/mobile/prototypes/staff_mobile_application/analysis_options.yaml delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/.gitignore delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/29a493751_PNG3Krow.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/build.gradle.kts delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/google-services.json delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/src/debug/AndroidManifest.xml delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/src/main/AndroidManifest.xml delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/src/main/kotlin/com/example/staff_app_mvp/MainActivity.kt delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/drawable-v21/launch_background.xml delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/drawable/launch_background.xml delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/values-night/styles.xml delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/values/styles.xml delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/app/src/profile/AndroidManifest.xml delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/build.gradle.kts delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/gradle.properties delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/gradle/wrapper/gradle-wrapper.properties delete mode 100644 apps/mobile/prototypes/staff_mobile_application/android/settings.gradle.kts delete mode 100644 apps/mobile/prototypes/staff_mobile_application/assets/logo.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/comparation_v2_v3.md delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/.gitignore delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Flutter/AppFrameworkInfo.plist delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Flutter/Debug.xcconfig delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Flutter/Release.xcconfig delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Podfile delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.pbxproj delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcworkspace/contents.xcworkspacedata delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/AppDelegate.swift delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Base.lproj/LaunchScreen.storyboard delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Base.lproj/Main.storyboard delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Info.plist delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/Runner/Runner-Bridging-Header.h delete mode 100644 apps/mobile/prototypes/staff_mobile_application/ios/RunnerTests/RunnerTests.swift delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/.guides/config.json delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/.guides/setup.md delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/.guides/usage.md delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/README.md delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/add_review.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/create_movie.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/delete_review.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/generated.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/get_movie_by_id.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/list_movies.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/list_user_reviews.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/list_users.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/search_movie.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/upsert_user.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/main.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/models/shift.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/router.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/auth/get_started_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/auth/phone_verification_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/auth/profile_setup_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/availability_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/benefits_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/clock_in_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/early_pay_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/earnings_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/jobs_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/payments_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/shift_details_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/shifts_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_home_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/certificates_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/documents_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/tax_forms_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/taxforms/form_i9_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/taxforms/form_w4_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/finances/bank_account_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/finances/time_card_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/level_up/krow_university_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/level_up/leaderboard_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/level_up/trainings_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/attire_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/emergency_contact_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/experience_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/personal_info_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/support/faqs_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/support/messages_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/support/privacy_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile_screen.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/services/mock_service.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/theme.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/attendance_card.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/commute_tracker.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/date_selector.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/lunch_break_modal.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/swipe_to_check_in.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/payments/payment_history_item.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/payments/payment_stats_card.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/payments/pending_pay_card.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/scaffold_with_nav_bar.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/shift_card.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/shifts/my_shift_card.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/shifts/shift_assignment_card.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/web_mobile_frame.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/auto_match_toggle.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/benefits_widget.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/improve_yourself_widget.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/more_ways_widget.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/linux/.gitignore delete mode 100644 apps/mobile/prototypes/staff_mobile_application/linux/CMakeLists.txt delete mode 100644 apps/mobile/prototypes/staff_mobile_application/linux/flutter/CMakeLists.txt delete mode 100644 apps/mobile/prototypes/staff_mobile_application/linux/flutter/generated_plugin_registrant.cc delete mode 100644 apps/mobile/prototypes/staff_mobile_application/linux/flutter/generated_plugin_registrant.h delete mode 100644 apps/mobile/prototypes/staff_mobile_application/linux/flutter/generated_plugins.cmake delete mode 100644 apps/mobile/prototypes/staff_mobile_application/linux/runner/CMakeLists.txt delete mode 100644 apps/mobile/prototypes/staff_mobile_application/linux/runner/main.cc delete mode 100644 apps/mobile/prototypes/staff_mobile_application/linux/runner/my_application.cc delete mode 100644 apps/mobile/prototypes/staff_mobile_application/linux/runner/my_application.h delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/.gitignore delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Flutter/Flutter-Debug.xcconfig delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Flutter/Flutter-Release.xcconfig delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Flutter/GeneratedPluginRegistrant.swift delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Podfile delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcodeproj/project.pbxproj delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcworkspace/contents.xcworkspacedata delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/AppDelegate.swift delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Base.lproj/MainMenu.xib delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/AppInfo.xcconfig delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/Debug.xcconfig delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/Release.xcconfig delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/Warnings.xcconfig delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/DebugProfile.entitlements delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Info.plist delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/MainFlutterWindow.swift delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/Runner/Release.entitlements delete mode 100644 apps/mobile/prototypes/staff_mobile_application/macos/RunnerTests/RunnerTests.swift delete mode 100644 apps/mobile/prototypes/staff_mobile_application/mock_staff_app_v2.md delete mode 100644 apps/mobile/prototypes/staff_mobile_application/mock_staff_data_v3_update.md delete mode 100644 apps/mobile/prototypes/staff_mobile_application/pubspec.lock delete mode 100644 apps/mobile/prototypes/staff_mobile_application/pubspec.yaml delete mode 100644 apps/mobile/prototypes/staff_mobile_application/test/widget_test.dart delete mode 100644 apps/mobile/prototypes/staff_mobile_application/web/favicon.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/web/icons/Icon-192.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/web/icons/Icon-512.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/web/icons/Icon-maskable-192.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/web/icons/Icon-maskable-512.png delete mode 100644 apps/mobile/prototypes/staff_mobile_application/web/index.html delete mode 100644 apps/mobile/prototypes/staff_mobile_application/web/manifest.json delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/.gitignore delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/CMakeLists.txt delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/flutter/CMakeLists.txt delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/flutter/generated_plugin_registrant.cc delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/flutter/generated_plugin_registrant.h delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/flutter/generated_plugins.cmake delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/runner/CMakeLists.txt delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/runner/Runner.rc delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/runner/flutter_window.cpp delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/runner/flutter_window.h delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/runner/main.cpp delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/runner/resource.h delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/runner/resources/app_icon.ico delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/runner/runner.exe.manifest delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/runner/utils.cpp delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/runner/utils.h delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/runner/win32_window.cpp delete mode 100644 apps/mobile/prototypes/staff_mobile_application/windows/runner/win32_window.h diff --git a/apps/mobile/prototypes/client_mobile_application/.gitignore b/apps/mobile/prototypes/client_mobile_application/.gitignore deleted file mode 100644 index 3820a95c..00000000 --- a/apps/mobile/prototypes/client_mobile_application/.gitignore +++ /dev/null @@ -1,45 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -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 -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ -/coverage/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release diff --git a/apps/mobile/prototypes/client_mobile_application/.metadata b/apps/mobile/prototypes/client_mobile_application/.metadata deleted file mode 100644 index 2c6187b3..00000000 --- a/apps/mobile/prototypes/client_mobile_application/.metadata +++ /dev/null @@ -1,45 +0,0 @@ -# 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: "b45fa18946ecc2d9b4009952c636ba7e2ffbb787" - channel: "stable" - -project_type: app - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - platform: android - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - platform: ios - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - platform: linux - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - platform: macos - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - platform: web - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - platform: windows - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/apps/mobile/prototypes/client_mobile_application/README.md b/apps/mobile/prototypes/client_mobile_application/README.md deleted file mode 100644 index edb5b95e..00000000 --- a/apps/mobile/prototypes/client_mobile_application/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# client_app_mvp - -A new Flutter project. - -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. diff --git a/apps/mobile/prototypes/client_mobile_application/analysis_options.yaml b/apps/mobile/prototypes/client_mobile_application/analysis_options.yaml deleted file mode 100644 index 0d290213..00000000 --- a/apps/mobile/prototypes/client_mobile_application/analysis_options.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/apps/mobile/prototypes/client_mobile_application/android/.gitignore b/apps/mobile/prototypes/client_mobile_application/android/.gitignore deleted file mode 100644 index be3943c9..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java -.cxx/ - -# Remember to never publicly share your keystore. -# See https://flutter.dev/to/reference-keystore -key.properties -**/*.keystore -**/*.jks diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/build.gradle.kts b/apps/mobile/prototypes/client_mobile_application/android/app/build.gradle.kts deleted file mode 100644 index 950967ca..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/app/build.gradle.kts +++ /dev/null @@ -1,45 +0,0 @@ -plugins { - id("com.android.application") - id("kotlin-android") - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id("dev.flutter.flutter-gradle-plugin") - id("com.google.gms.google-services") -} - -android { - namespace = "com.example.client_app_mvp" - compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "com.example.client_app_mvp" - // You can update the following values to match your application needs. - // For more information, see: https://flutter.dev/to/review-gradle-config. - minSdk = flutter.minSdkVersion - targetSdk = flutter.targetSdkVersion - versionCode = flutter.versionCode - versionName = flutter.versionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.getByName("debug") - } - } -} - -flutter { - source = "../.." -} diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/google-services.json b/apps/mobile/prototypes/client_mobile_application/android/app/google-services.json deleted file mode 100644 index d2dd9ffe..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/app/google-services.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "project_info": { - "project_number": "717206318340", - "project_id": "krow-apps", - "storage_bucket": "krow-apps.firebasestorage.app" - }, - "client": [ - { - "client_info": { - "mobilesdk_app_id": "1:717206318340:android:b0bff06f9967d8678af451", - "android_client_info": { - "package_name": "com.example.client_app_mvp" - } - }, - "oauth_client": [ - { - "client_id": "717206318340-9c24vluvsda8gh0pt8gk9sd7vj2nptn2.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyCXKJ5yME2a4FlrAzZA5LzSt97JwEwn9qE" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "717206318340-9c24vluvsda8gh0pt8gk9sd7vj2nptn2.apps.googleusercontent.com", - "client_type": 3 - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:717206318340:android:d3eac8c3774905e08af451", - "android_client_info": { - "package_name": "com.example.staff_app_mvp" - } - }, - "oauth_client": [ - { - "client_id": "717206318340-9c24vluvsda8gh0pt8gk9sd7vj2nptn2.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyCXKJ5yME2a4FlrAzZA5LzSt97JwEwn9qE" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "717206318340-9c24vluvsda8gh0pt8gk9sd7vj2nptn2.apps.googleusercontent.com", - "client_type": 3 - } - ] - } - } - } - ], - "configuration_version": "1" -} \ No newline at end of file diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/debug/AndroidManifest.xml b/apps/mobile/prototypes/client_mobile_application/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index 399f6981..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/AndroidManifest.xml b/apps/mobile/prototypes/client_mobile_application/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index ffae6d58..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/kotlin/com/example/client_app_mvp/MainActivity.kt b/apps/mobile/prototypes/client_mobile_application/android/app/src/main/kotlin/com/example/client_app_mvp/MainActivity.kt deleted file mode 100644 index 34dfb450..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/kotlin/com/example/client_app_mvp/MainActivity.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.example.client_app_mvp - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity : FlutterActivity() diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/drawable-v21/launch_background.xml b/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/drawable-v21/launch_background.xml deleted file mode 100644 index f74085f3..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/drawable-v21/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/drawable/launch_background.xml b/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 304732f8..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index db77bb4b7b0906d62b1847e87f15cdcacf6a4f29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-hdpi/launcher_icon.png b/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-hdpi/launcher_icon.png deleted file mode 100644 index 55840fadf9584849159d68e921747409cf0cdcd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2081 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 diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png b/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png deleted file mode 100644 index 9a20688e4dc2de1832e2bd16b49e8915cd11e25a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2751 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 j2ym(Y<7@j{^#?4(OH{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png b/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png deleted file mode 100644 index 1f506d87742ae8a2528cdf908100bd30bce235c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4023 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 SwEPF;G$sfOgV%bl&;AEK0ES2a diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4d6372eebdb28e45604e46eeda8dd24651419bc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png b/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png deleted file mode 100644 index c2c87b7dd57262bdf8ab2138fb3f0a7c338f788c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5214 zcmds*)nC+s(#C%*-3ZGfC>P2;Nl7g1(%lFW0uoAxv@9VZ0uq9N zAR!%x_xAk{&bgSGo0(_kGZ)XrH%>=Og_MYn2mk<5HC3qIeeM3gAi%rNdQ0y3003rJ zgDM!j&i#`Y;Def_9bADsjXIEX`c}p3LB+6;^e7mVf{3NkfX9S~8Vn_eyfdoeL_ddu z70S3YbajZ-Ek{^BjwJDbA|SX(7>a{=)FE|v>_plco|po6+V5By6JI*>pSb>s91G4` z+FCyAtnMfj0JFTofP+3WB5cO#vAN-#qy%WUjckx6c%aqBmBgWJKf4 zL>u%+2g%xtt0LQ*UQRCjOEr`hv)83m24a$MUG{UV0s~B+QU_7joYHY}5n@yd&J$_s z7h)Hiy(T@d^;}dv#h*P^D-Y(QlH=h8_D((D|HD*|s=JOd$l*pd+yn9rgs zYpf$q{hAV^W@vjX8Dnxo9xE2~a;uHKX**AkPIO+${>5RvE6S$d61ZD7(;}BKhf2w{ z{7tvUmw0e{ZXq}x_6apeu3ct+*=|ZesAz%v_tcCr@%5_17=MdX!<`OdKeQ(0wsS;9 zBY(uMP8UQ$gO$reG-b~ZnYPYI&lgPSl5`W#n4V=lcG>yiI@8g?y`0<^#rz9&zT<^U znx!Le9ZD7ZPvr|3XB#h(zpyA|2^AD3Sr#BM;tsRp0&p5HlgBGq34JhV$Kfm4OId!^ zx*PU{B|fpZ8s#w@#7wj;74bGSTsEPLC=)94;%kX1xs%TB=;OoC+yV-cH{0Dm0eWdV z0hXWLznR)sa~;}GSU$1u3(iaUhy1Ky@r->Xoh3-9`9rH1c!1 zbX#7WT&9`Mv^5JaCm-LNq|SS{Hq#L!{XyF5~p1*PcIpQok;J=KL<@yw$@KH!)w&g-ubbmDljx8&2Kb z!-_@cWt^Yxr0v0k^jvKXHWT1Y2=q_th;ds9!F9e60AC*WRDf##ZJ+JKB&Z2!UpMy?kPLuIdCB)T%XjPi zbmzEpQE9YoqYw5+Hr;}ouCW+m_N>mN_@`dr`7ed1lmcV?yn9E2DsdqWa#SdbuX*h($mjz2n~y~Uf**jv=ip~5L~ zYC9a`s{GdOB3tP4ON=b5D65$;vsvdTv0j(dvCHqb?vi!kZPDVYLIwi`PBi*o$+Vsa z#+fBUxGp{(P-(;|kjAVq#$P5CTL6#zP}3f1#Bg)zt$Yt*B7-+)+Pa-CDT~1eb%*Mr zdihSQr_qe81 z!~w@R$KvsiR3kowiW7BC`p8mUPJ&f-s_P{?NjJHyuZ5(Hgk)m5v^BJmCL{aQ)ZFhX z5&T!mQ|wDkcU(>O?4y~kt#a)fJvn|osbT}*;CfUg$8Y$CQWUct;gBsPmRP&H!;-`M zF`O3aS)n;pxZB?Dx~MVGWLt5$LN0yyiqO|>x6~_BFdLT;x)YVTf$S!M}gJ(jSrm0*KDNgcn!}s zNa-U9^z*{JYkTH%lPSH)w|w18p_yZ@$j{mIe#PRq{;5^PhnLRJFkYfz1>(lTSqAiG zl2J9-?4a`_ooL&>cPtCaCrgpEJ{s0-0xhOC6${saA?^Nw%)Egre?aCR7o9D7kuj_q zFea#mCb;_zy~Rc%Mn7)w_vK%k2Ku5j&?YTEa*2a{)1OjwE2|x7e|Pd@zA7-d zw;}7 zKSl$H$>o}02gMgGGQM~arq$H=_#3|#NFGob^fk<@TA!lqOas|be?K+yOV#gjJGhL( z12^0T2*-w=9HI+0pE->sJ1*E&E1k3C;JXqqhKKB>eSyR%iO7Ah2PTcXQTC?eEI?lOV%QgIj&rAixxTW^KI-DQAY+Q5Sj8qy0xpwTa7+jJC?Tuj;8uP~y9jc8?=#f$XuSoRS(N-=R9+s02!# z>D*YG0uPgqDCSWF$tRGTF1C2-C`Fql8#&G-GO$lXsCFnAPJ2M*$sl^VQ0yFm3l?hm zP+J|YyRLCZzjYKE=7PI_ZLxeClURdo(v&HB+OUyF$f3-(ER>~)7SsHrY`C;`HsJRw zz!N>SAvHC$S@Yc>@=S#za+LvQ+IzqAi6E`?i+Bx2x2)>m4 z=Vg<$d&_UuFWAa|;b5NI{6Bf9taLUD{EinvZNEYCe@9;!uS-9m>_#4J@O8iE`NlZy zK6$z^kt40V*h&&h7)8~ct-02z?X$4$7u^@@WKU4I-Ql=-`9adWywDk}*9_Bjl_4N3 z{AiVmd{tz#^PDB}P)(bk6PX=@$j$MpNvpi^SRT^KM~&D#S`>>XT1}Io9<({~N^G>5 z81^Ck%|$_5N6L(~ipSq~L3*-_PS!8{=jdl29t%2nl=|iQZaAC$o$;9fvkVNJ8Bh@X zi~Kv>|CsM(kyxd(a5h^d%X2I+8mH{|4whrWE*T>EsT2os5VCBZ2@hx&Cpe3&OOF43 zH_LkD0(le7VRlZg&zlRR$np|#bs6~K#hC%oMD5bf<-eaIMv^99odHm7H%h=FrI_sr zRkPdedc*)oDO+%nDV~C_tD?C0D2f6G`&%ukOI%o+z6k%*)HY^oA?Db7w{0B{Nt(s? zDLHrClsvTjmz^{*y;Lm_2gOBzolS^-S5Exon?^|6AiTQF|eMq7!)>JK652ont`8Y<~Qz^ zmDM6=NMN+280&I)+Wxm&xo-qR;I6(%r$Llvk(9hq`x2v$7@7sCaMQQywlw%xoYv-4 z9#Bn7f2rY5vVL5b3(n%PSb5uR>5DZ~Di;-`MH_{K;QPF?85dSL0RqH1DS%%B-Gf$7 zZ10@Qo?yyI`}nbDME0bZe%ZYb6)K8eJMCEe8t5zK&4nM0gUC}T-wlT|3}pd*xua&v;x1;5p^!#-}#%TJjctr*R`Euh_+Kd&hD4f5?1;d1Z7`OTv z9cT7wUTk+$${(Ja?zb#e88w$0+t^gK1VZ z%5_Ov_NCR^aGuK|BNK3@4Kkg-SHI~lWj+u0>7vUti)0zz%O}(W2hGe)sX6LIOyg;# z9*P#!f0OM$zK3HakldT@XEd``{6fNjEPmCoFa)KefXp%IK)gd7<b0f2>=dEFI`@4M4i2&c1081@lEk<9S-B4kw*=@P zN{uPya1^{<*ebf9=CD*Ies!hG%9Jxq_w;WH^UZ>Lsb@)7>!cRrc%8G4^lRI=vnHqd zN-?^i#u$c6OS*$=QAFPCx>oA*EK1T0F?jhNiC|rPyurSz0$J+L{bHT9q@G^oxeteZ z`iUDgeP6IqCrbSf4RwU5q$hkPSANAi`BkOA!Az?4)*2y4=%0RwtE)W4$l^F-a{;hL_!nbM zs?z$q?McQo0z4o;BVk-b(g@4`SAEwX{miq{EqoJhHVKt&wOl3uq$q7IRJZ??Odvj~##^(LnX(@D)9qe!LJ-m2?zX}>z?Jnsozzp_T%YaCMSWno-efNBUKF~X zus8Fe!SdZi3x|NVcxsy^2JoDG#63&I1Zk72=mph34EfZCA}(~!tP<)ySmS7CqPV zwpBBoWdVM^(;AOOj>&07E|H2=XITY+MML2B6b;lA!tsJF>|Go zU7+WsUjVj$(c}`?kJ#t4N7#J6zXF`e>-lx0T&)eJOFdCyj_)_~AX3lHNv{x68k(NS zkf;CnWjs_mzmel!7VjT5Co7Edd(;ymS2ud>(@US1Q{LnbgJoM&m5*dZDl>BK!H3CK z?Cc8<`jaUXT*C*?0gDZ&EU~)KOA-ts*5@E+c>g%#xyCzpfp5hPKZcGyUG%UQRC_q* zjTyfdhgcgve2+N`qbgi~0#ZJc64CAU_H+Fs5*TfUyDLpd1u0dxIdN${EHNq?9`IX7 p6R-{H3%ynQ-vL+uAHQYaVOcr?`pNo|P50aoP=jefYZYxG{sWtsqOSk| diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/values-night/styles.xml b/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/values-night/styles.xml deleted file mode 100644 index 06952be7..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/values-night/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/values/styles.xml b/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/values/styles.xml deleted file mode 100644 index cb1ef880..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/android/app/src/profile/AndroidManifest.xml b/apps/mobile/prototypes/client_mobile_application/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index 399f6981..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/android/build.gradle.kts b/apps/mobile/prototypes/client_mobile_application/android/build.gradle.kts deleted file mode 100644 index dbee657b..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/build.gradle.kts +++ /dev/null @@ -1,24 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -val newBuildDir: Directory = - rootProject.layout.buildDirectory - .dir("../../build") - .get() -rootProject.layout.buildDirectory.value(newBuildDir) - -subprojects { - val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) - project.layout.buildDirectory.value(newSubprojectBuildDir) -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean") { - delete(rootProject.layout.buildDirectory) -} diff --git a/apps/mobile/prototypes/client_mobile_application/android/gradle.properties b/apps/mobile/prototypes/client_mobile_application/android/gradle.properties deleted file mode 100644 index fbee1d8c..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError -android.useAndroidX=true diff --git a/apps/mobile/prototypes/client_mobile_application/android/gradle/wrapper/gradle-wrapper.properties b/apps/mobile/prototypes/client_mobile_application/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index e4ef43fb..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip diff --git a/apps/mobile/prototypes/client_mobile_application/android/settings.gradle.kts b/apps/mobile/prototypes/client_mobile_application/android/settings.gradle.kts deleted file mode 100644 index e4e86fb6..00000000 --- a/apps/mobile/prototypes/client_mobile_application/android/settings.gradle.kts +++ /dev/null @@ -1,27 +0,0 @@ -pluginManagement { - val flutterSdkPath = - run { - val properties = java.util.Properties() - file("local.properties").inputStream().use { properties.load(it) } - val flutterSdkPath = properties.getProperty("flutter.sdk") - require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } - flutterSdkPath - } - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.11.1" apply false - id("org.jetbrains.kotlin.android") version "2.2.20" apply false - id("com.google.gms.google-services") version "4.4.2" apply false -} - -include(":app") diff --git a/apps/mobile/prototypes/client_mobile_application/assets/logo.png b/apps/mobile/prototypes/client_mobile_application/assets/logo.png deleted file mode 100644 index b7781d5a2cf7f0713e770072f3c7af2b40a60b78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8558 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 Af&c&j diff --git a/apps/mobile/prototypes/client_mobile_application/ios/.gitignore b/apps/mobile/prototypes/client_mobile_application/ios/.gitignore deleted file mode 100644 index 7a7f9873..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -**/dgph -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/ephemeral/ -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Flutter/AppFrameworkInfo.plist b/apps/mobile/prototypes/client_mobile_application/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index 1dc6cf76..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 13.0 - - diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Flutter/Debug.xcconfig b/apps/mobile/prototypes/client_mobile_application/ios/Flutter/Debug.xcconfig deleted file mode 100644 index ec97fc6f..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Generated.xcconfig" diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Flutter/Release.xcconfig b/apps/mobile/prototypes/client_mobile_application/ios/Flutter/Release.xcconfig deleted file mode 100644 index c4855bfe..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Generated.xcconfig" diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Podfile b/apps/mobile/prototypes/client_mobile_application/ios/Podfile deleted file mode 100644 index 620e46eb..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Podfile +++ /dev/null @@ -1,43 +0,0 @@ -# Uncomment this line to define a global platform for your project -# platform :ios, '13.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.pbxproj b/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 92b8f353..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,728 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXBuildFile section */ - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 59A242D46CCC2B41A5A2C541 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BD5AC650E4AD66A8AC1F1833 /* Pods_Runner.framework */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 76284B4CE5310321526352FD /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93FA99887D920E203CE2CDBC /* Pods_RunnerTests.framework */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97C146E61CF9000F007C117D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 97C146ED1CF9000F007C117D; - remoteInfo = Runner; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 50734491C8F4091FC4215298 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 6B4A6F53289C89C876C48A46 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - 6D7BF6C00FBA636F126BBD33 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 93FA99887D920E203CE2CDBC /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - B701E0489709E5092E6A038C /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - BD5AC650E4AD66A8AC1F1833 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - C4A6F6F8B46779D11DEEA3E7 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - F4AA850DEDC9D26C59B80E5F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 59A242D46CCC2B41A5A2C541 /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - F86625E7251DC5F34D5E3557 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 76284B4CE5310321526352FD /* Pods_RunnerTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 09914133214C1E3120D3D9EE /* Frameworks */ = { - isa = PBXGroup; - children = ( - BD5AC650E4AD66A8AC1F1833 /* Pods_Runner.framework */, - 93FA99887D920E203CE2CDBC /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 172627A77D8C2EB68F8D116E /* Pods */ = { - isa = PBXGroup; - children = ( - F4AA850DEDC9D26C59B80E5F /* Pods-Runner.debug.xcconfig */, - 6B4A6F53289C89C876C48A46 /* Pods-Runner.release.xcconfig */, - C4A6F6F8B46779D11DEEA3E7 /* Pods-Runner.profile.xcconfig */, - 6D7BF6C00FBA636F126BBD33 /* Pods-RunnerTests.debug.xcconfig */, - 50734491C8F4091FC4215298 /* Pods-RunnerTests.release.xcconfig */, - B701E0489709E5092E6A038C /* Pods-RunnerTests.profile.xcconfig */, - ); - name = Pods; - path = Pods; - sourceTree = ""; - }; - 331C8082294A63A400263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - 331C8082294A63A400263BE5 /* RunnerTests */, - 172627A77D8C2EB68F8D116E /* Pods */, - 09914133214C1E3120D3D9EE /* Frameworks */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - 331C8081294A63A400263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C8080294A63A400263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - AE1567838935F36DA48C52B1 /* [CP] Check Pods Manifest.lock */, - 331C807D294A63A400263BE5 /* Sources */, - 331C807F294A63A400263BE5 /* Resources */, - F86625E7251DC5F34D5E3557 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 331C8086294A63A400263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - A06687346091B014AF063603 /* [CP] Check Pods Manifest.lock */, - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 4F27457BBFA344CA19B6713C /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C8080294A63A400263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 97C146ED1CF9000F007C117D; - }; - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - 331C8080294A63A400263BE5 /* RunnerTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C807F294A63A400263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 4F27457BBFA344CA19B6713C /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; - A06687346091B014AF063603 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - AE1567838935F36DA48C52B1 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C807D294A63A400263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 97C146ED1CF9000F007C117D /* Runner */; - targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.clientAppMvp; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 331C8088294A63A400263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6D7BF6C00FBA636F126BBD33 /* Pods-RunnerTests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.clientAppMvp.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Debug; - }; - 331C8089294A63A400263BE5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 50734491C8F4091FC4215298 /* Pods-RunnerTests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.clientAppMvp.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Release; - }; - 331C808A294A63A400263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = B701E0489709E5092E6A038C /* Pods-RunnerTests.profile.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.clientAppMvp.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.clientAppMvp; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.clientAppMvp; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C8088294A63A400263BE5 /* Debug */, - 331C8089294A63A400263BE5 /* Release */, - 331C808A294A63A400263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a6..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index e3773d42..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcworkspace/contents.xcworkspacedata b/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc14..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/AppDelegate.swift b/apps/mobile/prototypes/client_mobile_application/ios/Runner/AppDelegate.swift deleted file mode 100644 index 62666446..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Flutter -import UIKit - -@main -@objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d0d98aa1..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1 +0,0 @@ -{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}} \ No newline at end of file diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index d0e33935c1efc234562b5a193dfa89c4c5cc1a0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30733 zcmeFYg;$ha7dLzjjUwoch@ga03JOSfs5F9-(x{|>bjJ*0f=G;XN;gV3C`xxabPO?c z!wd}b9=xCDUEljJeCt`uwbV7&+2`zi_Sx~*LK<2eX|E~qF!)Pf)q@J|wm zf(ZPz1+N=|AkQI{hw?gJiEESNj@J&$xA5W-U+$c{+~%oWKJUQ6%RW>%{7aEa4AGB= z)*Ct|12zv>{?y_p7Uq7u3Y@&j_p(WGLdWB>@`vZS!N%XO-uGiSkm{l`JF#j%_rjor zoq6$F1IyLGyz3Gb@6ZL)65hUqN=F#jyzhq^?(7hdI`!Fqp;U_h{q;W){7(!1_YnSP z3;t&g|K}0@|L6_FGd!}VF$a9dj@3mA)fG#I$<|>@H4r5C>JkL0thgN)2C0!lnQ6kh zWd&*L+vmt2DCXBZv6HxbAI*IpisNTCOxO2m%n}F;@9-X#)0mErr`xg&@NC(mB-WGd zY3WmIveS*lv|5*#@u7t3dh}}BRcKOCk=i|J7n4lyN}wLyVMiREdGI@$8RC1 zDv?#F^TMw4+-JN3L$u1nE9f_T>>0?j>2%{jtw7rk2M7#S!_?c3VfjP zQ$ zTStwF$L^k}LERnKaT_R4^#~ zzTX|TaSLujf~&taYO^wJacY|Zo(TIeWdU_fcbk#Ieaa5f?{@ASrWNWRw0LaoDQvol z$TehH19_2Lf>^;?xL*_8ucfhqp}^5)AO)g*&QzEFVa3e~kqqAEKMx_qorvAjD(lhf z>!L;xQp?A_StA7WPzv%?M?8rkM{iC_ZbIa7La7~{Qbknz&DR;l^bjJE4U&s)^Cpbs zJ6TFU^=0_AkN3$wwD^tbLfA8hcOlv-?|ALFXWE1J0P(*ffs~5}m+;#vaG@=xtV4@P zd*(m;-Mu~2AtPq*A}{2OYFr7ApoJiFV+ttTG`sgWvqKiM`tzH`u3WRab;*b*{3KA7 z+1$I|$n+)`1T|G%gjh{7vfxe@OEjTQ+0K4bKo27u(Q5d)LEo$F%;@ZqqPC^-Cjn@3- zMF`qdfDkIz3U;jXXn6Dcgj|JTQjeoIse!i3(&^hScB%FQjMXNFkP z2Qcx>kt6coYMf7)BtZ7$#YY5vnwqg^ab4MDNx`X+A++J2dNI^M< kVWOCPVu+QF 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 diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index c7df9ee5994d72460e1b23dc3087944e13ac2cc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 506 zcmV9Vm1H$`@ehs*U3x2efn6Xu-@qjd+y8LV5#_uNDEbAu;LR?#!!re0SOW(q8Wxb!~HVZ7>^8NYi ze@nM~Z^-6(^ZwuIE5B`xS)n#>-1n1#fuT8%7w%6cCdS$foEvDqd)n0 z7(adazvuYR51&E)^0Z}#YJUFuF9QREh9XMfF)}hncygS%@_YXJ?>F!NEsE!wz54sk zqrZOq{4XlVWUK|VSwe)Ffq~)6xBr5CDB|L#5c^Z!2v zKSy>ZCPt{{@?>srdv;j~X0*UmkY-VpXTJULuK+Kju{Nu-1>4p`AP;)kaUepQpO?wn zkPT~O1i5f@&i(4^$j-vd=w`*v#`>9ui_yW94ND@y1m(%xUUuwS${=Mj63k~-iLkRW waB?sbrJ0F|QD2=E&Xtoy@!BBC7a5dh_{2q+;ZiHNe{Y=jMMsTgVXFWq2P3-0rM;iwwz9D@WJhu(1aQeqf%Jd; z{BP5NpZyEJ-h1*F6deo5iZTZ{Bm7-6`Sa!jprG1&;#c*gFLRpsA>#l4|F53( z`OW+P&tCu9bK)l?s1O#PzVd73_8$a?(WdzP_5YD`znsk385kH2oc;w7 zloDmqS7$-7`1_ClyN*HK8|=zqp~r@4D;(5i@*Ftz>(VVyq^#QUy)}=AmzxQ$9S*i0 z{0X)A6x3o58+JxUMih&$-u?3vDhsk0kF6j*%#7v9+|lJ985kIT{AAd7@|V98$L?cL z{gwu-$1nV5U|`sG_-A+N|KGnEj$MFRY|D-?1VX)h^A|3puE5Md2)J6Yb8|9&{SFG- zeJ6jJ>9StG2ThfY**xxP@Bja2c>em|)jNMafBF9noN_qX8ElOa0SUDjxxvRsMA5{? z%4lc8w*Bx=u*E-3b)X4CR)Wb?hgDyl<-!e+JNBLU_5CN*Y-bC0PIiRRP>V$c5hc<6 zr+*cs376rnmQafyzxX$O#W$EBC>C8U*&!D1KK}C$tWfZGVn@~vwLnXm1s-&Qd_)z8 zu2$>}44)zFt9PNsJ6p1WJ;&BP|0^(3Ph9*B3n5U-!eTKmH`Ce)0xP!va4=;v(7=+B zFoCQDvyKYOl{<)Hj*XSU-UMW^i4Lm(FXM;L|Np>Jj;%2pFE@&R5J768&t{>IFBf3~ zcN=zOi>(aUc(|A#$==qO4N{6hfSVONnqG?PV-Fkl-UVL~?yyF<+sPcwVstN2WU+}h zi=!FaesK99E5Q`u#R-=Rbmr(?`1Q$)f51Y`)0SOP2HhfxEM{b6T+t)2VegNx-~anN zaUiEk0Y0Wf3xzlA{lU$}80d_pM546m!_LMS?#YQ&N{F8+DToV~#zEQU8nt-T;!%r7 bEyfD~p}K4r3-HTg00000NkvXXu0mjf65kf1 diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index 7b90a0966de3defd4d7d90bad3918796df20dac6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1604 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 bEyfD~p}K4r3-HTg00000NkvXXu0mjf65kf1 diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index 65900f5b76a940734d1ac4617f87358e02810c3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2135 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 diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png deleted file mode 100644 index acd25220e3ec10de87f4449bcfc6484db2555b3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1303 zcmV+y1?c*TP)0Pg-9g<+ElcG`_f-p9fx1k`&223`I3uAANZMwN^&Si6%xJ>63{?R3D zV~K7iOC*j+(k#x!2!&x(pgJK86&()85~CB4*IL@^UGHXTd(ZVaz)QN|l79cXd!FC( zJfG+H@;trbqvJey@PyAbfV@IjN)*CUq7ar6g|L(;gr!6wEG3#9Yh;W&-Ql{@%MOlk zZZ`J=SDZSAU{c;WA`A z&!6pJ`fjqzO{x`%s;LHp!(2lfon*ovjfcHbtO+N-ak~tY$%w_p;3^#48gO^@uuNe8 z(UVTr4G!(qOMJ%j{M(<8A3f>xzHWO-^Tjru#06Qe4D}CjC<@F~;kjv~Jl3wSY+XG8 zYi`IRKYk-@*%D|uZs*JvXVqc*joX~iXtp>LV(|}N)r!Y9T3rGY0HFHEiLydk7qIsc++FflsWQO*Y-`#!U zF;!YJA+#L()hQWU-$IMAnyj?&Y>LK&=K!p4j@X6o4Gaaf`@&bRAiy-DNM!#G{X9Lo z?+3fL#m#{o`)y}xBD|sGIKH8kmW*mX@A|OZ_e{I^vmGv>YkdyfKg7B_!HH*ixtN-P zNl?WWZFetw;*4+Lr9au`^RB#fPb@mGvO}ZN&#DWT8M}kiQs|@subKwS z#lk#L&z@8PN?wZ3k3a{8eH*j1(YFTS%vp~UMg#W9VyvgnbBhfOaTj}7o1J&k&>&2M z%46xYFtmds98e+zLDsA!%od+NnymEjD4ZdCrDvD<8DvkN&!dfPv_q75g{w))gb>RZ z1qj-T=b&$D^Iv({%zT_ru`OADyd0!k^6p!^JCD%QFT zxazueAC_2C6D!C+n)5Tsua8WKTS&rFWx{Ko2hk=rFdEPVxx*-!SZT?s$a$!^ir1zR z8Z|8Nhv#F7CcL{BdbBu4E&Ka1m{=+tseC`|tBAcF}VirhCtT;z~;sE-~DOyV*etC3--y{soKr!#kgRutER; N002ovPDHLkV1la9fjIyG diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png deleted file mode 100644 index b876168c5ba8e7aa7e55e09324ebafd79d416be7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2736 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 diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png deleted file mode 100644 index bd5106947f008f5930446e05bf0df8949196415b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1519 zcmVnxo2)D+8=D+KOd4k#XL3-`lBpT3 zL9J07qmf=HCXEp*L|#%*XGqNyS=;JO}b@Yj`culE1UiP_3Uq++xzVA z`Tl;-vy1jRIp`q~`fmd~fHYQhq_L_aja40Ktm;T(RYw}DI?`Cx(QsM29qj35U&}TB ztsd6r=S+GyW;C3fh^8cA7z$K|HS~2YtMOER$)Sz5iFWRtX^uE`UIvH z#|Dsx&kNd9qx@PYrQp1 z-MjM06$|x$8=YLrtcNPxIfYK{0pG;>Jlvc4&Ne%z736{=j{MoyHhbu6C@$KGA6;XN} zP-bdJJx;FuCNm)(Rc0+Jp*nBNNMB#3FU%!TL}5)~0G>%F z=BDCXcDweLxrI2#LF=|V8_OcYNik=&=e(3Vc(E#L=^)nXGh&IDO(0>6Xc8G~uZ#Wo z3)!PD&(gj77O7}HK{y6>ZU_q};hmpQLhx1(yXye8Et?b~RSopu-`1V?Qf}6$=O3x7 zo4MF3E>WhHkT!1_>sM8tK96`A9R(NV4FM`>(`sYOb$|H@5$Hgw{{Vd<$mtZaLZLm1cf{+(k0h$~xJj=e%qrjWXkh5CEVkFRc2^?Vf=TIh30#|K9WJ zlKv&WV)tLM2UlT0$LncStPU63?GRUBTr3h9KHQ`V zTDe$XxStZ*$f>hl56$TaAT?`T46=HeVdHyzW4h7FUcSmqOhA8aXF9sXvJNtUjJ3xl zE7IsFg)Tj$MnxhsCSgA{^XucL`^(>&g4dlB6J|@pZ59H8TtcL(o}QS1N|V~pI{W^t zK^63%o0gzVDyKuabuCzc1Djc_ zr7$$B1w35f8k4D13-{AqG(vGRQ#63W*#!U)J!&M~N-DDno;ew-JMRmM z+bo21#}@n`6@f!@Qx)PWzQ@`ugaWG^E-@C3i$Q`;z!}qV;V2U%wOF5>N8}gZm3AxA z2r^~_Cu~s$v8PmavRgd&z8kw*tO<{!Ti!5j{pc?LHwg5>rZAHsIAI%JF&?j@Tdwn| z&6tiqpY@Nk-fLC4D~;(>u;cY!4271=(+S6WsUpnq4+kQSeCN6T85C^qheHkKc&?3({ECk;bZyG*)$_v8p4DRUK)p>gZu&{R5Yn V60YyNz$5?w002ovPDHLkV1jqK$gKbX diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png deleted file mode 100644 index 47ef28c60436f993c05b39f5d3d2ae4ca4461768..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3063 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 Aq5uE@ diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index eb73d40b0c2090432cc27c14ba383eaf4020ebe0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3227 zcmcIn=Q|q=v`6g`BSvfQ-STSC)JxG2sV%75Vk=cOqETwE6jkM|Xv`S3VvpLJQf;hM ztZHko)(WCr_kXzedCvH7&iV2?W4(6bMh7%3wti6{%gh*!iNd&}TdV9UBA6)+nbs9K zX^LTG;h!w*8n<1F!^gN){lZ0khWlt=*kRHj!27ueowoz`cJJf`@$Q1j<97l%$S*Eq zZtQ9vU;`u8kP&P4@6Pm-x@kp9iUodO((tA*D)MvMfW&LOAkKuu?n2HeJqa4LKJEWq z0K%b%E<7B?S0DW6kZD!DX-hz4K+>JPCh}$G^vwuD>n+trZH)4vY%Nuc?dyS=!33N8ZuQ~~`9r7yQ?W~b(G2>#sYTjkzoVmGZy*h9D2Lwa-yzUM1@e%MedQU%uQ z?ryw*eimsybb*+kg=QROu1IG{Ij4nK5tH{`csxg@xZBfTt{$8L{MNM{THXIR9S$f| z%Q$(DS({oQbH=`38^8JMPAv74w@1M65^PYX4J38P+lQ|t4>Ncj)3(b zw8wfdX-3oPOair|w#9-LxY;BMf?k9)^*(bsdK^!!35GPY(rBS0wj?I)M6zQhuZ!~G z6J2ww?GCI@e&g(zC9bf;BfkNJkRXg+uEbA7c0e}f;-%Z)mbW9~5iLEaeBBxnZc+2w zJQL|%YRyK!IsvWqgnCrCG6eAheWb7&r}^){{ap%`XQci8F#UvsRsVg%*p)5CjKSD; z3cIE;hNGRv($1Z~I<^nTxL~ z-d=d))gxw{JLhbrP9cEO1G_v{xgFMIZN`#!wN3deupsNOVp7NA>0V37Fvzj#pZ+|j z@+FG5o27=8T+^gnN9P3Yr0Gb*x4tBPP+x&%wrL4~+Blbb7>t#*>o%7eah8rh{?-oCHFmzK$al-Zs?lu$ zE^lPboak(MV*!$V261bp-i$h`L6G^=ztRn7Y-Vo7Cutp^ zw`{Q_i-$4h^7mF^P3u==T(G+r+|I7t5WKyAt$c9e^U0v7x)(9o@F0+Jd#6Ru5i;)B z)l=}#LL^cN%)Ax(dDg)Tl~2j2~Y`CoNj!b70q2H=}JWf7<^{7Q@jbFxQJ%dG)b?JCzHZm__^cRzM;vau+J;JV%jQN{wmnbV`JL8H zg{TKEZP#gDIKwq^$S3fTtGV(K=wH?+os(rH$S_r*sU{y(D^? zR>ZW+C@n2Qg4{DJ1O?|cpyqt|VJJ_J&UxEct$!*uST7yKYL;qQ(^V}CB3QV?_Z5Aa zH-STi^ZN$7Lr00lFYmH%o9iXep{*uRY>Nv6HGkga6k!`_ucwCasPf!|O*lS{+yxHB z%UNAS7QXCcI;p8|QO5G_GT7Hi3KAnbQn!;5D)$Xj z85ax5Z)x-%t3slaf3&oF<>Z@H#+It|L`sgl(wYBni3XUIEFz@V_Ulm&k4ThMNj6a< zV(E^w_^Zlm=k?26c>HHKUWIP3>6vz}Yo=dA$)q+rU{V`0M~CoC4>$U#!ABxrGYc|; zmLu6$&*&pZ2%7RDR7r70W&y?_PFt8Z9be9 zlCnv1rE05Er z#iuqcPpvFPswv>h7fsn@vti0ti@qDZUyX2PU|MF{lQStTrYA2S)BG6Q-696G;*#Or ze+ud}`XEF4lN^MhFJ*HuHV`|`t3(O(vAa)BX{kx5{rO#l!Q_M0b&#;+*}N37_BJ5n zkq<4cLTa%8hcaKVS&+RV+y-zit$=SZN_)Zw8$f!B2B)#B+lX>1DKvUByb#UItNq4^ zx}2fWa8r8#`#x3Ls!izlSWoLh*HNyQySO0wPi|adyp1%hH*8~FtXyb86{CfObuMk+ zapvo(?>uXv24d&gvtr5Zr33rDIIa0|e3T}YF1c-8ZCOR=sk0KV-BWkWb#T#ntmx?}3M$GU*;s0$our@Le-R=1%*3$9;!rH2P=Zy}iEvv_r70_**V zy6)HW#E*!Ml{IuV$D)Hs=yKB6MNQkWx&+P`@I46ow$#%0dTNa_oA~Sy9x68VMiT7a z9`Y%)YEsS|#MvHhlV?`>OSN>bgY{RyyUK#|2_>FmO2;xd4qOTLSp&tl-sBEj=Nt{% z)6MJreqTh8?ar?au{kK=#q`7JH;7vbq&@8B8yQuWUCQ} z900_c7#?l*WJP^ZMv1}@xV?a)V6-qec5h19dh|#+0!RPs_-jt3rK5RJS6H|m$6`JY z+T;4OWBAAUhc0Q#3r7s7C%1kFc>%BbwtvdIbvoKznJ$@>4WD+bVydzM>2RcJaacTB zq0xNn`8C5y5d?|-U>wSZ@;RtW-1cs)OL%AS#zqCcM+O#G*zCd~`2WhT9t>L%rSl=pUj|k;@h?+7F z_(br^B0(+gQvx0SYW|p%es6o4>@qX;H9R4<{4v6dG5h+L-n_TweOOTvJmbbxj=+?L xv*`+Qqd#ba+W?GAT%Qy9|7PA-BtG$yN*frg<0jy8eD!ot!SqZZ)w<5n{{v2xB#Hn4 diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index 7de91503a393d7470305310fe1b3cfbbb71a0935..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4753 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 Mp`xQ)p=cfcKXFhU-T(jq diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png deleted file mode 100644 index ecc091c1662b0ac26ca5bba995adfc43e682cf7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1942 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/AppInfo.xcconfig b/apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/AppInfo.xcconfig deleted file mode 100644 index 9932ad62..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/AppInfo.xcconfig +++ /dev/null @@ -1,14 +0,0 @@ -// Application-level settings for the Runner target. -// -// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the -// future. If not, the values below would default to using the project name when this becomes a -// 'flutter create' template. - -// The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = client_app_mvp - -// The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.example.clientAppMvp - -// The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2025 com.example. All rights reserved. diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/Debug.xcconfig b/apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/Debug.xcconfig deleted file mode 100644 index 36b0fd94..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Debug.xcconfig" -#include "Warnings.xcconfig" diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/Release.xcconfig b/apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/Release.xcconfig deleted file mode 100644 index dff4f495..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Release.xcconfig" -#include "Warnings.xcconfig" diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/Warnings.xcconfig b/apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/Warnings.xcconfig deleted file mode 100644 index 42bcbf47..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Configs/Warnings.xcconfig +++ /dev/null @@ -1,13 +0,0 @@ -WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings -GCC_WARN_UNDECLARED_SELECTOR = YES -CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES -CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE -CLANG_WARN__DUPLICATE_METHOD_MATCH = YES -CLANG_WARN_PRAGMA_PACK = YES -CLANG_WARN_STRICT_PROTOTYPES = YES -CLANG_WARN_COMMA = YES -GCC_WARN_STRICT_SELECTOR_MATCH = YES -CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES -CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES -GCC_WARN_SHADOW = YES -CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/DebugProfile.entitlements b/apps/mobile/prototypes/client_mobile_application/macos/Runner/DebugProfile.entitlements deleted file mode 100644 index dddb8a30..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner/DebugProfile.entitlements +++ /dev/null @@ -1,12 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.cs.allow-jit - - com.apple.security.network.server - - - diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Info.plist b/apps/mobile/prototypes/client_mobile_application/macos/Runner/Info.plist deleted file mode 100644 index 4789daa6..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Info.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - $(PRODUCT_COPYRIGHT) - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/MainFlutterWindow.swift b/apps/mobile/prototypes/client_mobile_application/macos/Runner/MainFlutterWindow.swift deleted file mode 100644 index 3cc05eb2..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner/MainFlutterWindow.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Cocoa -import FlutterMacOS - -class MainFlutterWindow: NSWindow { - override func awakeFromNib() { - let flutterViewController = FlutterViewController() - let windowFrame = self.frame - self.contentViewController = flutterViewController - self.setFrame(windowFrame, display: true) - - RegisterGeneratedPlugins(registry: flutterViewController) - - super.awakeFromNib() - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Release.entitlements b/apps/mobile/prototypes/client_mobile_application/macos/Runner/Release.entitlements deleted file mode 100644 index 852fa1a4..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Release.entitlements +++ /dev/null @@ -1,8 +0,0 @@ - - - - - com.apple.security.app-sandbox - - - diff --git a/apps/mobile/prototypes/client_mobile_application/macos/RunnerTests/RunnerTests.swift b/apps/mobile/prototypes/client_mobile_application/macos/RunnerTests/RunnerTests.swift deleted file mode 100644 index 61f3bd1f..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Cocoa -import FlutterMacOS -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} diff --git a/apps/mobile/prototypes/client_mobile_application/pubspec.lock b/apps/mobile/prototypes/client_mobile_application/pubspec.lock deleted file mode 100644 index 377d9419..00000000 --- a/apps/mobile/prototypes/client_mobile_application/pubspec.lock +++ /dev/null @@ -1,866 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: c209688d9f5a5f26b2fb47a188131a6fb9e876ae9e47af3737c0b4f58a93470d - url: "https://pub.dev" - source: hosted - version: "91.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: f51c8499b35f9b26820cfe914828a6a98a94efd5cc78b37bb7d03debae3a1d08 - url: "https://pub.dev" - source: hosted - version: "8.4.1" - archive: - dependency: transitive - description: - name: archive - sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" - url: "https://pub.dev" - source: hosted - version: "4.0.7" - args: - dependency: transitive - description: - name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" - source: hosted - version: "2.7.0" - async: - dependency: transitive - description: - name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" - url: "https://pub.dev" - source: hosted - version: "2.13.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - characters: - dependency: transitive - description: - name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" - url: "https://pub.dev" - source: hosted - version: "2.0.4" - cli_config: - dependency: transitive - description: - name: cli_config - sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec - url: "https://pub.dev" - source: hosted - version: "0.2.0" - cli_util: - dependency: transitive - description: - name: cli_util - sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c - url: "https://pub.dev" - source: hosted - version: "0.4.2" - clock: - dependency: transitive - description: - name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" - source: hosted - version: "1.1.2" - collection: - dependency: transitive - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - convert: - dependency: transitive - description: - name: convert - sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 - url: "https://pub.dev" - source: hosted - version: "3.1.2" - coverage: - dependency: transitive - description: - name: coverage - sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" - url: "https://pub.dev" - source: hosted - version: "1.15.0" - crypto: - dependency: transitive - description: - name: crypto - sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf - url: "https://pub.dev" - source: hosted - version: "3.0.7" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.dev" - source: hosted - version: "1.0.8" - equatable: - dependency: transitive - description: - name: equatable - sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" - url: "https://pub.dev" - source: hosted - version: "2.0.7" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" - source: hosted - version: "1.3.3" - ffi: - dependency: transitive - description: - name: ffi - sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - file: - dependency: transitive - description: - name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" - source: hosted - version: "7.0.1" - firebase_core: - dependency: "direct main" - description: - name: firebase_core - sha256: "1f2dfd9f535d81f8b06d7a50ecda6eac1e6922191ed42e09ca2c84bd2288927c" - url: "https://pub.dev" - source: hosted - version: "4.2.1" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - sha256: cccb4f572325dc14904c02fcc7db6323ad62ba02536833dddb5c02cac7341c64 - url: "https://pub.dev" - source: hosted - version: "6.0.2" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - sha256: ff18fabb0ad0ed3595d2f2c85007ecc794aadecdff5b3bb1460b7ee47cded398 - url: "https://pub.dev" - source: hosted - version: "3.3.0" - fl_chart: - dependency: "direct main" - description: - name: fl_chart - sha256: "7ca9a40f4eb85949190e54087be8b4d6ac09dc4c54238d782a34cf1f7c011de9" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_launcher_icons: - dependency: "direct dev" - description: - name: flutter_launcher_icons - sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7" - url: "https://pub.dev" - source: hosted - version: "0.14.4" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" - url: "https://pub.dev" - source: hosted - version: "6.0.0" - flutter_riverpod: - dependency: "direct main" - description: - name: flutter_riverpod - sha256: "9e2d6907f12cc7d23a846847615941bddee8709bf2bfd274acdf5e80bcf22fde" - url: "https://pub.dev" - source: hosted - version: "3.0.3" - flutter_svg: - dependency: "direct main" - description: - name: flutter_svg - sha256: "87fbd7c534435b6c5d9d98b01e1fd527812b82e68ddd8bd35fc45ed0fa8f0a95" - url: "https://pub.dev" - source: hosted - version: "2.2.3" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - font_awesome_flutter: - dependency: "direct main" - description: - name: font_awesome_flutter - sha256: b9011df3a1fa02993630b8fb83526368cf2206a711259830325bab2f1d2a4eb0 - url: "https://pub.dev" - source: hosted - version: "10.12.0" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.dev" - source: hosted - version: "4.0.0" - glob: - dependency: transitive - description: - name: glob - sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.dev" - source: hosted - version: "2.1.3" - go_router: - dependency: "direct main" - description: - name: go_router - sha256: c92d18e1fe994cb06d48aa786c46b142a5633067e8297cff6b5a3ac742620104 - url: "https://pub.dev" - source: hosted - version: "17.0.0" - google_fonts: - dependency: "direct main" - description: - name: google_fonts - sha256: ba03d03bcaa2f6cb7bd920e3b5027181db75ab524f8891c8bc3aa603885b8055 - url: "https://pub.dev" - source: hosted - version: "6.3.3" - http: - dependency: transitive - description: - name: http - sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" - url: "https://pub.dev" - source: hosted - version: "1.6.0" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 - url: "https://pub.dev" - source: hosted - version: "3.2.2" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" - source: hosted - version: "4.1.2" - image: - dependency: transitive - description: - name: image - sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" - url: "https://pub.dev" - source: hosted - version: "4.5.4" - intl: - dependency: "direct main" - description: - name: intl - sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" - url: "https://pub.dev" - source: hosted - version: "0.20.2" - io: - dependency: transitive - description: - name: io - sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b - url: "https://pub.dev" - source: hosted - version: "1.0.5" - js: - dependency: transitive - description: - name: js - sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" - url: "https://pub.dev" - source: hosted - version: "0.7.2" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://pub.dev" - source: hosted - version: "4.9.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.dev" - source: hosted - version: "11.0.2" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.dev" - source: hosted - version: "3.0.10" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - lints: - dependency: transitive - description: - name: lints - sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 - url: "https://pub.dev" - source: hosted - version: "6.0.0" - logging: - dependency: transitive - description: - name: logging - sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" - source: hosted - version: "1.3.0" - lucide_icons: - dependency: "direct main" - description: - name: lucide_icons - sha256: ad24d0fd65707e48add30bebada7d90bff2a1bba0a72d6e9b19d44246b0e83c4 - url: "https://pub.dev" - source: hosted - version: "0.257.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.dev" - source: hosted - version: "0.12.17" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" - source: hosted - version: "0.11.1" - meta: - dependency: transitive - description: - name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" - url: "https://pub.dev" - source: hosted - version: "1.17.0" - mime: - dependency: transitive - description: - name: mime - sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - node_preamble: - dependency: transitive - description: - name: node_preamble - sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" - url: "https://pub.dev" - source: hosted - version: "2.0.2" - package_config: - dependency: transitive - description: - name: package_config - sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc - url: "https://pub.dev" - source: hosted - version: "2.2.0" - path: - dependency: transitive - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - path_parsing: - dependency: transitive - description: - name: path_parsing - sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - path_provider: - dependency: transitive - description: - name: path_provider - sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e - url: "https://pub.dev" - source: hosted - version: "2.2.22" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: "6d13aece7b3f5c5a9731eaf553ff9dcbc2eff41087fd2df587fd0fed9a3eb0c4" - url: "https://pub.dev" - source: hosted - version: "2.5.1" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" - source: hosted - version: "2.3.0" - petitparser: - dependency: transitive - description: - name: petitparser - sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" - url: "https://pub.dev" - source: hosted - version: "7.0.1" - platform: - dependency: transitive - description: - name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" - source: hosted - version: "3.1.6" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" - pool: - dependency: transitive - description: - name: pool - sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" - url: "https://pub.dev" - source: hosted - version: "1.5.2" - posix: - dependency: transitive - description: - name: posix - sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" - url: "https://pub.dev" - source: hosted - version: "6.0.3" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - riverpod: - dependency: transitive - description: - name: riverpod - sha256: c406de02bff19d920b832bddfb8283548bfa05ce41c59afba57ce643e116aa59 - url: "https://pub.dev" - source: hosted - version: "3.0.3" - shelf: - dependency: transitive - description: - name: shelf - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 - url: "https://pub.dev" - source: hosted - version: "1.4.2" - shelf_packages_handler: - dependency: transitive - description: - name: shelf_packages_handler - sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - shelf_static: - dependency: transitive - description: - name: shelf_static - sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 - url: "https://pub.dev" - source: hosted - version: "1.1.3" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - source_map_stack_trace: - dependency: transitive - description: - name: source_map_stack_trace - sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b - url: "https://pub.dev" - source: hosted - version: "2.1.2" - source_maps: - dependency: transitive - description: - name: source_maps - sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" - url: "https://pub.dev" - source: hosted - version: "0.10.13" - source_span: - dependency: transitive - description: - name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.dev" - source: hosted - version: "1.10.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" - source: hosted - version: "1.12.1" - state_notifier: - dependency: transitive - description: - name: state_notifier - sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb - url: "https://pub.dev" - source: hosted - version: "1.0.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test: - dependency: transitive - description: - name: test - sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7" - url: "https://pub.dev" - source: hosted - version: "1.26.3" - test_api: - dependency: transitive - description: - name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 - url: "https://pub.dev" - source: hosted - version: "0.7.7" - test_core: - dependency: transitive - description: - name: test_core - sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0" - url: "https://pub.dev" - source: hosted - version: "0.6.12" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - url_launcher: - dependency: "direct main" - description: - name: url_launcher - sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 - url: "https://pub.dev" - source: hosted - version: "6.3.2" - url_launcher_android: - dependency: transitive - description: - name: url_launcher_android - sha256: "767344bf3063897b5cf0db830e94f904528e6dd50a6dfaf839f0abf509009611" - url: "https://pub.dev" - source: hosted - version: "6.3.28" - url_launcher_ios: - dependency: transitive - description: - name: url_launcher_ios - sha256: cfde38aa257dae62ffe79c87fab20165dfdf6988c1d31b58ebf59b9106062aad - url: "https://pub.dev" - source: hosted - version: "6.3.6" - url_launcher_linux: - dependency: transitive - description: - name: url_launcher_linux - sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a - url: "https://pub.dev" - source: hosted - version: "3.2.2" - url_launcher_macos: - dependency: transitive - description: - name: url_launcher_macos - sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18" - url: "https://pub.dev" - source: hosted - version: "3.2.5" - url_launcher_platform_interface: - dependency: transitive - description: - name: url_launcher_platform_interface - sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - url_launcher_web: - dependency: transitive - description: - name: url_launcher_web - sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - url_launcher_windows: - dependency: transitive - description: - name: url_launcher_windows - sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" - url: "https://pub.dev" - source: hosted - version: "3.1.5" - vector_graphics: - dependency: transitive - description: - name: vector_graphics - sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6 - url: "https://pub.dev" - source: hosted - version: "1.1.19" - vector_graphics_codec: - dependency: transitive - description: - name: vector_graphics_codec - sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" - url: "https://pub.dev" - source: hosted - version: "1.1.13" - vector_graphics_compiler: - dependency: transitive - description: - name: vector_graphics_compiler - sha256: d354a7ec6931e6047785f4db12a1f61ec3d43b207fc0790f863818543f8ff0dc - url: "https://pub.dev" - source: hosted - version: "1.1.19" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.dev" - source: hosted - version: "2.2.0" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" - url: "https://pub.dev" - source: hosted - version: "15.0.2" - watcher: - dependency: transitive - description: - name: watcher - sha256: "592ab6e2892f67760543fb712ff0177f4ec76c031f02f5b4ff8d3fc5eb9fb61a" - url: "https://pub.dev" - source: hosted - version: "1.1.4" - web: - dependency: transitive - description: - name: web - sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - web_socket: - dependency: transitive - description: - name: web_socket - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 - url: "https://pub.dev" - source: hosted - version: "3.0.3" - webkit_inspection_protocol: - dependency: transitive - description: - name: webkit_inspection_protocol - sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" - url: "https://pub.dev" - source: hosted - version: "1.2.1" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - xml: - dependency: transitive - description: - name: xml - sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" - url: "https://pub.dev" - source: hosted - version: "6.6.1" - yaml: - dependency: transitive - description: - name: yaml - sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.dev" - source: hosted - version: "3.1.3" -sdks: - dart: ">=3.10.0 <4.0.0" - flutter: ">=3.35.0" diff --git a/apps/mobile/prototypes/client_mobile_application/pubspec.yaml b/apps/mobile/prototypes/client_mobile_application/pubspec.yaml deleted file mode 100644 index 0f69b66a..00000000 --- a/apps/mobile/prototypes/client_mobile_application/pubspec.yaml +++ /dev/null @@ -1,103 +0,0 @@ -name: client_app_mvp -description: "A new Flutter project." -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -# In Windows, build-name is used as the major, minor, and patch parts -# of the product and file versions while build-number is used as the build suffix. -version: 1.0.0+6 - -environment: - sdk: ^3.10.0 - -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. -dependencies: - flutter: - sdk: flutter - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.8 - go_router: ^17.0.0 - flutter_riverpod: ^3.0.3 - google_fonts: ^6.3.3 - intl: ^0.20.2 - lucide_icons: ^0.257.0 - flutter_svg: ^2.2.3 - fl_chart: ^1.1.1 - firebase_core: ^4.2.1 - url_launcher: ^6.3.2 - font_awesome_flutter: ^10.12.0 - -dev_dependencies: - flutter_test: - sdk: flutter - - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^6.0.0 - flutter_launcher_icons: ^0.14.4 - -flutter_launcher_icons: - android: "launcher_icon" - ios: true - image_path: "assets/logo.png" - remove_alpha_ios: true - -# 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: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - - assets: - - assets/logo.png - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/to/asset-from-package - - # To add custom fonts to your application, 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 from package dependencies, - # see https://flutter.dev/to/font-from-package diff --git a/apps/mobile/prototypes/client_mobile_application/test/widget_test.dart b/apps/mobile/prototypes/client_mobile_application/test/widget_test.dart deleted file mode 100644 index 5516c273..00000000 --- a/apps/mobile/prototypes/client_mobile_application/test/widget_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility in the flutter_test package. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:client_app_mvp/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const AppRoot()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} diff --git a/apps/mobile/prototypes/client_mobile_application/web/favicon.png b/apps/mobile/prototypes/client_mobile_application/web/favicon.png deleted file mode 100644 index 8aaa46ac1ae21512746f852a42ba87e4165dfdd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM diff --git a/apps/mobile/prototypes/client_mobile_application/web/icons/Icon-192.png b/apps/mobile/prototypes/client_mobile_application/web/icons/Icon-192.png deleted file mode 100644 index b749bfef07473333cf1dd31e9eed89862a5d52aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5292 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 diff --git a/apps/mobile/prototypes/client_mobile_application/web/icons/Icon-512.png b/apps/mobile/prototypes/client_mobile_application/web/icons/Icon-512.png deleted file mode 100644 index 88cfd48dff1169879ba46840804b412fe02fefd6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8252 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 diff --git a/apps/mobile/prototypes/client_mobile_application/web/icons/Icon-maskable-192.png b/apps/mobile/prototypes/client_mobile_application/web/icons/Icon-maskable-192.png deleted file mode 100644 index eb9b4d76e525556d5d89141648c724331630325d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5594 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 X>c!)3PgKfL&lX^$Z>Cpu&6)6jvi^Z! diff --git a/apps/mobile/prototypes/client_mobile_application/web/icons/Icon-maskable-512.png b/apps/mobile/prototypes/client_mobile_application/web/icons/Icon-maskable-512.png deleted file mode 100644 index d69c56691fbdb0b7efa65097c7cc1edac12a6d3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20998 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 MPgg&ebxsLQ025IeI{*Lx diff --git a/apps/mobile/prototypes/client_mobile_application/web/index.html b/apps/mobile/prototypes/client_mobile_application/web/index.html deleted file mode 100644 index d0a2ce87..00000000 --- a/apps/mobile/prototypes/client_mobile_application/web/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - client_app_mvp - - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/web/manifest.json b/apps/mobile/prototypes/client_mobile_application/web/manifest.json deleted file mode 100644 index 14ca16c9..00000000 --- a/apps/mobile/prototypes/client_mobile_application/web/manifest.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "client_app_mvp", - "short_name": "client_app_mvp", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "icons/Icon-maskable-192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "icons/Icon-maskable-512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - } - ] -} diff --git a/apps/mobile/prototypes/client_mobile_application/windows/.gitignore b/apps/mobile/prototypes/client_mobile_application/windows/.gitignore deleted file mode 100644 index d492d0d9..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -flutter/ephemeral/ - -# Visual Studio user-specific files. -*.suo -*.user -*.userosscache -*.sln.docstates - -# Visual Studio build-related files. -x64/ -x86/ - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ diff --git a/apps/mobile/prototypes/client_mobile_application/windows/CMakeLists.txt b/apps/mobile/prototypes/client_mobile_application/windows/CMakeLists.txt deleted file mode 100644 index 369636d4..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/CMakeLists.txt +++ /dev/null @@ -1,108 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.14) -project(client_app_mvp LANGUAGES CXX) - -# The name of the executable created for the application. Change this to change -# the on-disk name of your application. -set(BINARY_NAME "client_app_mvp") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(VERSION 3.14...3.25) - -# Define build configuration option. -get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(IS_MULTICONFIG) - set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" - CACHE STRING "" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") - endif() -endif() -# Define settings for the Profile build mode. -set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") -set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") -set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") -set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") - -# Use Unicode for all projects. -add_definitions(-DUNICODE -D_UNICODE) - -# Compilation settings that should be applied to most targets. -# -# Be cautious about adding new options here, as plugins use this function by -# default. In most cases, you should add new options to specific targets instead -# of modifying this function. -function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_17) - target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") - target_compile_options(${TARGET} PRIVATE /EHsc) - target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") - target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") -endfunction() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# Application build; see runner/CMakeLists.txt. -add_subdirectory("runner") - - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# Support files are copied into place next to the executable, so that it can -# run in place. This is done instead of making a separate bundle (as on Linux) -# so that building and running from within Visual Studio will work. -set(BUILD_BUNDLE_DIR "$") -# Make the "install" step default, as it's required to run. -set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() - -set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") -set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") - -install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() - -# Copy the native assets provided by the build.dart from all packages. -set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") -install(DIRECTORY "${NATIVE_ASSETS_DIR}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -# Fully re-copy the assets directory on each build to avoid having stale files -# from a previous install. -set(FLUTTER_ASSET_DIR_NAME "flutter_assets") -install(CODE " - file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") - " COMPONENT Runtime) -install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) - -# Install the AOT library on non-Debug builds only. -install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - CONFIGURATIONS Profile;Release - COMPONENT Runtime) diff --git a/apps/mobile/prototypes/client_mobile_application/windows/flutter/CMakeLists.txt b/apps/mobile/prototypes/client_mobile_application/windows/flutter/CMakeLists.txt deleted file mode 100644 index 903f4899..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/flutter/CMakeLists.txt +++ /dev/null @@ -1,109 +0,0 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.14) - -set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") - -# Configuration provided via flutter tool. -include(${EPHEMERAL_DIR}/generated_config.cmake) - -# TODO: Move the rest of this into files in ephemeral. See -# https://github.com/flutter/flutter/issues/57146. -set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") - -# Set fallback configurations for older versions of the flutter tool. -if (NOT DEFINED FLUTTER_TARGET_PLATFORM) - set(FLUTTER_TARGET_PLATFORM "windows-x64") -endif() - -# === Flutter Library === -set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") - -# Published to parent scope for install step. -set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) -set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) -set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) -set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) - -list(APPEND FLUTTER_LIBRARY_HEADERS - "flutter_export.h" - "flutter_windows.h" - "flutter_messenger.h" - "flutter_plugin_registrar.h" - "flutter_texture_registrar.h" -) -list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") -add_library(flutter INTERFACE) -target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" -) -target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") -add_dependencies(flutter flutter_assemble) - -# === Wrapper === -list(APPEND CPP_WRAPPER_SOURCES_CORE - "core_implementations.cc" - "standard_codec.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") -list(APPEND CPP_WRAPPER_SOURCES_PLUGIN - "plugin_registrar.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") -list(APPEND CPP_WRAPPER_SOURCES_APP - "flutter_engine.cc" - "flutter_view_controller.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") - -# Wrapper sources needed for a plugin. -add_library(flutter_wrapper_plugin STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} -) -apply_standard_settings(flutter_wrapper_plugin) -set_target_properties(flutter_wrapper_plugin PROPERTIES - POSITION_INDEPENDENT_CODE ON) -set_target_properties(flutter_wrapper_plugin PROPERTIES - CXX_VISIBILITY_PRESET hidden) -target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) -target_include_directories(flutter_wrapper_plugin PUBLIC - "${WRAPPER_ROOT}/include" -) -add_dependencies(flutter_wrapper_plugin flutter_assemble) - -# Wrapper sources needed for the runner. -add_library(flutter_wrapper_app STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_APP} -) -apply_standard_settings(flutter_wrapper_app) -target_link_libraries(flutter_wrapper_app PUBLIC flutter) -target_include_directories(flutter_wrapper_app PUBLIC - "${WRAPPER_ROOT}/include" -) -add_dependencies(flutter_wrapper_app flutter_assemble) - -# === Flutter tool backend === -# _phony_ is a non-existent file to force this command to run every time, -# since currently there's no way to get a full input/output list from the -# flutter tool. -set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") -set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) -add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} - ${PHONY_OUTPUT} - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - ${FLUTTER_TARGET_PLATFORM} $ - VERBATIM -) -add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} -) diff --git a/apps/mobile/prototypes/client_mobile_application/windows/flutter/generated_plugin_registrant.cc b/apps/mobile/prototypes/client_mobile_application/windows/flutter/generated_plugin_registrant.cc deleted file mode 100644 index ec8e8d45..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,17 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include -#include - -void RegisterPlugins(flutter::PluginRegistry* registry) { - FirebaseCorePluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); - UrlLauncherWindowsRegisterWithRegistrar( - registry->GetRegistrarForPlugin("UrlLauncherWindows")); -} diff --git a/apps/mobile/prototypes/client_mobile_application/windows/flutter/generated_plugin_registrant.h b/apps/mobile/prototypes/client_mobile_application/windows/flutter/generated_plugin_registrant.h deleted file mode 100644 index dc139d85..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void RegisterPlugins(flutter::PluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/apps/mobile/prototypes/client_mobile_application/windows/flutter/generated_plugins.cmake b/apps/mobile/prototypes/client_mobile_application/windows/flutter/generated_plugins.cmake deleted file mode 100644 index 02d26c31..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/flutter/generated_plugins.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - firebase_core - url_launcher_windows -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/apps/mobile/prototypes/client_mobile_application/windows/runner/CMakeLists.txt b/apps/mobile/prototypes/client_mobile_application/windows/runner/CMakeLists.txt deleted file mode 100644 index 394917c0..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/runner/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -cmake_minimum_required(VERSION 3.14) -project(runner LANGUAGES CXX) - -# Define the application target. To change its name, change BINARY_NAME in the -# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer -# work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} WIN32 - "flutter_window.cpp" - "main.cpp" - "utils.cpp" - "win32_window.cpp" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" - "Runner.rc" - "runner.exe.manifest" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add preprocessor definitions for the build version. -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") - -# Disable Windows macros that collide with C++ standard library functions. -target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") - -# Add dependency libraries and include directories. Add any application-specific -# dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) -target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") -target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/apps/mobile/prototypes/client_mobile_application/windows/runner/Runner.rc b/apps/mobile/prototypes/client_mobile_application/windows/runner/Runner.rc deleted file mode 100644 index c6f91c08..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/runner/Runner.rc +++ /dev/null @@ -1,121 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#pragma code_page(65001) -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_APP_ICON ICON "resources\\app_icon.ico" - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) -#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD -#else -#define VERSION_AS_NUMBER 1,0,0,0 -#endif - -#if defined(FLUTTER_VERSION) -#define VERSION_AS_STRING FLUTTER_VERSION -#else -#define VERSION_AS_STRING "1.0.0" -#endif - -VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_AS_NUMBER - PRODUCTVERSION VERSION_AS_NUMBER - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "com.example" "\0" - VALUE "FileDescription", "client_app_mvp" "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "client_app_mvp" "\0" - VALUE "LegalCopyright", "Copyright (C) 2025 com.example. All rights reserved." "\0" - VALUE "OriginalFilename", "client_app_mvp.exe" "\0" - VALUE "ProductName", "client_app_mvp" "\0" - VALUE "ProductVersion", VERSION_AS_STRING "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END -END - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/apps/mobile/prototypes/client_mobile_application/windows/runner/flutter_window.cpp b/apps/mobile/prototypes/client_mobile_application/windows/runner/flutter_window.cpp deleted file mode 100644 index 955ee303..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/runner/flutter_window.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "flutter_window.h" - -#include - -#include "flutter/generated_plugin_registrant.h" - -FlutterWindow::FlutterWindow(const flutter::DartProject& project) - : project_(project) {} - -FlutterWindow::~FlutterWindow() {} - -bool FlutterWindow::OnCreate() { - if (!Win32Window::OnCreate()) { - return false; - } - - RECT frame = GetClientArea(); - - // The size here must match the window dimensions to avoid unnecessary surface - // creation / destruction in the startup path. - flutter_controller_ = std::make_unique( - frame.right - frame.left, frame.bottom - frame.top, project_); - // Ensure that basic setup of the controller was successful. - if (!flutter_controller_->engine() || !flutter_controller_->view()) { - return false; - } - RegisterPlugins(flutter_controller_->engine()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); - - flutter_controller_->engine()->SetNextFrameCallback([&]() { - this->Show(); - }); - - // Flutter can complete the first frame before the "show window" callback is - // registered. The following call ensures a frame is pending to ensure the - // window is shown. It is a no-op if the first frame hasn't completed yet. - flutter_controller_->ForceRedraw(); - - return true; -} - -void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - flutter_controller_ = nullptr; - } - - Win32Window::OnDestroy(); -} - -LRESULT -FlutterWindow::MessageHandler(HWND hwnd, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opportunity to handle window messages. - if (flutter_controller_) { - std::optional result = - flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, - lparam); - if (result) { - return *result; - } - } - - switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; - } - - return Win32Window::MessageHandler(hwnd, message, wparam, lparam); -} diff --git a/apps/mobile/prototypes/client_mobile_application/windows/runner/flutter_window.h b/apps/mobile/prototypes/client_mobile_application/windows/runner/flutter_window.h deleted file mode 100644 index 6da0652f..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/runner/flutter_window.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef RUNNER_FLUTTER_WINDOW_H_ -#define RUNNER_FLUTTER_WINDOW_H_ - -#include -#include - -#include - -#include "win32_window.h" - -// A window that does nothing but host a Flutter view. -class FlutterWindow : public Win32Window { - public: - // Creates a new FlutterWindow hosting a Flutter view running |project|. - explicit FlutterWindow(const flutter::DartProject& project); - virtual ~FlutterWindow(); - - protected: - // Win32Window: - bool OnCreate() override; - void OnDestroy() override; - LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept override; - - private: - // The project to run. - flutter::DartProject project_; - - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; -}; - -#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/apps/mobile/prototypes/client_mobile_application/windows/runner/main.cpp b/apps/mobile/prototypes/client_mobile_application/windows/runner/main.cpp deleted file mode 100644 index 0ccff5c2..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/runner/main.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -#include "flutter_window.h" -#include "utils.h" - -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } - - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - - flutter::DartProject project(L"data"); - - std::vector command_line_arguments = - GetCommandLineArguments(); - - project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); - - FlutterWindow window(project); - Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); - if (!window.Create(L"client_app_mvp", origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); - - ::MSG msg; - while (::GetMessage(&msg, nullptr, 0, 0)) { - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - } - - ::CoUninitialize(); - return EXIT_SUCCESS; -} diff --git a/apps/mobile/prototypes/client_mobile_application/windows/runner/resource.h b/apps/mobile/prototypes/client_mobile_application/windows/runner/resource.h deleted file mode 100644 index 66a65d1e..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/runner/resource.h +++ /dev/null @@ -1,16 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Runner.rc -// -#define IDI_APP_ICON 101 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/apps/mobile/prototypes/client_mobile_application/windows/runner/resources/app_icon.ico b/apps/mobile/prototypes/client_mobile_application/windows/runner/resources/app_icon.ico deleted file mode 100644 index c04e20caf6370ebb9253ad831cc31de4a9c965f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33772 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 diff --git a/apps/mobile/prototypes/client_mobile_application/windows/runner/runner.exe.manifest b/apps/mobile/prototypes/client_mobile_application/windows/runner/runner.exe.manifest deleted file mode 100644 index 153653e8..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/runner/runner.exe.manifest +++ /dev/null @@ -1,14 +0,0 @@ - - - - - PerMonitorV2 - - - - - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/windows/runner/utils.cpp b/apps/mobile/prototypes/client_mobile_application/windows/runner/utils.cpp deleted file mode 100644 index 3a0b4651..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/runner/utils.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "utils.h" - -#include -#include -#include -#include - -#include - -void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); - } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } -} - -std::vector GetCommandLineArguments() { - // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. - int argc; - wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - if (argv == nullptr) { - return std::vector(); - } - - std::vector command_line_arguments; - - // Skip the first argument as it's the binary name. - for (int i = 1; i < argc; i++) { - command_line_arguments.push_back(Utf8FromUtf16(argv[i])); - } - - ::LocalFree(argv); - - return command_line_arguments; -} - -std::string Utf8FromUtf16(const wchar_t* utf16_string) { - if (utf16_string == nullptr) { - return std::string(); - } - unsigned int target_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr) - -1; // remove the trailing null character - int input_length = (int)wcslen(utf16_string); - std::string utf8_string; - if (target_length == 0 || target_length > utf8_string.max_size()) { - return utf8_string; - } - utf8_string.resize(target_length); - int converted_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - input_length, utf8_string.data(), target_length, nullptr, nullptr); - if (converted_length == 0) { - return std::string(); - } - return utf8_string; -} diff --git a/apps/mobile/prototypes/client_mobile_application/windows/runner/utils.h b/apps/mobile/prototypes/client_mobile_application/windows/runner/utils.h deleted file mode 100644 index 3879d547..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/runner/utils.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef RUNNER_UTILS_H_ -#define RUNNER_UTILS_H_ - -#include -#include - -// Creates a console for the process, and redirects stdout and stderr to -// it for both the runner and the Flutter library. -void CreateAndAttachConsole(); - -// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string -// encoded in UTF-8. Returns an empty std::string on failure. -std::string Utf8FromUtf16(const wchar_t* utf16_string); - -// Gets the command line arguments passed in as a std::vector, -// encoded in UTF-8. Returns an empty std::vector on failure. -std::vector GetCommandLineArguments(); - -#endif // RUNNER_UTILS_H_ diff --git a/apps/mobile/prototypes/client_mobile_application/windows/runner/win32_window.cpp b/apps/mobile/prototypes/client_mobile_application/windows/runner/win32_window.cpp deleted file mode 100644 index 60608d0f..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/runner/win32_window.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include "win32_window.h" - -#include -#include - -#include "resource.h" - -namespace { - -/// Window attribute that enables dark mode window decorations. -/// -/// Redefined in case the developer's machine has a Windows SDK older than -/// version 10.0.22000.0. -/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute -#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE -#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 -#endif - -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; - -/// Registry key for app theme preference. -/// -/// A value of 0 indicates apps should use dark mode. A non-zero or missing -/// value indicates apps should use light mode. -constexpr const wchar_t kGetPreferredBrightnessRegKey[] = - L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; -constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; - -// The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; - -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); - -// Scale helper to convert logical scaler values to physical using passed in -// scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} - -// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. -// This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { - return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - } - FreeLibrary(user32_module); -} - -} // namespace - -// Manages the Win32Window's window class registration. -class WindowClassRegistrar { - public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registrar instance. - static WindowClassRegistrar* GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); - } - return instance_; - } - - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t* GetWindowClass(); - - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); - - private: - WindowClassRegistrar() = default; - - static WindowClassRegistrar* instance_; - - bool class_registered_ = false; -}; - -WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; - -const wchar_t* WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; -} - -void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; -} - -Win32Window::Win32Window() { - ++g_active_window_count; -} - -Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); -} - -bool Win32Window::Create(const std::wstring& title, - const Point& origin, - const Size& size) { - Destroy(); - - const wchar_t* window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); - - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; - - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); - - if (!window) { - return false; - } - - UpdateTheme(window); - - return OnCreate(); -} - -bool Win32Window::Show() { - return ShowWindow(window_handle_, SW_SHOWNORMAL); -} - -// static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window* that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } - - return DefWindowProc(window, message, wparam, lparam); -} - -LRESULT -Win32Window::MessageHandler(HWND hwnd, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: { - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; - } - - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - - case WM_DWMCOLORIZATIONCOLORCHANGED: - UpdateTheme(hwnd); - return 0; - } - - return DefWindowProc(window_handle_, message, wparam, lparam); -} - -void Win32Window::Destroy() { - OnDestroy(); - - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } -} - -Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); -} - -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame = GetClientArea(); - - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); - - SetFocus(child_content_); -} - -RECT Win32Window::GetClientArea() { - RECT frame; - GetClientRect(window_handle_, &frame); - return frame; -} - -HWND Win32Window::GetHandle() { - return window_handle_; -} - -void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; -} - -bool Win32Window::OnCreate() { - // No-op; provided for subclasses. - return true; -} - -void Win32Window::OnDestroy() { - // No-op; provided for subclasses. -} - -void Win32Window::UpdateTheme(HWND const window) { - DWORD light_mode; - DWORD light_mode_size = sizeof(light_mode); - LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, - RRF_RT_REG_DWORD, nullptr, &light_mode, - &light_mode_size); - - if (result == ERROR_SUCCESS) { - BOOL enable_dark_mode = light_mode == 0; - DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, - &enable_dark_mode, sizeof(enable_dark_mode)); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/windows/runner/win32_window.h b/apps/mobile/prototypes/client_mobile_application/windows/runner/win32_window.h deleted file mode 100644 index e901dde6..00000000 --- a/apps/mobile/prototypes/client_mobile_application/windows/runner/win32_window.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef RUNNER_WIN32_WINDOW_H_ -#define RUNNER_WIN32_WINDOW_H_ - -#include - -#include -#include -#include - -// A class abstraction for a high DPI-aware Win32 Window. Intended to be -// inherited from by classes that wish to specialize with custom -// rendering and input handling -class Win32Window { - public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates a win32 window with |title| that is positioned and sized using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size this function will scale the inputted width and height as - // as appropriate for the default monitor. The window is invisible until - // |Show| is called. Returns true if the window was created successfully. - bool Create(const std::wstring& title, const Point& origin, const Size& size); - - // Show the current window. Returns true if the window was successfully shown. - bool Show(); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - // Return a RECT representing the bounds of the current client area. - RECT GetClientArea(); - - protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Called when CreateAndShow is called, allowing subclass window-related - // setup. Subclasses should return false if setup fails. - virtual bool OnCreate(); - - // Called when Destroy is called. - virtual void OnDestroy(); - - private: - friend class WindowClassRegistrar; - - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Retrieves a class instance pointer for |window| - static Win32Window* GetThisFromHandle(HWND const window) noexcept; - - // Update the window frame's theme to match the system theme. - static void UpdateTheme(HWND const window); - - bool quit_on_close_ = false; - - // window handle for top level window. - HWND window_handle_ = nullptr; - - // window handle for hosted content. - HWND child_content_ = nullptr; -}; - -#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/apps/mobile/prototypes/staff_mobile_application/.gitignore b/apps/mobile/prototypes/staff_mobile_application/.gitignore deleted file mode 100644 index 3820a95c..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/.gitignore +++ /dev/null @@ -1,45 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -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 -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ -/coverage/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release diff --git a/apps/mobile/prototypes/staff_mobile_application/.metadata b/apps/mobile/prototypes/staff_mobile_application/.metadata deleted file mode 100644 index 2c6187b3..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/.metadata +++ /dev/null @@ -1,45 +0,0 @@ -# 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: "b45fa18946ecc2d9b4009952c636ba7e2ffbb787" - channel: "stable" - -project_type: app - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - platform: android - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - platform: ios - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - platform: linux - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - platform: macos - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - platform: web - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - platform: windows - create_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - base_revision: b45fa18946ecc2d9b4009952c636ba7e2ffbb787 - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/apps/mobile/prototypes/staff_mobile_application/README.md b/apps/mobile/prototypes/staff_mobile_application/README.md deleted file mode 100644 index 240238ed..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# staff_app_mvp - -A new Flutter project. - -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. diff --git a/apps/mobile/prototypes/staff_mobile_application/analysis_options.yaml b/apps/mobile/prototypes/staff_mobile_application/analysis_options.yaml deleted file mode 100644 index 0d290213..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/analysis_options.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/apps/mobile/prototypes/staff_mobile_application/android/.gitignore b/apps/mobile/prototypes/staff_mobile_application/android/.gitignore deleted file mode 100644 index be3943c9..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/android/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java -.cxx/ - -# Remember to never publicly share your keystore. -# See https://flutter.dev/to/reference-keystore -key.properties -**/*.keystore -**/*.jks diff --git a/apps/mobile/prototypes/staff_mobile_application/android/app/29a493751_PNG3Krow.png b/apps/mobile/prototypes/staff_mobile_application/android/app/29a493751_PNG3Krow.png deleted file mode 100644 index ef04350b533cf3300ab1a0b957a7a76b0b744143..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47063 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 - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/AndroidManifest.xml b/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index 02a7e068..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/kotlin/com/example/staff_app_mvp/MainActivity.kt b/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/kotlin/com/example/staff_app_mvp/MainActivity.kt deleted file mode 100644 index 861d0ce3..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/kotlin/com/example/staff_app_mvp/MainActivity.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.example.staff_app_mvp - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity : FlutterActivity() diff --git a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/drawable-v21/launch_background.xml b/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/drawable-v21/launch_background.xml deleted file mode 100644 index f74085f3..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/drawable-v21/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/drawable/launch_background.xml b/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 304732f8..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 3091831ac4f4fbf5241c2a22316f674316ab29e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2123 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 diff --git a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 9fac3fb8f6a937db04ba2279198987b6914270c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1422 zcmV;91#$X`P)vg9J($zQM5oSdnVW2GI%mw>dkMNn%(ld6 zjGIg57NTz24CSfF+o%i`S1WB5L=Y$x!P3(09M{_(Z(C3T-D1C_={?VTe)s$z=U!p( z^w|ddk0rGC0!AwbfW74au(uol_Lc*{-f{rgTaO-qyPFW9k9onv-30@8b!ctZps#;$ zY*se{jR;_Jus2pLNkDey6vRYLgp-qiYcm)OkSV%QTBE=((o49|bZacv%act2p|b$* zt`pp6>axVkvw%dHYTBZ+}P02Eg?WBqn1G6k7r((zMQ%pZHXWpt=aCUNnkCz)ZtW2>D zFh4DlI;**qEo!XWb`0k)^Bq*tqQ=gB)!1|B9Co~siRC%*TpMxrueU8kL(@U1ZuT(a zavZ}QQIqQGMt=o5aH#Ap|<}UI+J%Jl- zy>!csBIdOH^*Qtb81+PC03sjv;sa&tyNq_F*yriPM6aMrpb1ffrBI-7|pw1sCwv>Qt^yk{(3?NG4BD zGKJ;A%bcF#( znl=f(-fl>Yn?xauDz8yO)34~{I$ zcp5cGbf`RgeN+JDbt>rfLtG*mTfGc zak`>jg_3H;r~pVbsy^QWagyZ&p}A9*R5#OyW{f)K(Wj{L8uWV0-=KM!m~5r_S!1*+ ztdLs-XzS3>JYy6|mc;SnrUdf(+R8;^{z_T+Pwf6+Lng2OWHZvl3wKX{jK;ftbZ|yF`v_QDtdIcrg3?xfAix){Iqi^!b5%O zvHXiYXQ*%7ulmND_~g3^Yg>?tU6otZDa; zbvStRPXzc)fLzsOG4`8l+&-(2C^FKc2{9R4W@D~L@4L`{O%4Ei%K>0-IRNY}2Y|ih c0I;|I2K%Yy!Vz@%*Z=?k07*qoM6N<$f*y0J_y7O^ diff --git a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 7bd61725c5fb6088c56f8120135f9d8522eecfab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2795 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 L_0`H%P~rarryYa> diff --git a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 6fa64c699e639e5460bdb22ae8fb2ee752bd17e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5314 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 - - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/values/styles.xml b/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/values/styles.xml deleted file mode 100644 index cb1ef880..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/android/app/src/profile/AndroidManifest.xml b/apps/mobile/prototypes/staff_mobile_application/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index 399f6981..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/android/build.gradle.kts b/apps/mobile/prototypes/staff_mobile_application/android/build.gradle.kts deleted file mode 100644 index dbee657b..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/android/build.gradle.kts +++ /dev/null @@ -1,24 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -val newBuildDir: Directory = - rootProject.layout.buildDirectory - .dir("../../build") - .get() -rootProject.layout.buildDirectory.value(newBuildDir) - -subprojects { - val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) - project.layout.buildDirectory.value(newSubprojectBuildDir) -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean") { - delete(rootProject.layout.buildDirectory) -} diff --git a/apps/mobile/prototypes/staff_mobile_application/android/gradle.properties b/apps/mobile/prototypes/staff_mobile_application/android/gradle.properties deleted file mode 100644 index fbee1d8c..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/android/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError -android.useAndroidX=true diff --git a/apps/mobile/prototypes/staff_mobile_application/android/gradle/wrapper/gradle-wrapper.properties b/apps/mobile/prototypes/staff_mobile_application/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index e4ef43fb..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip diff --git a/apps/mobile/prototypes/staff_mobile_application/android/settings.gradle.kts b/apps/mobile/prototypes/staff_mobile_application/android/settings.gradle.kts deleted file mode 100644 index e4e86fb6..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/android/settings.gradle.kts +++ /dev/null @@ -1,27 +0,0 @@ -pluginManagement { - val flutterSdkPath = - run { - val properties = java.util.Properties() - file("local.properties").inputStream().use { properties.load(it) } - val flutterSdkPath = properties.getProperty("flutter.sdk") - require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } - flutterSdkPath - } - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.11.1" apply false - id("org.jetbrains.kotlin.android") version "2.2.20" apply false - id("com.google.gms.google-services") version "4.4.2" apply false -} - -include(":app") diff --git a/apps/mobile/prototypes/staff_mobile_application/assets/logo.png b/apps/mobile/prototypes/staff_mobile_application/assets/logo.png deleted file mode 100644 index b1dd25b7f2ea36ac5210fab2851c943c7e6f5ec6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8790 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 diff --git a/apps/mobile/prototypes/staff_mobile_application/comparation_v2_v3.md b/apps/mobile/prototypes/staff_mobile_application/comparation_v2_v3.md deleted file mode 100644 index 48e7b853..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/comparation_v2_v3.md +++ /dev/null @@ -1,304 +0,0 @@ -# Comparación de Estructura de Datos: v2 vs. v3 (Análisis Detallado) - -Este documento detalla las diferencias y similitudes en el uso de `Map` y `List>` entre la versión 2 (descrita en `mock_staff_app_v2.md`) y la versión 3 (código actual). - -## Resumen Ejecutivo - -El análisis de la v3 revela dos puntos clave: -1. **Persistencia del uso de `Map`**: La gran mayoría de las estructuras de datos para mocks y estado de la UI siguen siendo `Map`, muy similares a las de la v2. La inconsistencia y duplicación de datos entre diferentes pantallas sigue siendo un problema. -2. **Inicio de la Refactorización a Modelos**: La introducción de la clase `Shift` en `lib/models/shift.dart` y su uso en `clock_in_screen.dart` marca el primer paso concreto para abandonar el patrón de `Map` en favor de objetos fuertemente tipados, tal como se recomendó. - -Este informe primero catalogará todas las estructuras `Map` encontradas en la v3 y luego las comparará con el análisis de la v2. - ---- - -## 1. Análisis de Estructuras `Map` en v3 - -A continuación se listan las estructuras encontradas en el código actual del proyecto. - -### `lib/screens/auth/profile_setup_screen.dart` - -1. **Variable**: `static const List> _steps` - * **Propósito**: Define los pasos del wizard de creación de perfil. - * **Estructura de cada elemento**: - ```json - { - "id": String, - "title": String, - "icon": IconData - } - ``` - -### `lib/screens/worker/availability_screen.dart` - -1. **Variable**: `final List> _timeSlots` - * **Propósito**: Define las propiedades de los rangos horarios seleccionables (mañana, tarde, noche). - * **Estructura de cada elemento**: - ```json - { - "id": String, - "label": String, - "time": String, - "icon": IconData, - "bg": Color, - "iconColor": Color - } - ``` - -### `lib/screens/worker/benefits_screen.dart` - -1. **Variable**: `final List> _benefitsData` - * **Propósito**: Mock data para los beneficios del trabajador. - * **Estructura de cada elemento**: - ```json - { - "id": String, - "title": String, - "current": int, - "total": int, - "color": Color, - "description": String, - "history": List>, // Anidado - "requestLabel": String, - "notice": String? - } - ``` - * **Estructura anidada de `history`**: - ```json - { - "date": String, - "status": String - } - ``` -2. **Parámetro de Función**: `void _handleRequest(Map benefit)` - * **Propósito**: Maneja la acción de solicitar un beneficio. - * **Estructura**: La misma que un elemento de `_benefitsData`. -3. **Parámetro de Widget**: `final Map benefit` (en `_BenefitCard`) - * **Propósito**: Pasa los datos de un beneficio al widget de tarjeta. - * **Estructura**: La misma que un elemento de `_benefitsData`. - -### `lib/screens/worker/clock_in_screen.dart` - -1. **Variable**: `final List> _recentActivity` - * **Propósito**: Mock data para la lista de actividad reciente de fichajes. - * **Estructura de cada elemento**: - ```json - { - "date": DateTime, - "start": String, - "end": String, - "hours": String - } - ``` - -### `lib/screens/worker/earnings_screen.dart` - -1. **Variable**: `final List> _recentPayments` - * **Propósito**: Mock data para la lista de pagos recientes. - * **Estructura de cada elemento**: - ```json - { - "date": String, - "amount": double, - "shifts": int, - "status": String - } - ``` - -### `lib/screens/worker/payments_screen.dart` - -1. **Variable**: `final List> _recentPayments` - * **Propósito**: Mock data para el historial de pagos. - * **Estructura de cada elemento**: - ```json - { - "date": String, - "title": String, - "location": String, - "address": String, - "workedTime": String, - "amount": double, - "status": String, - "hours": int, - "rate": int // Inconsistencia, debería ser double - } - ``` - -### `lib/screens/worker/worker_profile_screen.dart` - -1. **Variable**: `final Map _user` - * **Propósito**: Mock data para la información básica del usuario. - * **Estructura**: - ```json - { - "full_name": String, - "email": String - } - ``` -2. **Variable**: `final Map _profile` - * **Propósito**: Mock data para las estadísticas del perfil del trabajador. - * **Estructura**: - ```json - { - "level": String, - "photo_url": String?, - "total_shifts": int, - "average_rating": double, - "on_time_rate": int, - "no_show_count": int, - "cancellation_count": int, - "reliability_score": int, - "phone": String, - "skills": List - } - ``` - -### `lib/screens/worker/worker_profile/compliance/certificates_screen.dart` - -1. **Variable**: `final List> _certificates` - * **Propósito**: Mock data para los certificados de cumplimiento. - * **Estructura de cada elemento**: - ```json - { - "id": String, - "name": String, - "icon": IconData, - "color": Color, - "description": String, - "status": String, - "expiry": String? // ISO 8601 - } - ``` -2. **Parámetro de Función/Widget**: Se usa `Map cert` en `_buildCertificateCard` y `_showUploadModal`. - -### `lib/screens/worker/worker_profile/level_up/krow_university_screen.dart` - -1. **Variable**: `final Map _profile` - * **Propósito**: Mock data para el perfil dentro de Krow University. **Nota: Es inconsistente con el `_profile` de `worker_profile_screen.dart`**. - * **Estructura**: - ```json - { - "level": String, - "xp": int, - "badges": List - } - ``` -2. **Variable**: `final List> _levels` - * **Propósito**: Define los distintos niveles de Krower. - * **Estructura de cada elemento**: - ```json - { - "name": String, - "xpRequired": int, - "icon": IconData, - "colors": List - } - ``` -3. **Variable**: `final List> _categories` - * **Propósito**: Define las categorías de los cursos. - * **Estructura de cada elemento**: - ```json - { - "id": String, - "label": String, - "icon": IconData - } - ``` -4. **Variable**: `final List> _courses` - * **Propósito**: Mock data para la lista de cursos. - * **Estructura de cada elemento**: - ```json - { - "id": String, - "title": String, - "description": String, - "category": String, - "duration_minutes": int, - "xp_reward": int, - "level_required": String, - "is_certification": bool, - "progress_percent": int, - "completed": bool - } - ``` - -### `lib/services/mock_service.dart` - -1. **Parámetro de Función**: `Future createWorkerProfile(Map data)` - * **Propósito**: Simula la creación de un perfil. - * **Estructura esperada (inferida de `profile_setup_screen.dart`)**: - ```json - { - "full_name": String, - "bio": String, - "preferred_locations": List, - "max_distance_miles": double, - "skills": List, - "industries": List - } - ``` - -### `lib/widgets/shift_card.dart` - -1. **Tipo de Retorno de Función**: `Map _calculateDuration()` - * **Propósito**: Calcula la duración de un turno. - * **Estructura devuelta**: - ```json - { - "hours": int, - "breakTime": String - } - ``` - ---- - -## 2. Comparación v2 vs. v3 - -### A. Nuevas Estructuras en v3 -- `lib/screens/worker/worker_profile/level_up/krow_university_screen.dart`: - - `_levels`: Define los niveles de Krower. No estaba en el análisis v2. - - `_profile`: Una nueva versión **inconsistente** del perfil del usuario, específica para esta pantalla. -- `lib/screens/worker/earnings_screen.dart`: - - `_recentPayments`: Una nueva lista de pagos, diferente en estructura a la de `payments_screen.dart`. - -### B. Estructuras Sin Cambios (o muy similares) -Las siguientes estructuras son prácticamente idénticas a las descritas en el análisis de la v2: -- `_steps` en `profile_setup_screen.dart`. -- `_timeSlots` en `availability_screen.dart`. -- `_benefitsData` en `benefits_screen.dart`. -- `_user` y `_profile` en `worker_profile_screen.dart`. -- `_certificates` en `certificates_screen.dart`. -- El parámetro de `createWorkerProfile` en `mock_service.dart`. -- El retorno de `_calculateDuration` en `shift_card.dart`. -- `_recentActivity` en `clock_in_screen.dart`. -- `_recentPayments` en `payments_screen.dart` (aunque es similar a la de `earnings_screen`, su estructura es más detallada y consistente con v2). - -### C. Estructuras Modificadas o con Nuevos Hallazgos -- `krow_university_screen.dart` (`_courses`, `_categories`): El análisis de la v2 mencionaba este archivo pero no detallaba estas estructuras. Ahora están formalmente documentadas. -- La **inconsistencia** del objeto `_profile` es más evidente ahora, con dos versiones diferentes en `worker_profile_screen.dart` y `krow_university_screen.dart`. - -### D. Estructuras Eliminadas / Reemplazadas -Este es el cambio más importante: - -- **Reemplazo conceptual de `Map` por Clases**: El uso de `Map` para representar un turno (`shift`) ha sido reemplazado por una clase. - - **ANTES (v2)**: Archivos como `payments_screen.dart` o `time_card_screen.dart` tenían su propia definición de `Map` para un turno/pago. - - **AHORA (v3)**: Se ha introducido `lib/models/shift.dart` con las clases `Shift` y `ShiftManager`. - - **EVIDENCIA**: El archivo `lib/screens/worker/clock_in_screen.dart` ya no usa un `Map` para el turno del día, sino una instancia de la nueva clase: - ```dart - final Shift? _todayShift = Shift(...); - ``` - Esto demuestra el inicio de la migración hacia modelos tipados. - ---- - -## Conclusión y Recomendación - -La v3 del proyecto sigue dependiendo masivamente de `Map` para datos de mock y estado, con casi todas las estructuras de la v2 todavía presentes. Las **inconsistencias** (ej. múltiples versiones de `_profile`, `_recentPayments`) siguen siendo un riesgo técnico. - -Sin embargo, la introducción de `Shift` y `ShiftManager` es un **avance arquitectónico muy positivo**. Muestra la dirección correcta para el proyecto. - -**Mi recomendación sigue siendo la misma, pero ahora con un plan de acción más claro:** -1. **Priorizar la unificación de `Profile`/`User`**: Crear una clase `UserProfile` en `lib/models/` que unifique las diferentes versiones de `_profile` y `_user`. -2. **Migrar `_recentPayments` y `_timesheets`**: Refactorizar `payments_screen.dart`, `earnings_screen.dart` y `time_card_screen.dart` para que usen `List` o una nueva clase `Payment` si es necesario, en lugar de `List>`. -3. **Continuar la Modelización**: Progresivamente, convertir las demás estructuras de `Map` (`Benefit`, `Certificate`, `Course`, etc.) en sus propias clases dentro de `lib/models/`. -4. **Limpiar Mocks**: Una vez que los modelos existan, los mocks deben ser instancias de estas clases, no `Map`s, para garantizar la consistencia en toda la aplicación. \ No newline at end of file diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/.gitignore b/apps/mobile/prototypes/staff_mobile_application/ios/.gitignore deleted file mode 100644 index 7a7f9873..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -**/dgph -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/ephemeral/ -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Flutter/AppFrameworkInfo.plist b/apps/mobile/prototypes/staff_mobile_application/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index 1dc6cf76..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 13.0 - - diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Flutter/Debug.xcconfig b/apps/mobile/prototypes/staff_mobile_application/ios/Flutter/Debug.xcconfig deleted file mode 100644 index ec97fc6f..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Generated.xcconfig" diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Flutter/Release.xcconfig b/apps/mobile/prototypes/staff_mobile_application/ios/Flutter/Release.xcconfig deleted file mode 100644 index c4855bfe..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Generated.xcconfig" diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Podfile b/apps/mobile/prototypes/staff_mobile_application/ios/Podfile deleted file mode 100644 index 620e46eb..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Podfile +++ /dev/null @@ -1,43 +0,0 @@ -# Uncomment this line to define a global platform for your project -# platform :ios, '13.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.pbxproj b/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 12b34513..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,728 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXBuildFile section */ - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - A6F5EE189BF639628AE45C3C /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B13CCDB5FD8CEB4F8FFB43B /* Pods_RunnerTests.framework */; }; - D5F26222A5E50B6A60DA39DA /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B0B9CCEC15DE23E58DC42451 /* Pods_Runner.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97C146E61CF9000F007C117D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 97C146ED1CF9000F007C117D; - remoteInfo = Runner; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 039A2FCBC314380B54033007 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 2CC144E0143B4CAAD8949124 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3B13CCDB5FD8CEB4F8FFB43B /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 6D58F7CBA805D9F84D2DDB73 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - 6D7385FFF09B0C6116FEC86A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - B0B9CCEC15DE23E58DC42451 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - C08B5E216D105790DF6FB837 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - CF7A185B9A21B91B0DE7D158 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6F3F2623D6016F80292A992F /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - A6F5EE189BF639628AE45C3C /* Pods_RunnerTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D5F26222A5E50B6A60DA39DA /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C8082294A63A400263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 384E97F604A1C0D9D7F8ACFD /* Frameworks */ = { - isa = PBXGroup; - children = ( - B0B9CCEC15DE23E58DC42451 /* Pods_Runner.framework */, - 3B13CCDB5FD8CEB4F8FFB43B /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 9431EBE7EB5D5EB6B71540CB /* Pods */ = { - isa = PBXGroup; - children = ( - 2CC144E0143B4CAAD8949124 /* Pods-Runner.debug.xcconfig */, - 6D58F7CBA805D9F84D2DDB73 /* Pods-Runner.release.xcconfig */, - 6D7385FFF09B0C6116FEC86A /* Pods-Runner.profile.xcconfig */, - C08B5E216D105790DF6FB837 /* Pods-RunnerTests.debug.xcconfig */, - CF7A185B9A21B91B0DE7D158 /* Pods-RunnerTests.release.xcconfig */, - 039A2FCBC314380B54033007 /* Pods-RunnerTests.profile.xcconfig */, - ); - name = Pods; - path = Pods; - sourceTree = ""; - }; - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - 331C8082294A63A400263BE5 /* RunnerTests */, - 9431EBE7EB5D5EB6B71540CB /* Pods */, - 384E97F604A1C0D9D7F8ACFD /* Frameworks */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - 331C8081294A63A400263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C8080294A63A400263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - CE9689C1E92E6C2367B60EBA /* [CP] Check Pods Manifest.lock */, - 331C807D294A63A400263BE5 /* Sources */, - 331C807F294A63A400263BE5 /* Resources */, - 6F3F2623D6016F80292A992F /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 331C8086294A63A400263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 9CBB0946A0D01F90169EAEE5 /* [CP] Check Pods Manifest.lock */, - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 63412035F5A4F70543904256 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C8080294A63A400263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 97C146ED1CF9000F007C117D; - }; - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - 331C8080294A63A400263BE5 /* RunnerTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C807F294A63A400263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 63412035F5A4F70543904256 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; - 9CBB0946A0D01F90169EAEE5 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - CE9689C1E92E6C2367B60EBA /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C807D294A63A400263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 97C146ED1CF9000F007C117D /* Runner */; - targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.staffAppMvp; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 331C8088294A63A400263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C08B5E216D105790DF6FB837 /* Pods-RunnerTests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.staffAppMvp.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Debug; - }; - 331C8089294A63A400263BE5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = CF7A185B9A21B91B0DE7D158 /* Pods-RunnerTests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.staffAppMvp.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Release; - }; - 331C808A294A63A400263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 039A2FCBC314380B54033007 /* Pods-RunnerTests.profile.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.staffAppMvp.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.staffAppMvp; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.staffAppMvp; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C8088294A63A400263BE5 /* Debug */, - 331C8089294A63A400263BE5 /* Release */, - 331C808A294A63A400263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a6..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index e3773d42..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcworkspace/contents.xcworkspacedata b/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc14..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/AppDelegate.swift b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/AppDelegate.swift deleted file mode 100644 index 62666446..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Flutter -import UIKit - -@main -@objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d0d98aa1..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1 +0,0 @@ -{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}} \ No newline at end of file diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index a4e27cb843fd8ba80c21c82fcee0720af03b811b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31482 zcmeFZc|4Tw_dkA*UACm`OQi^jsO(0Bibh#O4Ml`3*>_r`EJ=3FpzJ0~Az8*Q*|(5g z))>Y*_L=!!l^|M1$4%-RPc*-3)^gKlEe^2JaN&G@M|z`hF@v=xO*kF0H4PB^O0BHs~t1H zzE!q`WX*~^#eHU32uI9|4fpKbvJ&nlDR=n}gx%i{B3-1+KrJ+JkO@2?X;sR+AT@T% z|3YaDFv{chOUh5^ociJ8_^HE3*wMp>CIjUWeEPqiLC}9y0!-n*Rsxjp--GjCr|@4t z32flMp#v!4|Nm$@c~)5P@{}|2(QhGTA?B1ycr|xN1(?WVb_kN^(vrd{F4T zO~+md=VsO_z5qc-&1j&>wV1n7xpMblU3*2>b3Q@#s02? zqGll_68VS7Tk?mGD2RX9>5R(|)4Vas-0S2-@+;yc~{P&m3bbQ+tT*?R@!^aG{^hBx*b`<2sZL1H4Liw8CYeIBp>CTzi{xzcbaH;tU=KXzd!~{<)GAwUT0;Px5vY7oQ`SqeyRZa zydnTrs@hQSg|E%|@ko_QC%($DHtq0Yc)U605m0YxFO)Ssd)wfy0 zE}`Szqo68f7Wt<#wP=7Em9If+MK??WZC}*HMhC?^wa0SldhRt#DG}#tHu^-VM|mKq zR)Yqjd9$>w!!{e9u=8LrXtA-G(Q_|gcC#hejkWu4>$|TNej?q&L6=k7aRe&p zsOvx9bS21OX6t+F+k2nqmiy`5Myc|=YoYFJsdaK_P~rGpP;$C5e=d*$Tx)aI+G)s& z*a1GLJOI}IQDT5Nc|i?gr!1Q{uHRQOC8ZG^Xb zb*w^w$fW1dMHwRijU`S)wHBysvi@9g)ST-6`Lss`Gy#Xa^KTcLr~9X&jEXNVN|wzFp4nV)iFt(=76^L*V4mmWb`i_ zZ=bO*pB!b$@e(g3-Xx@rFPTMZRM5eo)pQ1kyDY|t4Tw_#MmMhTv-}8;?u+KRp(RK9~FR2&V=c4ipG*0^os(52TY zn;i_^kVoM6Qa`Ut&BP>?JZMY@`?C0xzE$ z%6GV&;AmlJQpP%YMT)dGR~SfAtt2tTPcOh`X*XukW$R$4u)9d(ihV!qIZItcD&0Z1Z0s8t6kH3|(b0bIp)%9)?xJP!kkA(ff(rgRCmcag>`UF~KRZeKW+> zm3MVWyA!2Ue&XaHHD!Bfj>Dir?x)!Tt?0O3ie>@=p;Otg)PSY-3e^k;<^9y3MqGoJ}`Fl$ldC= zuB^xpE05qvu^wRt=;%or2n(cKnD-7`UC;M|XK5dWPCjOUcyC0J<6Iw<-b5Q*hEU~0k(Yviuf@r-7;i>9a_P0P$=<+c~a!^5Xr^uix+qVKxb zixJ9Go^Fxg=ennbxC?fH5BYhoPPZVIX%tWiJDf1JaPX4!LttsPLLFnK<$<=PGla0< zqUg#?60=lgz^?>qK@9MPEjPb%@BQq-cqhvC>t9?Zd z61|d2qS15JQqt;&1MtI6wjZ(iny3dBGtxFFW7qIn8;d-i#z2v*dJSSIeyCcycl8ff z>V<=iY`KLk>Ik93Uo~<(kRS7xss!GN*ym7|P$=2?2>jOjwK=dVi&N0czNve7F0yxw z6FgYRMFN5*C1`?I-yz6OP2@^MSL&>T`#$VI%ZXOrma6ZS8|!Vmr{E=Nn}1#c@`(F2 zq-)|)SR{M!V9TJ5&G5N71Fw~p64ob9v=HfZRx*(EJ1YQ5VPk-t9+38&CgBZ36 z^J>Bc127p4ZHR$xiv)ADzF8|O)XBT{cUa3YAl>G2h4Dr=&I4BaU7-Up^@TLKYq>f~ zTnibLIHF9YCSA16_E^|}N)@ZJzYWK3?ZZj^c$O=|oWPr?YbnR0udrrv_u|>;P_L0E zV6`ihp~JOABfPCM?@3Sf&<6z?Uosep8`yGc!+D%i{?z03u!k|5cDdvfoOkWFp>ndj zNJq03z9v#j^x+pFJGsFXrOM(^?6Wako1kOmh=W&D^1dgo*2(KFz^G2elb3vGIXet5 zrn)0NTD%9)uU*$mz4mA(yFHOQ>tXLrl2OsExDFiL06GdCyu}8o72kC~&53>&9i%B6 zck{=}_{1s5@->)3!|M|p01#=BS}HcqS&wEMB4@6oD^`_k)*aN9K9+6GMwt7hiU{lc zl01TE$D+#z+Uynym+DwkNvngM=1+a@PrF7A6()yp~2Hf}1WFb_pKVHc_@ z&iJqM`Uz772YuOQn>;gwj*C*DuboAWI^H)+G&Pgft1c+mlxQB+XR$3FkjK^J4xrJ) z1ZT9)GN1Xtq=G;}tZNEMhi9I#d2FhxQR24K4Rqj_mW93_@uj=gD|n*7c5LwAZ$6;X z*VrJ)Hrg%t@uq;VU_eQq_d!4(?nK>+b(zsk-!Obsrn>L9#CVQi-M#jC!p9gMu4vbf ziF$$G@A;Q&SNh#Md5z$ih#n;b?MCgdxmY}NJ!T}H#UdPkgHK}idDRbj7H<|*+#niBCN7iL~r;GzLe3eEE zs&PT=uE)+A^qaJWOb>Er!wOG9J4}9L=)xyM-5~z*aUo^7sV}#-i$=hdEixR!lx-v> z<=Kd?RF*c`5#F1pFB7Lv(NodNmYZF8@;yO*D3^t!-0k!SA|<4*)F_4BCvUVk=pv}E zL|IrZ>YQVQNcH3J;P7`uNnt_R;x`lIi|SCVLx%I7efjE8v)kA06++l}d+yEF?9)rX zUd4_ofW3f&aMsyMP{L%c6<$SJt)F$-CUuS#dVSZ>gjU&s-z1Wp^yc~`l4*G|^QM~e*jL|o}S{y)J2IsVZV|7j+M5>Y*q?Yoj0 zpujpX%d)dd<_22s-{gsuBkW`NP%F!~xM>sJ|K8Bd&j=T!0A~0Gbv3|uA3Jfdw=%O= zI4BXuKk-p~E+*Wq9PYpNTYx`n^Rt-r1ebaQumY0@HXJ%k(W%4+f16?N)p=VsLDgw~ zHNGLoIJ2Pa-aTWaQ`mm?0NJqx;dmGaU3Km*BOE6)P>jc7gbHKvpOH0K|63IVKWt9T zsR`Nr7xPX2i{oaq<9h}5CS0&uza=8|_anCPF(d6ycLyq?uh0BRSDc52e>&m*!5XB$ zdzgrr12N;)kb!5!e*jFTXZ97BQK}EW-~r0pA1ugdcvsqtpG}?a7_yr4jl5UR@#+fy zZPPoNSrcQ(3tz!$3Cn2M1MX1kGM5tJ`S+_r!X&BOTuJQ6K|GOcZ6H|C0WFDe{q`=|seeMHdH^qQ8dmj+{*lfAx zT~XA3PgUlpj;0W|gNSc}#PdTnv#{Xwwk$orxtzvp#{v24AS3m+SGus|7({i&@f7Nv zJvWYr&3;$lWFa{K1dvknYS&#@)0$hx22Pauyq%!P@U(~Tx?E9mJV@BcD`=guEF26m z3H-b3wj4833{F$mHc9Wj$>8$r)PuqxXUA=luV%}(E>*DHnX_c#dZ`8RfLIjRMkgHz zrpNwyYyk5PJq*^gy|BD}WX^)V%i?nYA2>c?qw3`V7q}ifk!F%!RpBIMA#oymdE7Ff zI1A|2QdQ$4`)Dll$#XOOlUuG|N}bzW&K8=yd~n1#li(sL*?u6iUOnnI$zKb%o*8YH z7^L<+c6LHGfomf*;F759xhiDOPj={shcS?SyP=cy< z2e2xy*ePh}8KMPxuI_tZX!wQUY0^Giivc>7=CeXRqd@;y;5QyqaRN_&IW@*qYnE1) zM(=WQ)56fy=3ESxJ}CDU$s=>qFH|(1v%TN-!R23AUYF`XG6=0zD+e3udn}b>bVyRW zW?)F7-`nGnh{nL*TQTNmwUiYz33s4*iMg2Q>vi^?%SiHnfX2(VNz!jS;EBkjLZO2- zva%h1Bv0}Ce&gD~!n+O`vxwxWvXTT8I0a!roC!AApC-MN?w@=4D^p>V{(pYUdy z;NYo$#sywru9`Ucz{rT+EA`#rOz(4^uclf$Og0x&^URhDt9^K<-m3Z2^U&wMtHk;{ z+CBKuE>eYLeWkla_(0!DO?=>NxxFWY(f_tJJDspk6jp`3^ApihzH%0BcTF#F$(XG< z^VRR&6Ay>W*o>lw2VOXJ;aR=`MrAC1P@;Z>(KjLP&TGX9{AmiLoEv;0CFD=;m($az zvcPF;)4=*PpE$_w7__M^D;k- z?@ApDivm84g##l-7}*ruHGK}$Exw_Wr~Wc0;Wk;3pOVfe=YC3Z*HC{6rG@?aHjJ&a zT%7`;kVgV6MYrG`ymi1^M$s+7k*0G z^i>ePBc3%&Q;Q3UI0CaQIn4N~fI*+ayz9&Luyi&tGin>^nJ6gn6wiN($6GX7u0E9J z{*A4R!s8XQVY{))_^voqGn0Z)qSPZ`^jB5_3zm^JeJWv}jToS3N3$+Sq@Ua`1*sg_ zT{=7CMdf_Pp2f}JDr8$uJ7?eSy(#>l5>m?AkO4|Rz3aVeOtK|U|LE9u1&+-5syG2- zoNZs4uQg~d_)V#^fZP@ZD6t4zub}V4W9jx-$!wag#pMo39RxJf-nuKlyFMLZe)|l3 znvi#qA4I>J*Vm9$uP?DZ@iFqlo~|;zTM6`#$BIv3av*?%-q6@CGN+StyZY0=qYqS) z52EBAJyv+GZodaOy3&qh{&Q`J8pqJ=4wQMhyZhe!Eax*6+j+_M^OA{(-8zEq#ndy< z%O3#DFQ8p5omak5@NR8c{qUnl#|=GPw(s4=koDg4iP&8DL%OK36LuPkI3mFJe5yO( zbD>#h>HXYkudQo*V}l6jN#%;+?@;vU=_20ym2!{0d`IHqQBb0(ZAR>P!+Mcg?JsQmh>}6L6-{h*RTGv+Ya2dLwycm1YU*S_PIOCaobFl{NPn&8KOo zYIC~3oH~aJ+okq%b8rqw7g=UU3u$a;23~D0WB5Gxr=^C*=d2FxZma%P)*v58dNZE~ zb6R43ibdr093+J(Rdqj5og%1HY22Xq>Y6Qnv;I8yfm?B+UVc2&NB=V?A!Z=~zJn$A zfEt5wgB6rA>@hxcIb&sU30YIVa_^;Q0n34xUqHICOBYO@gW*E1%Y9SvgOM8lRd6uD z&sftu(kTmzjZEehVP{P+1Y65kk-BQ8HD{^Yz?Y+)#jI4dt36-px)6ig4&y5|@|AM$ z(%)Y{^A%5Gwxzl%dZIuAFWQM`5ezi3jn51ESuJc~;H*QDlcZp~Qj@4Bo}`KHI@{ag zt;$u;ULdX-WTi0}6!d<7A0HTG;+qQ3$D7#G19B>mJd5%WIT@`c65Zneu+SuI>U3q%z0xElD2GXliLfhI!Mg`W6svfP0M#U=9kL_Cj#NS*S zSJrhWZi_BVtSoKAhs*)l==iJtS68!yEt=7Ps|VF5P%rtiErW$BxT}RSki%Io#Oj_+ zBpBvhjCCGaN?Y;!g!zPrXReP5Tb%NI;)7B4AYlcu4g_E4*n5|;xGAiU{NKG5xv#jO zb^SsVbX`u5h3Nl7uajorihT#QIRcuC(vEnlQ9GgkrsY%8J!HGAPQRNW*#f;Z4A_)W z8t#fG!-+L`)S55$-ItppB1|^xX?+{Mry8z7+^iL({YYiv1kraM98<&Hs8AH+XXjr7 za`x-860`M-^t4V4I~L+RdS|CWxIyFDiw&`w1af~%!SVrtSq}CJ;pthTGM{m5?Nd_T z0Ogz~GC&Qd4A%Z0Oy~DilGZO8k&w9qBMuW2$*TTty}ci>r!Bnc~=@ znQsw;61}e%$q%AGKme&CrOuqm=)I~~W9QcyU8#R+-+%*prLlN90f-dyBoec1JnW6N zofv*i%(-Jc>^N=w_?oDrOpmsV>no|98DEc09g*Q z>JX(D)nnS+HEZb#h4Xp?5+$a9= z^6(@!JnMsk-X{0q8 zT)9u^#FmB?OT4)~d8szlT7A{NT>3=R5LUHI&nm6BVK3*zM$1yk+HS&ev{fu zyKi@q$I|^TSypkAs-hxeL%>@`cDYJEy@#fv5ZqZts;>l^oK551(GpnNN*YbQju0-zSUu@xhmfBc3&I zZ#Xn$WD;)ult7eE1438mga~zn){p#xtQ}kT8RtYL zs{{=~(1e&e>j($KO1iTsCt5nt zpi95n*|MI6S+-ld`TCU+CZ&vkX!U`7(%?bxW&3rxcJr3m>x7!Q!R%3W{-e+(i4%RD zv8ZiVL;JU{`~RAC-~l(}m@bkZ_`CRO={RzK0Da5c?jM>Eyjt93S2&m%Vt9vaeUVH- zowITiK*J)`%v_>S`j3fKBYCf9PVI@NSQfQM?*o2rsWL#$w%?=!Y%@#b6VmnFu6?%g za&uVOkop!#1}m5n`b0V4ww1jVHP!oTAUg&mUNnv-_)E0-;;gxkY{Fx~-)w@$NzBss zTLlu0=|X4W5)fPyk462J+j_OTU9yulm%Hn!yM9XS+NSZF!S~)I4 z>VL8m=8&r5;~QdIaa!U^%kC#+-59f@SmsTfZ*=NaAwv>oXo9b#-E0}Pn6;qR0K~4K zvj5iPpW=>uY=>mHAo)9k0?T*5pzLyIDM?CAE=dSvpY?@@Oa`f>qGs1Rs$kJXJ1Fky zd(QDo@!#d`nm_xjSX8%}Mmp`}9RpO(?lXo1!;nVGn<@8jyMc4b`;`SXXN9*d(UH3{W zjWpY+Ef^Td5BPvrOV`j&!@MJjBdl7zFY%&ReHFxi>N?1N0C?TIDMe4jFmdSG#Z=w1 zB3R^G`V5^1*d7m2=%qbP;z7V zu@*@y`xb1e`2psbff1zC5%KF@Cl~&##+dKUny>TsWtb=ij3F7h!X{Ll!QlFIZN28bbv0K|7FlO>r zp-?+#_5$mrBc0nVKT#X!38jNNjK}{G>9Ys75LYm5&(^?HHW*j%FjWsk*vW1mZ=9jBd$SR`X&_R7JIk+KGlSov_GjYXH47a**cwg z`%W>+PP24XwPN+cPR0L(6aqQ3WxS?u**0LiE;SX9yj?fE(!e5|M*?hfCg^EpKXf0A zUvWpA>ehB6Xn8rN|9CRF(PPnMF4J^c$<7D)+kXP-{hTgWbkYO|+zkHp zT2qu+7*sX1|B?TT*k{iYcyjDn_1@fq92=(QV0Yh%ZJz;V`5Gitpnml2j+^hWG~dp> zO_Q~F-7oK$yGNsrLgUvrx-XSiKE7P}ryBGWdZUwW#e&kfdh#M!N4|VJ$T`2)eNTD| zRHIh)gH{iU1}#Q%hOi_6i~D^;#b6Dm1qPfeY_r?xR8!}$Mr3I>iemtv@W~yl79wZn z<+XW(+invDrs$(9L?)_QT>HIGRhIE#eX%x3DnIgSaouE-4g`%Hg$g)*U-r}hq<2dvEt!Z@Dpu<`Mz=x%JS3f#K;tWt>`ZjsCXgkU> zS`4;+aUN=@e=-^Fvezvo4Xd?6Bz)kLjrzuilxp;n|ClFN0r~*2Jp|uV>6(zY0G2Ej ziVdO(*JXSM7XK05l3n3uNKB-x<%+4jQs*Z@7NxZ9g0FuN%p`F_8!SUh)l0PbSab ziyfkd>%>+cmET0tWcgqlk0e#C1jsWw_q3MFYW59E$LAacVQ1$dK!WIg7KZLcx6_e6 zW`uo!3V&LJb3loj%a<3-ac4J32Rc2@>xUzR&-rOVK?a*L(_HN}WJIIEXDI6EV zs$(JN=VuEVWTvl+bN;dLYO8HJUNp@Ah7iJ_Xi56Mtf#A zV`4e-uAkA*FPn}20T>Tz*hzI@&?@70{-oLXKK-#pZ!G6zo_Ohto6BljR6#sGsgR52 zA#pWaP@+n9ZNruBg!K8k)?F(0#bAh9s=~@dCPYr2v2B1sn{Z@r*P25PDaagDu{<*g znIl{Cc7$5oETl2L1O@O#>#KFb3hG~L%i38zz2Ij%yVsY;QBZ}9-j;FlxEzv2`h)aF z`>d`e4Kl6KX3M@$I`qk}ZDS)K4w_(wesaR(z2pPmc?`Xt-KU6mxu)o3Ks|!GIsNxA zO4Miso8@J!LrHQby+h;DZO8zh-gSR2%k$@()-5|$s3SlWy0py*9l72#@>JHcFo6T2 zG!Rt+bE))86`5d=RG&Gy%6ngh$XrSf4MmB~89ZsZ_paZ4Z(0#Hi4!Os zq>2bbQCs)@FjW5GAB=hDT;#xad3J0d(p$H{1T>Hp4n8-TLEV&5bAx|UfzG8s-FU(N zMFGr^kv>@ia`D^&jMa0%Se=5oJXWd{cHk@Rs`)+qdw9cFq4wuR(VfMNkv)GgH$do( z$bDWQgjIbkFRLJf{C{gX9sMdLv}O>r!F|uXZP3fwgPZkED|d$9F*pz|p@$a84e{-o zzp+4T|A1L+*K34msMl7M1toQ?a47+ zZ|AZ+bFD`g$T1Oq*rQ!{I~qDf{qpG4aV(IbHF9*z$pMf;ZVq}~%ifchU0F}6XoT&a z@p$1J@&T%v-borEtv`}g!-^W3*&4PHf7oO5vtc>id{EBMD*1)In({}v;!)Iy_ioVq z!i28o>3jU3#76ToE0Qmhxg(1x7Ke&x5&^A&;~e5mvU#(CR;A-T14H+mAvr;5DxJz4XE*0etsuyc$${AN5Ynx=2mLy(sV-ywy#b3Y_kE@QYBRj;83^FWM7w;4rJJ&R$~sDar^r zYdTRq<~wydp#ue3{taj#C@6e%&3>M>G_GcJ>U+0xdd0#P+3py0i88b6Mx%4_O^p_l zcmD}R6FHR9dRumxEqr%X1vDK@)!`pnrFGxx~Zwhqb0Zg5~XvXaFmJ*OABN|4=9dGe`0kFrWmku`h zoFWv3l;j#1ecFaBe9V8z#DqTFKg&>sD4V_)N|)xB#~XYka>ZPijD5X4Hn6AVXw~*< zgKd?!a?lyCEqJh-#2yv6{%0w>Y+}P#^Qw%wixbt|Nc^5w2LNC%<`x$%pMH4uFFuJl zLCihg332jLLtuJSp`CEQBhEjd`C>onq=-AY0@i(CM)@F0-*ta@tGTac9ejO};#Sm0 zOj!ijAJG*#Vn+V{;s(Z`oa#<8oyhqQprc>S_1w-eb1roJ1)3bD|7m#u4*G?GElMvw zY++YFtK2!%JNy}t7%e6=WG5VRWeI6 zq?JizFsN&NeIY14YbIFmI|__2reZddbHj^^s+KnM{hFbSsyWKjRy?$PU$DQwPUcZ# zRz#w8@Lb@v8&J1D)kzk${JD?sy9f^Mw8768+E>n>=-adk6jmfd&KP}_?`6hM1$le5 zauZV|5q{WDmhWzy_p*4oYYt+_RqMH|cupI^}4vTp_Zz}2y?28jrSD>D@CT5#mCy7 z$p!P4*?U3H7RjUE7%KnD^3WzG#pbakrrHr_X=d(fL}<^?2@p z-U77gT#Sv=&1Ky)rLw^x1zuuhEeUpW?qh2;@?cE~#n_QNQ}lYhF3$383&aIte})R; zwKLV~TaIh%rj=#Yz^!QgLsS4K_D$2sZGsW9#|e~F>1ZA{4QtBI;+t2OcRcioHTUf( z6QfBwS~Z7Yu#u^43h~>@1Lib&^Q=htZpM?aZTc?y7hJ$(4N>si+!DA^WglqE_^f5( zhJ6ta9X<4wP5xi2EPb(@@b`=4<(uK1@Y=IKUrrJt%{msPc_ydoRs1f0xZ)HmqZlsn zT;e~j!_A}{G>&{+W{bJm7;YmT_Zqk{wvtNiQr~8KPYs_f@2h51!AZA3MPZ4UItxGo z08LSz^%ew%2-XE;LQY#MC$)sH7@G1iBsWQ_wsi2ckZ1Z5wn^uO~9Eehb^R_8bP(A>yZ}`K<2?4(L0} zu}fb-WA!2m0ttMjTv2i;W&M}nT&9O!_7rIb`7(axR&oq}*BZY9ns`1e_DM@0m*Gh> zyq>_NJH)u_LAt>#trhiOV9`EAI?^7dqg4f-bPTORC3E>(E5^o^g#Cyt}5l}#8Y=xlOy!y z=wkx~+{r6B*Si{g)6MhCM$p25B0H-IQ*-Q9N!=uwjL>s&M*|WfxnFE9CN*#;g&ko0 zPWI|f9H3qrQYYV!h@}QmBDOGPC7a5WB(S0vR@+=pE+0g>cZv3sWoR`Vh3;8iJFF8l z29sBC=*$ov-lM6)x(3f8y??!KZh!JA(Pa363O|xS)haq70IE8J61*Y+ZMJ5UQ;w6M zG=+r}y*zT6*X~W|6{rL*jayo^wfZmX9zPAC{t=`54OBj22Oa8W(Mz<3ktG_O&{wCK z0n_849lZ=x`A!DK@WijeIr<|1oHry>r)z1ag~!})NlOrRoj9*MbJ^$dwubSAPrEc~ zTBU|K$3m_t6&6^q6SK1x0WNLtPE#R26vw<5f9;1#>(A9Uth7G2UadU1vmp?dY`%ZH zSUv9V1|5Q$M*@US$}-&8BJ455ZE_Nb77Y4tf{wvF$0Z1A1PJE6he-D$1Ut znq=7XSLw^&mq}>Xhk0M;PkRmQxM6zYLWRH{U{~p(jvL#QxlV6-XZI`!g1#U)Ig}4s z*i>T^zTki1={7)IT&`z(Ro^o~e~toaU;Z{4D%;E*J0d4c_hKIZc;2ZyiYN4JJ7pcV zAL&@Rvk$$s^OI$TZ5T+(rb-4S)`b@;AKGv{!_%G-h%8yoe--C{rDG|UJ*r~ASqelu zqetj!Eits0A?Up7SS;EOIzRf4T3Gm{5z7UAS}tyF6=l_a6j!*a)$27Iifu_t(Q8dA z9>mnTTo1}ixKFc8vXox+)ilZ6eS3sO&4ObNQj>etXHADJ9nS)@l3l2LWRq>&Mr%Wz zs=4>AR0&%v(5I6ix*3{;tOC`<+!W3ndv~{>QyuT;L57$p;vJsg*`X+ zxJ6Dadf(C5A=w5Pt*hb}O)nWJQmeU5WbN!`NYg`j2z92P4DyTNvQ08fxdCK@H>A@3 z&B99k0D!ETei?VIk`S3Z$W(r;BY-^eB5Ki{U!DBL9c;E#rw~y~CWc?dxCiMp->Cgbb9j@mjvSQ9C~Fc=^RH znu#H4`MxN$x)~I2NuZh%5FM?*_)&c$|2k&KW1oB!B5BD}2m5ts-j5sE74Ihkg5;*h z1TF-6{hh1FY~;kekRZPvlW~7((g!nCTT;1LA=h*E_jXVnRz0s=>S14guqE~8>U_Mj&|DOnF&KVZ(WzfNjQdcU+{6X04vf;s zhm$b{9-hY0750?7KmcE%`qoMvC)(!Ea>$~DKar2sGiTB7ohUr16qO1Eqi#J81x01xOP0`2Sw zMu*mOLKy=cj8O8{na+BmS1lQ+ffJ|!w?r29=>J+5dy6mJO`*`_lIm6EjhPzeVu?1^op`0;yblGVDKl{iF9Ba4&j)B z%iG4z_z^wv{AYgjAWI$bg!7_bHyPfmU>b<9-$hIv?^&okF*NKYaWaPlH{YQOR)U?Z z0|deL#53p*Fwp~3kNom7-!>KVw^gsJrd4f*u+P||Ko4SF@*T;566E-&JFkws7CP~5 z@LI15?7Az}qFje^pq}>+ENvYFobX4v~|f{ zIh>t?oh%ap%MqddOBA>iqXgL=88P|1)SB_0Civ&tS<6Bb*yJbF;-aXZGBI_g>rf@L zDoyr+f^1X{0>6zgR@@hjZrL1|#(O4@WDWcpfDFHX5c6xkaUwfJ5?pvnG>_)_1|J-G zAHYjq(Szi3%~n1KnD4hdL>k>E>{3=&Tvma)Z7QmW`Kw&KPL8nuSWNC}amzd8oz@DA zRL<#@-w)1;z2Bl3NtdQ})F>bH1(TN26^uOk=QnJ@9*-}&s(XC>tUjLye2`x3 zk=4^Q@0Vih>C$d(_bkpdwN{wh5&yXM^m#;n0CF7y<9f-f&(*o0(JCB4yh`*wum4vg zy26-}^}e#g>oUk&Oy;1b}d>wjJM&`tLItaN_H8YX2PKt;YT8le~&?>&*xps zsecn;Yv<*QSH0B*ytcQ)a_61Py#+^^8i~)g3otRL=KgFTpS2X^&0Z1zBw|MZicnGTp0_$cgtQEd(>sBz3alKo^|>sQ7zk&i?s^>Ex-+7KIKvY8(~Go=-0* zZF%^#q{`-nbehlcMbhUp4_O-r~bhDT`g^4sVJ}-060l5(8%)u zddK-L@cUb31YVeww5@*#D6pWB_e)`$4heNf(!Kg-IdR9ho&y418PBWVcx5YWfAQX< ze;$=vn+*bbWOKY|jh_s-B7{gT7Yo_$=$tT*Gq-hJ|2$v1*u~S|%YISG@tl8L>y6{f z92d^%!fMgp3Eh|1@RuqFy~@bBB>Lx(K$4Hrv&)A?Xpq~j8oye~Pw^=HJf_0Sj4VNY zNC-n>z+3_jHVapc#6|BI8w?tT=`iU*ldQomd!Yx8sW#BnGX~G{ZMJV@8nugtyUVXu z6kT<^UpfMn_;q4seDbfbE!ksjK4{Un1s`DJ#H@6$iK;*koWPe)U7GR6DymiAC;uDkQeOYX zh{U`(*+2)n#rg4T>B4T}d4#t?s_Z1L6v(pC%BjiRn{+Lq4`0CnRp>%ceHtZoN8UIq z(#Av~?NiE(24!}Q%$*70QAWK(Wvy_qf2n>Pk*t8@IHerb_KMxZ{2H!e-8H$7_B97| z@;qRP_HmVf%moJOv1MH2ZF>S8fT_YJxF&a+EbO|8uWA8%bYi?6d+cOxlQp=r$f~%H zL3IsHS5X=%et3=wQJg^(a0UZmx4fJQr=yHLyaZQ6+nT<7Zj+iph9#lb{k2N3gG_l( z@pKA2o67lk9#qQ@`t(3K`0SDk;s58cdgRyA@;Qcg%jTCt2B_XpwVx_)}DiW^?DL)Kk{AKsXPh0m^a8|lZWqYgT8On618rtb$ z)U_X%`3D7u{aK&~8yZpJrWE(tk{CvpvlnY z%C*WFMzsx>jh1nAfA7zMS?%%898SfqTuK3<*tk>?6t=zVR~yd@B&UaA$g~_#aMAlh zCs5-qD3P(#F!CUnW^i@?uyV+#37_i}PpG6$b8`(Tqd2F;R^~|^CJiWU&q5joF-R=X zT3=>EV`>9=l@>p)>00)Wnr1G~Sz75a|kjKsr(n!>UR+v1wuRFG`&qp0pV za7Rh1oblaFU2*>pa7X2Rv?7N5h;4sXi)0=j*J@|fN35ygkIMY9V{6EyaN^gu?TN!1 z;g}w5Bj)%iMyRvr1ACu8(d0T;8t7o&W%7@^N^ zA2b@qWkdyOm2!94B~JW@%gH5|qd+3YfQO(z1IjMh_t%}~dG&yM?-VzY!gTwXT_*AL zt0M$Kt7Br2g|jJ(?bOTuw9EBp*`fOMm2uc#H+qO6x6R`bBWBGIV8PF)-HZy?P4YHM z><@sNP|Aq@)0zN^^plf4{&>g}`h-a5rr8T$UQDZdz zPPSi0eogDHmWhXBBbte>$^Yiam95(d$UVh460Eq}hh7bl!~i95zJk=aPC~xmY=JJC z>exFwmcGM(w^Tj0$WOQPQ`;KfU`Aox{$`gudHQAO#bQ8hEW?eI*6?wx%D_!;XlK11{NW!pw%jhHS>l@SscPwpJltm`TeT5Jka>b~>Vrt5ULUiw=yX9x zxgV>3kI-0h>^Bp!zM#0^?Kxk#tPOfDe`QsI~-9Rj6Kj0@Rv%PKni@(dq-l`lZ5;m>+|xQU;+YfK?p zjy(YvW*OdRjVy(a6~<`Y@jyS-3EnI<=C^V70Am~$G%uzg)fDFqe|@H8Ha1UTlQ+SI z%cEyxHq7@*KtcQ4c#!j@(L9G;bCvN%f!0Ev;|-E9%5r4$(4ERQz4q?f!yn8?6#9!Q z44;8H!ekG#bK?z{%3l572m6t)%snLU_oFN0_DD`2@WT5=g85)0TO#Zi+NZx6^8U#& zbDTG9Sk$KlSLbNn_q$|SW*v*kD=|H`dumw#hU%-Aey+@ahkiRw%iH^?|2Nz`#xg?J)AwZ2cIZ- z$u0$6Qe+Rm#Y`+)m6V-d>Vps4F$eUSjW`%xQ39##Q6NJbf`Zdr3r+Bk`Y7$&xKi(x zMX+7CJnb=atjDBsMa%3HVZl2mp!K0^K6Ou)N20uv8;EhmcGFs7>7f2~oc!xED*@hc z>=oqlc>BZt*2jDmcCGXk?zP94_CRMTOj<<03@e`i8UU(Y2tdmo{nHEi7XmOhn>N99 z&5WApLS`?m(sx|tNjl$GcFcNXH{S!|L{|9$1LW!4?b^)Zi#;0EgwpcS0(y>W>U zls2}2Js;L@az7v*V|d>IgW&`d8Fwvo?z9-}XLkQCn`c2x&Z@XzbW1MlN-mj4kV?(F z@gawSRs=`}qCB@BOMCaYIyL2D3RK&S@(N1(jl$P9je~X}lK}!GH_Fp56?99~Fr$Pv zxThocb~toY@ZvVBT7(i5%zKzT)ht|T?lwN=65nP-*(FXZahR`ZgNjn`M3eI?rF65O z68`SOKMv-)J@FgA`0m>#U(+^`9g3bBJFWb%=ZzQ$1+Q#k0FDh8{8d(yx5-=6yibcrIpXOUem3Bc-9^d1ayH`Y3RqzJ*(ACsS73^k_Imcu|}@}m1?|l zw*$|eQZQ2jqK%@-Gaa5su*p114BGfm{xVN$E6beNMVR;qVs^00NU)X|jH)F1|F!q! z;ZT2H{BIPkv`LF1EkZ>_WX~sAD#|vDj8q8O4Q4E(eA*Bdl3g*D84Mv=1||6*WEr~| zSu+!ZF$QC1es_HOKELnt`}gIZ(|r=*qQ0rV3;= z=B3nEav*bNbk`pKG&LaHN37O#zD#W^{yNJFe;icT$I7ndNAFbS;hXrdvBSsR0$_t}6*HakpAnZJmiO00sA}iFBA0k55 zncqOHXWW{75yeO`em+-i`j6K9wSgP#Nm+9x5_evpY1$XGLA}tvxi5KgwPPdoO$h?pstKpyp}L@>0X7Z00?pzpjwlE zjRIlK;i1dQsa(YADUT;L{Uli8&C{jB7Qkm0KkzvhTnp<%n-2E3RyH3N3X}Fpe)wOa z4qERoU)9MxrGhFeA5bqEPMfuRT!JT@%Y@&r${S6&;r@d8w{bi$uFJRd_$!Q*1-nJl2fw#05PODz^`Hqv5^-s<6tV*|c0wUW9~A4z&&;n|xX4MUPT%W)Rh+V|#Y*@VfS z0jm2~bzY}W(3P@WuG9;qjnI^6SlYedHx@o13BTj4#E&b~3VOb)DnCf1nUg>uruy6-^sCcejg)DAax)WILZC5R8skpsgEl}k_B>A zQ?vpJIJ~2C0JpNxDI+2ICWp#%lOJG9_z+xD>~IzT}9ao2{o z(f9OUlrq0O>^fF;x+n5X5&aQYh;xu#7!o@Zd3)=FVqr5~|3feH?ws?#FMmQSwjyP} zkCWOl1H^Ypn>+WY68ddK-}H8oC({3j`W&+prL$6|G)+;6-7!zaUw{bl>81vS_?D!H zdP?AUsO4REBS;iguA&fFD%!hdVYXSXRJb{l&hs_w0N&{XT-$>NaYDb zTP$2WH8qcYNe zHpsQ-AUxGJ_uaht-T0EUQ4rque1b>8SNS4sK8eg$%j*NF_5Q4rZhj(^vto>u=tL8I z=blG?qOmRKeCDa=ai$Ue=2#%bg}oq#oxD}9WY@+p2MK8hZx4U8wVYZiOD{}vThhbO z3fhbg%A15Nt-u+r8wVepR2!{2rc34B4sRug9B;@q9EJN%7XbxNRa~056IO`1qVR)qa6IFfS7AdQumwm2wG~LeV~g!iyy{z$@TL$UYB`ilKNK$w79s^Y=F+GDCqU9o2Shkrj~*or-%+e(Z^tC= zM1cc9zSVGS{AG;-G;=@6h{`MRL!RgkPg-xh2NIr9T)^Ew6LGrhjJcM{}d=2`Zhox+`1F#%3PHRqj~i~KoMBu-CYD=HFCvQ{I!430lr z2=-Ll=P#hXiL&ve(IKG|HJe%eTQn0hP*ann8;(NljA0z@zLw={2dONBJeJAM2!$tZ z_pu0ihZC%}If~lIn;4z=xgqQ%5f|ZWfL&bYNJ^x2m%vpvoxDWgKozQUK` zN_K0a1mFw1WXJW2{FEgV`rDI+d)+VjUV^hJqCpX=RjZax7P32Kp|2Ve&H9Ogb@Ow| zt()t;Fde16qHy+DtV^8TscO&LkYHX2*++iwmPHqj0`Bw7g z#e#KPoh{N!)$CCLjz>&{evA&?lp`)|2s<{s;Rjo0AWgu_tjgEApuEd#@ji*v?)!nN zJ}G;Tc(%`tpc(-b=Yb2slDFWI$F?uQ;nl&^D5@;)dL<5#n3j@qikC2V$_Hz^*1ze0ApyGjG9LEUsr*MY^3tuQ-|rYw+@8Qh76A=?-I+x+I6%N1EUt+}BK zlx=!?tDb^}bWal6fVpr#ZYIw)K!lBmjiqcQvt>xtSJ+F!#~L{XBJ~|7Nob9>tzRRt zI2u4kt?J(XmZtLeH{ZBx%@_`pr9U2*Zha3zqRa9b)tH0MM+tA+ou9|gROta(YE^fo zn76vk-QBSXPvK=#q&#vQQ;i+v;l=DcGZIpT_Mms^?vwX-Okk}^!zQegli2nKh49#1 z^3VA^0cjP+GxOXYNf0=+1PYqo9U+&t}d6ldV0ZCRDE4ME;N6|mo{P;Gmi9+NKNywiO|U&kz0t)(yNTHBiWb!A}R(DIkG@Xv$M&SV9V9=S{Kan1?u=@ z7fW$un;Pwd@=%r*_eJaPMT|zZ(2krmR3GH0I%#v`OtSRUPDQ(yR~eub$1BWGW{&7{oQ)g7)7eIr zM}9$X+6uF&iN4*S*G`o5y?)!sP6d0&OK`5cyW2KF!Tdm&?lqgS3<{<7Km&F4bwXZK zdG-kk9Fb%f)hm5uI9kC6GGy2%5E|uM;WgS-f!GDb+R&u{EtQp?iRsUz)EkWf)BArh zt7~5v_6ydH+$}`>3W>gXU^ehE%}?N%i#FP=)>*xI_q3$+K+YY2gY5{G>E>>T4QHKU zIXT`AH6MaQJ`P_*FHk?IEyq{r_F`D*0uG|**AluBY#@}PY{Z8Uos(Sc#*^2#Yv0Pw zeiVWidaW#}72>OM=y+mMgxcPMH^`nIx15hja?jqD;Jfm=N8>-!LXo4>ZwVJskJ$WRU1b-SXdY&S62;{zMQMiX-5%`Q@628Tai4+HDou(EoQ^x5mo!o!Mx zc34;LSCM>mxUe#59#`nG-F`ztc&iIy-`=%Trx7N0>?gY+C*kuQPG=^FrCVX+`$ z52W;KwMq66OA5OxWrsZS$?rU_f&%gjrjH+`i=R~=vlQHe z@<&!~p8It6{#z<9|LpR?_5;J!61#3*tlj-}NMCJwevtRGxUh1^Er8Jn=$0iW*mHeA z|LRAz1zN%k((H(S$Vu`Hc9EgR+&cZltS4$&HLc1=7-EDCre@~%y9bPNH$$@9lOH;* zTLP!XiF>d7%uwxvj8BJs!|qUC_)YCzWi+)j5N*%04m;X(ZPpb9sYH&4=ad8=b9X}~ z2ZA#>KD~n&NmDYn5zCcb{!LZpu>Le?KQ16GF|kJNWPZ7PZzRi=Sh8v}!>LkTKx{gC z4ng9{Hl)}QO9NMCXWSYaV^%qyGAU5jZX7yOBN$d}lNkP5IBd>NG36m7Ygw{1cc3n? zG<>`jo3`5Oy$w3z470CQKd+;aiikWK1znZ30P+f#irH&9VcrI1&>mN+k7PBbM+AkN zHUQA-ThfIhJd2F?2#LCji3buPD+}VmO|R83iOq`{`|p!mD!j&m^ehid1fTC=erZLI zWaXqsFxzf_dkNj}ukZa;oL?Ayu}WP9D)@V)Qj)S8*Ll(zGQ8tYG!%ITjJqg!tw83h zBt5Ha+3=|S5&6JC@zJc^`l&(Ub6{)k8LXK|*h@P_GdsI7a{qwG1aWVMHN4)ge1hiv z^w_so+`=H@{Cx=h+BSG+_lLFtbisua=W$o_z5@v%F1Kj({xu_$ix*0hbwVPQ^Ikah z{ED7F7FfRAJoAZ{OTomcR8sdWSWXh~-OSPYbn>>c$c#eKz_hm{Qb(41Mm|a@J9cDv zRG~bScavU}u2QxBHuTbe=SP1ytM?-&km36B$sOClf*9@4U$iaDg+D`W6=t?KUX*y@ z6wKzO>|yM+-_S}#oTl}$+wBsCbO-eN20VuC2lK9(ZrlQ;Yc66p2E*KVgQG7Er`~tO z-K})}4yJO_;>@#iB4OirDw#u?vGr7p3vI;1Jz*s#@;KU|Xi9_PZRI3(I9I8q*Ezuw zmT=Q|`H{-(;|%6c%@HxOZClWhloIsaIaOOJ#%|oMle`?BzdNQJHOFAVjBCd%50UdI z13U8{N*Jj=mKSf;ZINU0_Om=U{88N5{c$fY>TkTsgydKakWYSP0u*OP?IJwb^g|0>@&mJiv`Q|S|Whf`7z*d61JIhKy^Hsne- z^Tgx%l#1p%WW^M^VvmbKINrkqml@XK+0xnJnl~&xHD?#mYdvbYJ&iR)G`)zT@jK^D z_Ev_tK!$RsnjT%gB62~z%x<{0wvy;`mkT8G@k;Y(yfIlp-4t-YV5aArQ}(J~|3@WXU9!{2-ZOPL2DMc9x?D*h<72JeAgI5fy=Wai z7cwg(ajexa&uOMw;>$$^isV~|^FM|gR*YY2hfcf^bUjTAgvmWRDIje_`OanWI2_)Z zXZf21rWH%y|tUq3XB{p!M9`uw@+C| zibEGJ1i0BaudM#21kZ*0_-$|vh{4%ReV$^*Xrtb;;9>J~ex0r%bEuP0+_yO->bESE za?c-`7Yx6-g>$K+zV9LV1Jr zIbt~8BEG$O(OWF)3UzO7u-*9|3x=2+A_7$i`&ebb;i?vVPVIPYy6`+ha<{zkQ7g#s z38AHcjUU{~i1$v}_Hv0!C%9v(Kl);jgYM{&Z5FTuBP!vwN+ppz@6EeOZn>x$L&tBk zZ9HX{ns;AVJ*`<83`HjNblH-KR2-|sgFek!>H7G*eq9mI$&xB6CCfUr@#5@cF3sbSE1=W zU}U-W9A4arrnA9E!DvZS0vk^&D`O@RF(cL8Ph+iM|FP)Rs(e^5Bh%@1OKeBm{Tsf; z2z<|WsZ%e%5T~Q9do=$^3V&Y;PGbx&fTN*GIP)F0WgpZz-)|tLvo?j{5cw3dlA-wK zI7q37KNmO2MRt|Vm^A&d*OjvTl8*?y;~8j=;ZL%k@2g3nwbd>iU2`WKb~O8oxas%!V#D)q}kO zmUY2S?1pyCRfE};Z<>WNi!dWfX4iDUS<`7$+Tw{=6%hexdfA+Fu(($I>UPfuPQ>~# z#lsh72{T!80$^tW2gA)mP|gNc(k6BILQP;_U*FJh-}f5aY>bb9?hcB73<_WXuPffG z_@?|2pTAS&;I*{&~zZo*chSndnpY;f?s4Dtc0xZzTT29Brbe^rk z)=W{T-n9bg@@1f?EZ2l2WZnEVhBH6-$2^xd!NfaQ58I^>hAL1hV30WB@~8^|CE4tQ zkB>qrXDlVj_JbZXERTXyLvWi<#mZH|As#OC3(ST@#!OK=$(8!!g!@1YRZ zz}ol4m8I_{;y##tdki3g77q*hn_bn|xkLoLErPsM*jSi)7t zIWcr2P?dgyUSq363(Wpf+Y5Z<BU(gq1< zG_fda-%nS|mFz1fCR~Sp_Z#9EmwWPU-MW`;_|(bdAsE+VlNS z)>a`1YlBz*IFE`9ocx)6hN`MEn(21|Ga{9BmTBmqyXQ4ff;aN6S!TLC2!XKJN013KgvRf4Dzg%-TZ=xV`JRR>IC1Pogwj)p#-?6;<~1RKj=tnFCL>! zo$6d0p>xpy-Z+M}bYYf6@Yzx)Klrr2I*s>JPE`>@Kjl>Sp4&2AW9(K7YgLbL?(QTd zR>QtVUJlZ3jE20@g!h*R1P8C>_OeSF?XK(GxHp|`K7cp3(>gP{$h#=VDV%aTlV`2) z3FL%U0-+v6DgNEH8Jd!tF}-$eQ&pXsk!q^2fG(1`yl;`Wa_%xOJ+_lRFo>Doe&T?8 zH_paI#3DvR01A7!T4dkYys)Ox0$V_ARb(wsUMc!gFv%^V-7KOo)gsPkqWN_muW3$~ zAo9ScyGJHlw}(tL>bsuFZ#8mQf0WpdqPaJS>j(Te==TQyCsv3L^+>alma+qFODAGb1PK#k)|-(wrBhU@>k)+Se2@d=$vnnpakjH z=Y{9!LypR8U%_5EN=dZpWSp6ZG+yPGB zw`YK@CDhj0Ri}?1GvuRk5eujW(Gw%+!&=P;h9?n(fLwuJd}3;;M)(GYr%ceQ3HHYu3R6F%2`G^&$3*IR}r>*`{4<6!3nV4#JSUTXVz#syk}m*d;Mvp(!ZO71_r|? ztDgbVYCyLM`4_9h-)(Rk0&9}emPL~B5@pDP?pi>tBNJ#t*jYYPWKI-J(&n#&S|*Q& zVEc*TWN&(r{r@$31GT__6z_Dp)_^+dTQJ6%y&Av8OgD+)kV0XNF@R^0Z%dOBO6%bT z<--DjaxBX$?GGY~Pw)vxC@j48x5hKu!0iLQY)>j%KJ$;@1n!KrV%&MkL{<>a83UYz zBw7`eGZ34c`8$$7paxMI&Bxv`&eg`*ooLl^3)*+}&oB_3Gm&qoJlJGS^LHG)?oH3}?tA7pN3WAM#C&05sb_`H*`Ta-@$6%l)s#A>cnNy;5e5%U8fQR=Kvvhg@ zHxYm@9arDAxb@(D!K2GvyZ8%zu|YhudsY%ygEpCiLo{Gx0j%5S1zw=OxKxfs|MlYl zzvQi=b0_sAsN-LT24^YfVeMWp{i8_R<|GlI4@-cC2)r0;WsnD8pV@r7O$EWHBMyoW z159g4ELAsdvnBt{mX~OqiCgc}l9XRkiKr_3Ffv2cb8K}`J(ytA{xu{%vTNwzgAE{O zqul&kDrk!bWqg3e)x4MmdA;kluH8H(D;4d}L-q!mWDeI!rUFE>fG~7PEMA=) zf>o$dOyFJ@RF?SjwFG{MA7rZjxx36(Fd}c^2AA*>If2`txCm5@>zP}yZ)sb6eD*H0 zx;r@>!Bl8r&`;Sn1)ZLlUk-hII&6Nuha@(U>_92!MP_~;MH#V9$^&T~k*u)4c>r*Q z(40kzboxd`xde#fnM-1rqPHwPnD3`~z6hX4 z;XTuSL|j@7*#Q$+GMWJgx_58eL+}#KC{-62u^?q^HV#Tn_%Dxvp;6$ut5?9%GqX&j z$y~)p`|(rQq%x7C_z(Pxi06|A@%{W*)2ZX& z2rTIv*uMetq8yUdXSnB2V-mmW_Rid0SAoOH_4DE$VLQ68O`qH zO$B4w@}zuXO=7{R_S%x*<8<*C>7Q*VjbbDo$hU^-Y)Y4c@-Ea}4^y=`v;^xPxasK4 z1@?k#Pyez{xmn^as7+d&eKA>nKYtXyyGL649fN|l`_j%A0ShaA8obff#`|qI* zfxiCMig2m}@2)40(DWc;7uefs8ma>1zp1bvta=j3 zh_5P7knf63P^f80k+Fmk3VN+{@Rqch>V(}UXyb&viWFjqyT@eb&~HDog8Uo5cbNKq zi~bcq;gR46Guz-#C{-Z^Wf)(F8j$Km1)e*!`;S*oUJVYoxX+Z%l53WFrPgk*tmZ>= z+nmiWE%TcJwRcGJFpnKhP^ev-vB%7{0hAq$P>`KoGnWJ)hc`wDW&LdT;Kr;()Y3-Z9EZYpg)nzS(w|I#uhIs(IQamb=PAl_y-KNtpKf+iAj+A-hiQ1alQMv1# zx-o!v2I-pLgHGR41H5I#p$jyZtGSp^&Qlh5bTtSwpT2;&$&HTTYhmq>IVK+`0VIUO z`%cMe$)#S$5_!zlQ}hWXQ0gDphD3K9qRz?Mggy-OO8w%bxOeCoY-Ru72;g&;_%QP#6%U#ir?`Yv&e5wc~o^;HquP9^lVIJtWlto{O0;=Hlo=#CW zaG%vW5J0i33}C}oP84MmNk7TFUOqPpqEmg+g;IX6Fs3n|5_TnlU3wBY-CcXQ^-{^T z%Y#zHst-46Hs`x|GAW^q_%!*uxS=Ts&7J!jy!q=MNU*+am6(?AG?QM<;_!cgqidqM z4|9GMS6Oa1Y)=^)UOv}l?l^??4Vy%Gy5%5Q!)^d@zhIkFSH}0>T~iiP@&~qJk7jO< z20+AIE`1dMRlB!@C??+W1K-E>kpbYR&g!^>r}h0;tO&I#KhdHx5Z9E;0iK9bfGda6 z&Dv$#_l@Q34?9cJ(DazSo^`zk$og;oc9V2=;7`3BFfDdse48 z$R#BljOosMCg{MH9iFo|JA<9T_D|4!Q3RSLN*e{@Im2$!4lM;e<&;XT{516pT`ox; zv-ae;tH!5dxV;ol_wtV)K@!3_;%=xH!0iYstRQ>M2M-=N1%!Gr zpQ;k}GOX&FrWlb=Unp|>_B~h&(q4)FqE!X`{W_um5CoS3)5?En0xy8DI7v#(L<#IE z358TEY_ZM3^zrvP>0*DO0ErBhxNesbQbDkPHh7kC}IM9LCAmu@$8zn*8!zdMC%m7 zt)WC+YU*nh5jLmZju&2v8T)QOeF;I`IV zNy(`-&v=wlioKL(I>2#NZ;-;KPMOIj(C<}7#D6++M1L?#G%nDi*JwQ0x4QHNI6@*d zb{i7Sg?qJXC2!3Q_YGOj)CZ70n4G5NZ^xvy<%ceD2X%P!%?0HW9zz*zsp`my|-6c|532-HvoZ`z!)l&8zf7P}DoDX~Bn{dJ$b_%wg*#oxdGx!Ed(d1)EzNcyC&eE;!>ioD?JiNSkMJSged z!@$6>Wmfp1Q;)jl90zGO){%_y(>Z(Pd076suit+&Ffeq_JzkM!l^<``R^*sjzdgcR zOHzy{!dt6l+F=nvE)yNeqh}vOZT59kWn^S*oN^eVlYxQZ|9^(|na8Y+W&NC0>n0v_ zwO0D{YdmB|I^Z9ZwHn9 zI8!|haWwIlZ@;eCa&`Lhb00qapt8l>oU9XT+DaUV&|Ruo z%)`aDW^#~$rUbI!hfhC#|M@E{z{SMG2oVt$;GEm;Q$O+0>{aKHRr2$)_f@)>>q}p{ z`Kq90*Qn|XKn3*89LV&B4A}b5i??3+-7#K8_MMMO-AmUG+e?|}L>}X>~Mo?h> z{rfMeax=26Z~!!@Ve+BBfB$92n1F+Uy*SCdq;oF=1B0oa6hALJTqQ3LyOoj5!BdYI z7#QqKlKQ{9PG@_mWmMe`aL&KUw)2hD;%`VIBI7qr>iaoiM)o%hrWFK z?QE%lrp(h$8DgOE`RpQa}6b7h*a~mBb#T0F)=Ypit=cxi12c=adEOTFfe@k@%!kx z$LJO_Ffzi0{u5C+{rU6n$l1ppw#p!j%|I4I(#PZHpUz%+e(B~b15Hrj<7h4q56Jx| z9{&9G7v17F?-6-UL0aI^vrh!=-go=~#9~=VzO-;dsNjhQ5E5dslcfR+GZRD#IpZNL zzJBKoB(k)OZ*9ytSw#dB9*eE9T3fRBTfg&87s z^xTs#-+p1S7+5i!zWnU;&X3r1apKtkW4>#>LJ|X|NsB*IsSl}7N5KJ;=sv=4(9TZ^t@*Kb-2`~y|?q@&159_ zAldif(~s1&n1O*Iu56R9lPWhS>*js8KYacP7ytO>r)$D8UnkYC-+ph}howZK)Z$;i z|E}G61FO{gPd^rIxQt8VploxET0Cm;sKuie;{^ckxt4adtgB4`0000qr^tFw#zK>v(l^#*VZd2es7^ zr=zv4%IMfurD9d&jv^p(G;$*Z0Z9-9LO7D_R$RJy*(_Jaq^*+6GDXb*AJseg4gz!Qt^&M2I7NXlI7iwX97nXB!=Qj9=m7#iqTz{qn%z z*mOAwvA!uA18KGv^{sswr|vdBeuhJ4LOQTruxcr%u1T`{aDj9{J`=RLDf!2*+VDI-Ebee&ff#j*Kd_`%is0_&~aVNF)*n z1h%Vfc+i5__(^n9yg%5qHp(+8 z-tR(=2sESkEHhK=O;?1uV;p}UM>`w!3+$E*qr^DS>6`f^5)pLvA1gY2xkeio)QDWM zBO~ug@9@r)aM0hKy7Wq3lN^{NQGB-c&lfn^a6KLBTl-LFY48Ft;YLv_7-~Q}(y6fm z4(R0MH_u9pD)Y>JhCOv_0uOZWw>UnYY_MQ#`3?`&bUh!!?yPEPg;E7U zFj()X<`mtaMNQJa0l9-c6$wcs;;IObB|KL!=Voaef}Z?NAmT7+)IhG2yQ?iYw%o!N zf|k_KFiemR$eDEY4B@css_T1ofQAW#k_z#L)xM|`EAU(dEEsA3NKM0J&$mh+qtKIS zksP|c1sXySoLhvQ(Ab68+};mDV|M0wsYnxgWrPR#4ofOKk?mFZuv0#&pjuG=85_sU zR9$mL&C(vJY!>K03YsGqPgQjohVR#O>keHmhG7_e(U@Jfq_PvaP$-~#)lXu=J&+Kb z&6DNp9)9`KfIjaZi)J(7yt9rG3tLl`asl!+k|s8eI>*% z>qF~~=@M`#$HJiUCdUgLEBR4UVc>3MhCG0=m<HV|V^P#arS;ASdZo4aXD#_00000NkvXXu0mjf DiC7jg diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index b4fd03f91c7c3671925ae2f5abbf255fa035148a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 789 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 MACAzjfH~s+3m$l>Q2+n{ diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png deleted file mode 100644 index 31adf542a27081ac33b7cc46cce656cfcb2b54e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1084 zcmV-C1jGA@P)YdmB|I^Z9ZwHn9 zI8!|haWwIlZ@;eCa&`Lhb00qapt8l>oU9XT+DaUV&|Ruo z%)`aDW^#~$rUbI!hfhC#|M@E{z{SMG2oVt$;GEm;Q$O+0>{aKHRr2$)_f@)>>q}p{ z`Kq90*Qn|XKn3*89LV&B4A}b5i??3+-7#K8_MMMO-AmUG+e?|}L>}X>~Mo?h> z{rfMeax=26Z~!!@Ve+BBfB$92n1F+Uy*SCdq;oF=1B0oa6hALJTqQ3LyOoj5!BdYI z7#QqKlKQ{9PG@_mWmMe`aL&KUw)2hD;%`VIBI7qr>iaoiM)o%hrWFK z?QE%lrp(h$8DgOE`RpQa}6b7h*a~mBb#T0F)=Ypit=cxi12c=adEOTFfe@k@%!kx z$LJO_Ffzi0{u5C+{rU6n$l1ppw#p!j%|I4I(#PZHpUz%+e(B~b15Hrj<7h4q56Jx| z9{&9G7v17F?-6-UL0aI^vrh!=-go=~#9~=VzO-;dsNjhQ5E5dslcfR+GZRD#IpZNL zzJBKoB(k)OZ*9ytSw#dB9*eE9T3fRBTfg&87s z^xTs#-+p1S7+5i!zWnU;&X3r1apKtkW4>#>LJ|X|NsB*IsSl}7N5KJ;=sv=4(9TZ^t@*Kb-2`~y|?q@&159_ zAldif(~s1&n1O*Iu56R9lPWhS>*js8KYacP7ytO>r)$D8UnkYC-+ph}howZK)Z$;i z|E}G61FO{gPd^rIxQt8VploxET0Cm;sKuie;{^ckxt4adtgB4`0000I?9G!@Q0Jd$UESFQ304gqqL?UQjoqi>o^+cEl*{Q!xr161zNq0H(7?d1 z{d+2QA~Oqokcc3W(wDRvbh113D?Mn?Zm-zJT4$PrzYP<<=@b1e2VE-BbDnoEvOj<& zPFVA7JBT#nr+%R$=-kt(t(_1~^!(UrfpcFYvYl|MprfSM_fk7~L)BAcc^`Lk$AH){ zvTFH3(OFf6L!>|Ad_6BaDSjN`&up4Y>bO*rPH#HxC?C9{TGJpK09^4ydpIG3Bb(*a z5Z+=Tzl)4#Pk&I~CphevezQ4@{M%l`+MgTcX;nDHhxcDx+Ny{yO_ zDCF#{hZAzg;8;eW35TLAC&-tOh0{SYkO57sHSKq|L&$i0T@nbS7l~QSMSD!is5^GF zO0Rx7Ij^RS4VOk&g}Mj6uEUyS2pz0_sMmL?aH|N8G7`Z3nbN-@UfqY?MtC20J>gF` zgK(dbYTx`2D-R?K1z%L!TqAbfzAcej-Y%3Rc8XZQ2K;tHMwi^RWSEKNNVTA>h_GjU zky3fI4_`tPsqjm{F^hectlmm4%v9Yr3H)?>kw4QVqB`e%-V>YkzV;U4z|Lx-qIcE} z^#%7myY0wXvN45?tj`Do4fSqhRtKIKF_}b-3x6k zvLFKD0?Ng=+!l3N(YA@39yu{3{mnfu3lnH50qi+e<`dI_TJtlW&?E8+WfAU#i1RH_ zyx|?oP+?+{MR_1$fsCCLn9&Eu34xUJkZp$t*rtJ}R>Kc|xu-}DI`4K<|4 z+>jsStXxPCW1@ArY$JGWxb zMx)Y|v1&qBns;K1g#gIRy=(3cF5Tkytu)F7!ty*&2BE;BnO!QHrpx8z{>8@`vPVr~$ zR#o9iYY4ulZh+qn1vB6^zF>&M3padMifgLAstW3Aj-7w3;a^ozOPSM#d~9tq-ya0Q*;1o$x{{k9hC#%6*sdU<*qNh1A={|5 zV^N8jxdaNS89s8*;i?@v9&m5M3JdXm@GDSUDX8S%Au^7qMjmt>j-*zxDQTH@X}Qo{ zmliTKw7DxO!WzYt?3B(COgp5Q9d?n@hpzJWKjf+9) za(Ht-A1+3W8>hHVg{y-VL z_a6d^@WL9&RBBIr>oROgB6P-`ZA{=mz6Lh@KnADW7<2v(%Y>v zJ_!wPV}TBRt}py`n-7=VCzKr-bvx|Sm?w-b_t<9QW6$1gYsBkOL!NNiLL}}t+>0aL z5!JFz;QZ+#UWXF;(?4u`Ejy)_ux=|R_P`uMxcBefpl5QF@miAk{>DfLTE%bAiZRoi z7<;_#K4-1y`*Q*RnQsG9)gZ(_>-I?vfC}JzJw+ZucfQv<9k}NY5m5|0qM;q8cdY>z z_gf0dOe7@#qM3=Z`Qp~u~u_T#L_vg*6 zHoRAud(+5wUime(U(M`v`P}Nw$By)Wn9qM&37ocM2yAmaIkyYj{-`a7kMTR05-1CB z&FW3~8p$bc;CeodT?>w`)_9lXy<9f60Z!Nr#moJ(WFOIt!8zVd?5VJx=*gRCd=(#8 zJrP013zQx+Kf8E*FQG=?^WT3irSq)|!K8iNJ4mNGVguClWqM0c%PpTEkE>;V52WiJ pv&6q2NNQ0P5&ZdII35F@3#U3=LR&+WB`$Ud0Dcn*YlLEw{|AhuGfMyf diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index 2c6c319c3f507d1f2c4fe6f4352b41bbac967af4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3367 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 diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png deleted file mode 100644 index 28518ca76d7955da3b6567903d03d148f46a18ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1349 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 R{oDWm002ovPDHLkV1iW0{b~RJ diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png deleted file mode 100644 index 2f9542fcdadad0ca567900ccc3308c6c0d4147f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3176 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 Jq|ONb;J*ro9hU$A diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index 2c6c319c3f507d1f2c4fe6f4352b41bbac967af4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3367 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 diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index 416b3c4bbf5f5d133d1240033b9217e40820686b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4979 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 Q!!#l-wb!cE%GP230dQ@G0{{R3 diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png deleted file mode 100644 index 1ef9666360b4de3483e5960fd7c1a28ff15238f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2024 zcmVP)*|_#~FWhI`ivA z?LA{_%k-F9tn~nqGaM1H;ssJdNPvXHNH7PIkYrnp1G{fG2?7||fbhz2P}G)OU`L5dL#QjBPjVnoA3F@`rS ziWk5QVf!%YHXE!nm{g;B^_bySch7U&6N}{eKajt)KqN?B!ll!xK&#GRl6I;pC4EQh zWmom4TiQ>znX6c0EN5p)R-Q1LN`)Nd`1>*nM1lg5;D6h5DynGLW!DfR;uNbfD zO>`O*8pI0pXFAIC_M(;TDrB>~4jek~q@$1C7r*zlTqfgYm$pBZS$3d(@0TsO$$o6_ zqhCD|6BSIMP_{n0;_IK!y!By&YcU!P`h52qM^^Q1%5N*qHFXT?jpmskZ-HM^ogIL`n7lSiY?uCz2N^y(9wn;szFF$;t{P2ZBk>Kr@vIP-AKmv_Q z-S^HtdBx>JBYN!N#T$~5Rx{k6zXVq-Cxegt3PIOLjSDeOFl*bB8Q6GjtK!+xV}?mH zwh2j9lf0pQV9&O@H?K1=aAlT5REPmtgw8iGwXqG9HWyju=s!{#Uk}RMpdu8O>oR}kZGGs6& zGKk0Z!#x!@gdHCf+9gAEIwK{V;f?BfeVfueZFMHbWY9OQ1@E+aOux1C*c`29cz^#X ze_zIP8&?4Foh8Df^)eWqjR;pPa&n&BOg~+6!8`Vzto?Sgmlq8gFIuwZ(4LjAdpehg8$^1JD-+!Y+9Ru?2RAWTa*@2cS=d2Pzpr? zApf0@C1tw`k@ie;n3CUjGWYI;f@Nku;B#X>%f23f5z1W|G_qLBGrGL2&BstYj|W|cQgnr$|i zGH+^H6o6RnjmgXnVI{?Jk@3ck0jm|RJEcI11^O}5lX%ijRYD90sE4YW#@`KY776O;3y-{=3NtN54Kotq%EWWf;wK^SK=&R=lxMhyf|c}KqN?r%_D9@iC!M;Q<*bs71TFxgT~gQBY!5E8IV*jf)OJ27>||?nm6B<;)Nu zmX#U~L8x(PUruH|BgG&H`tMeu4->TtI2wmI&#_vm5-DajTRXe(e`|MXJ`L^(04w{{ zLVQ-hFpSJuFGk&$DU+oUZ=YcY6nlUFsjSp+`<}&WwUvIxjnKCDS0sDsUs(&Z(zN7Ds0T#dHSKy(K@2(jvGa?6$LNr5fiE;W3pG z`BM+3IBKntDlF(ayQ)bJOhQz?gFUMqoNbHM3OBS3%(=I2P$lVeB32~>LFEZGAW=PWEVimaEVit>S)Aovw-YUq= z#Mcl;I+ z<}X+jcv(By-KTNhOPNwDE-qiTIFuX0>KoAF{(Fbzj=lIB9M%mE>*k){-KXhxF|AOL zZ#0PpDMmC%F`_|=5e-s|Xpmw=gA^kgq!`g4#fZkgR_rfZYSzB;o5%_P0000NKl2DdTs|Lrcxt+(U(fF~ll zm#Lu)HS*5c%k?oeR0DqZASG5#)S`n5ttZ2z$ex;LRa;=4wQNoeTj%DK{G1o(b{rD+ zY?@(v^^WK{&uW(sa`j6gvh+2(3r%gALT5i%f@l zac=zCXD9u@a^>pIWnq~$YAZ3ed;Q**k9fI6$8&oTY^Dz;JhGZM#sAtGDrLPzC)gNW zyH!;kd7_ipV>wj;8=E$0=c`M4h}zog%HHnj%h}1qw1hjk^hVDAw13ac$+4@kZL;cQ zmQ&j99UVL$>e2BomJw>0tx6@!|DjIUyAk;3+f~=9`@ACZfh+4K&KEs@c`#rpVf(Cj zG9pAOpD^tq`Yave`)@d3vqmCr)*UaUN}ry-+qK;{GmxSkHwJW&oP`0eb`H%bv|9Fr zw)FXbb`o196!yI66!98vaN~X+L09@DhvkMI$h>=mt5mZ->hzmQuK(C6!UXgiLj9Oj zyZkf<%nJJ_gT%u+eJ9E<8Kd1Dkz#DXn(4C_{!db#rVw6Dd9pfAT8puP<(!)6Y1jvIXNBaF&lu8T&4lr?Dfu|nX zMhNwFYRl4~CZX!Z=P-78Gg^7!10Rbb}Y z*)IHLh>WLn&r-lsm)TW?w>lkKT?S@Yen-3X)*;_12iojD@y+91XN+0d%Z3JV(Jx3~ zLPx+F$s6P4i}v}ZXVH`&F3yT^8UXH=FxUPoT-=ZCnv~_M$Jq|+?hF$VGwfV}@$(e5 zeYHLWngU51ME#$d%DlUUZ#C5-s|Z_dF)1MxMGX;2swBGDfy1Qz*wv0AMbj;g@F4`= z-xV=F7_?lqU7+tjXx)gHf7v1)dE;WPPW?=<8j=etGP+T#g@{yvIJAISZHM5GM$<9| zM9&c^g4*)t84Bf5@e8Y{+B36G6BAO7wZT2UA-wS|8v~T`x>rKKwQAuZmLr=S zmzRXt*PQf*aLGUyd;S;@N6=fT$Yc?SFzlYOqXJRvz$cn_xjipy{ zpwDeR(wZfKQtolpi^~t`_oYpayp!?&rp65S1o@f0>Y8U-0zR{*9_v!|EO|d+m-|+U#t#@L zn0L+vo0FNqZpzTq@j2Bq#~M^6z@yW&q>!GhBC$!N-anO{DBAq9D~8GK)f_HcJMF_} z)$gred-D8$jE)WgM9&>;h9+Er694+ws-?F>gBA$am525N#9JjVs-ty$_JaWk&bR?< z9zJhF=U3Ks;MhLpSx$mytGj0%*-xWbnVszQU?LvG6WOzVmW?81G1gBg)!A`ud{YyF ztKU#@tkQR{_xN=92y0w)J&+ltP}YPC?$|aiOj>d|V5&%{ejaot$d`&fz2hNQAUd1z zW94>O0^h}Bmp!d4RAAS}Z~j?!i@!DgC7M?oJFGv><3@kx4Ai*n1vd#i!K9h{0iy|u z3@sufOza-@1>_Hdd7S!^xl-%kE|JF0lKO_r(Tq-9^IgIXE63A92?~@gEn+aVtp9Pm zpqq)}mj@mFvS+_BUh<=_%b{L^x9fr+Htaq<;ZJ>&;m|GWhG<02P@K;|djq!(&Pw6T z>7nG>Ye#=Z7Kk{}6dT`)$;yOI{BH14SDL5l#DV~@Sms7GsyXe=3XKdx$`0o8Qp6wS zURY3yrfAS0V`(|6x3HrL?M@u@ZQU;w`S{{toa%p=2&OVm&=mY|!uE(~!Zz>j^*j7} z5(!DbuHdjw(*q`s9V!5T7~RfF)89RTEfl3kJfx#`Uv2VHdku?(QqPDd68I(jeGk8% z@$z?%f@l}p;F9A8TH5@>#M)|3nSV1NrX*wvd?#{L>un3L-=xs6@c(qzv)v1u7b;S& zDgIzZ*{zwU_96Q54IeCQt#0v9c3fOgIu#l8m0Q-Lf-+$d3-Qm8v1#~R%ZDrFFEjbn zz)Q{qxZ9P;M$`Y%aGfBcPpH-v=21l#W2{&(r>w78v->`kqNl5RdvYXPTjpo;DEO^daJGcsxsQe77nyI|V|Gn%tJ8ob`f6mkA^G;Im$|bHB!K-Bl{GA zKw16kNjwtDy&2I4l!Hs1GYLgDbCJKhgEIvf$Cg+i0RHAtwV~H2n_FK_iOYC@zDsM; zizli0HRaBDqE183JrUet#(mW4N}VorwCVmxu_A4r`2ZL!K;4GtusY;68GipDKojn^C|(`E)}&@gZ8 zT5SK7T1RaKh3?nc`iNjF-hPM{ZR@kFtGngoXId#EP`cET+u70Znkp26p*gHMXZfofWLRM$Gxbz zQ){JG_wP@?C!A#WsxE)E*t|t6Zjw?(JZv0%g9omBQ8+n7{h3gph@$&2MHw4hvcT_~ zX2cS$Fzjp}30eJxY;0d}7T7=4{7K{x_oAywUX-dq1HiG5c}=7X|lY`%F)Q3EP4U;w5~Q^vT_Y_r6ecfwse_8ar7= z%}KrqIXLfaecW#mj3JQUQ|TI6`+Ev$_um@{C0^-vbuW^TbbE-`S77#6|r>u&(CyhMJB2MT3KlO5I$+aj)>m_hb} zH`y!}pWj&NzSajBv8Lt>ttKU7Ccw|Sd-kncNE_*!-|iKHzdkz&{diXclFS5nmBY#|_R%m)Ut?Sn!w2@8M z_^9%=;|u&Rc8COm)X1n+BMW8s<&dtxz<$K~UROX>c6{2B9aT6;k%V3^-(@Sf))03e zE7x&-4uP16TZ2rN7H`JkqdDzm1H?q*V1ayH>SD9@ss^^p`yMrVmQi(1O<_aGdX3bXT|Ly&f(E|<>GC252*hY z)R1Y~bjSqV-@nvX$BS4c)U|6YaCziPN1GphlKlm8&eOY9@kKbI9k6vkGUJ-#_VhO# z06XS41%-F*FzzOaspRiiLWg_2r9H-+Oi1K{DM8xmhBFrnFz%8tx{a`cm{JiG>5MXq zs#lIejz;bXBa{F>wa*Zs@yVW520U>|ePz@-e2}SFZseN3V@fxk<+&HM()x`_GeC2;*njV{ox_L%~vkUHW%at99CL2({5y1rXCpZew*s8jmi& z&xbqVgAZW1m9pf5+v=-kj;U2TO*{aKamVT#z1Fp79eP>=7IC%@p`HN66vM4)K}R75 zRK}S_#=QI$xtz2bxtzf}e(@)t&wDzTgtg7KBHvLg)*5x4pV_BUURkvGr?5cgY1gm* zgd6YB2GJo_sZ$328#kAEhxB59|7x`|Aj7`ha$8g7SO#w0MHrNIGx2~CDrg~W*GpH? z!n;`9X*~1agrGL50T&$Zm@_`jx%eo#xZB@D!Oo@MtX1IM7f{+9`E28Zm*TB#f1Ftf z;UbIaNTVGud>7-*d2grES(ZvOM|KOf7>ytKW+R^3Bc>0A9nBZLy4inxi|byITFck6 z*$$qQ>I=d>@Bf1ecLjO=-M>5tE`NEJE-O^otmJ-*JWh*27GH)Z-fH4=8@~{w^ts>s z?EJwi2c2e>V(Q6d8;P1`I^P9UzE738)Z2h~b#xQPK5U$D^%Vw_SDG?T*#mN_X74?b^|954Ylu zEidGMyAb=O_ty38rZ2zu5(qHO%-i?*EBXG8 z_xmKj`>{fjGH7In~L;j#Qc7K>p^vO=&@rEPie z_*PwSWqqI70xflG7l;dz!OPi)_pI5UpAZq^Ph1z15f{yki{|dnPtfX&74k>LrR{e+ z)Jxae1u`#57L)Pn^Wx(#rn7xK=2>rmzxVSy5}*5#=w@B-JC|zvRNBS0b5YDK$q!rh z$vaz96T=ozJDpB{Hfu$0dURoN)1}Xw+%;n7kW5_3yI%O?K#uofp5g7qI&~y7V_n4I zf*Z3&>pV+^2C@CwUc+jg-e8$eenDh_e%7qk%;J-rNv?>lAzlH=#~mk)OaFK0W-pq|jzx2hg=k4~P}UkP`XDA9j0sFww6bEXJ-)@dAFp_M=}q>g`2m^ONF((b2I{B6#~3*(cA-<|X-l zL7pHofH3KHo9e>V#=4e41R+R`7jR$NyYApNk*6mUpDIa-yn257Pfp!{Afm!F+S%80 zZH6}1t_nG@P4s!$J$!!AN*?;3+t@6P1@aI}ZkERG%oF0{5CosST=(f0t%RjeI{P#Q zA5{P8dfTP9wyawng3pkbDLA%2VHE7(E;$$eW_$3$>|pxFYwSWvEL8*-p2*0^-l${uXSJ-1X5nYkRT5K#sQkGyoI?CBuXL*RBEw z(ujJ-`8agWZ$AF#1~DI)#+XdTu>;Ac-mkVrQbeJCzMf9%*(eb(8FUE#e#Xj7js)^3 z+EhjpxDemd6OuJ%4%$4hHfaKF27=ucN z^8Av7!Pq42wDDr`cOReLj1A^x#JpG3fPT(Oi=xx*x<-4ax_@X2|7cJWzr}gjGvT@s z0S$Ll8m)mF;DZfjrT%x#*dmPuI&;GvmAtVZK@hBoXeE!!@zzZJXNxDn4af?4H{qi} zNnhMyN~1NnZbSfr&}y0oc5RHu24ndF5h4CVqq?oxD}em9&4Z)k`hPtd7p>&kf(!;d zD=n%_)`gcu5Ttybk_6D_&N5G`8kB$}oleioj47+?l8V8_qgtVSGDnolyRnk!&@Gd7 zMTc{u?HBWo-ih8p;!`UqshpH~LG!FpX58dUAPa3e-C^Q;vV0a20T{mlc z-#jX@%m1{8uMmI z9MfWXWB&^~60xZ}^Mu){cDvl^8I$6!!wnfI*?e#0ko^{{Po-VLYm2G|g-Fk~A7^XjFINT;=@Qyb#K( zyPQbEFoOSC<&8=wl5HKMqZ4{3Pjth(kjnZ#qsa=4LmT(I$MA<~xuXBX;q?wHtRvX3 zVsV3{-e76IKZ0NVQLs~vjn)T`XJ*Zg4q{Fg4;1&j)v9S4a3onrbiHDQ;M;eGHf;cJ zI?%QEUe}oO$GJzcweIvQQhwO7r`zlC zGZ$;{*E2R?7&&sfqTs0H$i8GBZx#f>H>$e}KB&fDcHnX6o90qkSE;NkjOS;y!ef&J z?=S!$7&-T8{YO_7p+SC{DZ`wv8*I4$b@~Wy!Elbr4D}Ba9RHo*e#svIN|G#4l4OCB yBny-zS)e4z0wqZnC`qzFNs5jxsBEsg(G;K&c!+78&*I;J{lyik(K>o3N* zl^W0Xq?fh$mQ{tcmWI2Lj_%ewTY2g#I`wDy`m>Hu?6!PU z?3_Mzfe?l6C)8=ZPt**Z(hCEf73pwMsZ$%b_VdZ~)%>~hyTbQi;jvDX!1G<)Jj36H z9<3E=0|)nX+g9XAn&N3uL1zKDBN9P#o>;04<^M2u*a0Y2-;uTy5ZC4BL67pIN7ntvo8>6D>y9%w#?bImAe^! z5~bUjWma0L(9~KzGAbGtSzgt3ntxbyev)SMlJVWyskbA{Du;qJt{c2dkBs;pUR}Tq z8=UZ^!2Nr3W~;_lCkKM+^55psSdfKU8v#|Q-HvAl&R_V>1+ERCJx)FId|w}o3{>q_ zQ)ME@r`KvA;3)1naLBtY+3Y>zs-o}3T)$fa`ZMm)tEAqqqdsj~q|1h7! zoQQ5vj_%_86b?H#jZv0Tl6YB)k@H$-k9Z=+r1d{-dr{(t>C|OBA@WP6iQkL4rg4~O}UD68@VB~Ag{&HxZD7*T1D=nXTMTb81 z?SJHLmeZVXPRDk(lj(K2&>RjOFOuMn8fUhh7tSMd)gC^#Dr>9%^<9<+m1R7Jojb=c zU%sIm?xz#-U;SIL^J`&UF(i*BvT%FPr2$`Dj1E)Xtm&Rnx6HIF&src~<_=Nu* z9)(8Mg}1?XXZ|4f52%gH*>~5&M5Or4;?=$;TvCPXTa%{WHOTkRaGyCU_NK%*-f%oh4_aZ#poptOQ@>yd6Km`J*xfo&*k)} zr`Vc!%;Fss_mgi*=B)G1Q}x0)C0{SZ=L8ob$HqU?mySf`%mzM_31#)_4+MRF0XDZMg07G0Q zv!vRNdFzNKGo%-c)GK(}0!oOn2p7bTA#tuMI{NxB4yg9yBY)sv`Bn?6J-a^5Jl zRMX|NVIOl9p<1LS-y^Y8{jD5wxsp;;Z%umVfrtZeirkPtVYGyX#Af(LPvZ_S2$j3$2{AJ-LU6&F3L zfJn!n1QXFV>rbAY`%^`0g>TEJFAVI&lA@mL3yplc9c%*|sF#&6_VP25A8)bJLWpn! zB$p(_wl#`<2lE9DOb)3;J(Y5^Bk!vPmF@4d$WOAXnve)dpoTrh%iM~YFSr?^M10SO zW4xF!X&tCpQ-g%xzf}hhUYRB;qd77{O`eC8ed9Adum9W}hwT~3%&;}I=i9MyAnqoK zi{Rg^IcT(0sfkuJ7XDPwY1t0&ifI8Foh1xAKA~<<&NeN%F=NnhtttE5)P1k{@cu)0 zA0p|CZ0idxB@0H>T4O1W@$R(+uh{sw>GbSkU1z)VO~P>O2C;p5d2I7uH#9#s%n2&R z`h@~8}PO3n)d+AK^u|M^V+ z=oI21@}`NrQ-z8!@$@n0a|(+v-v-e#%zHuySE)z~9%l?YzQ25BKXQTWE*9u>0BeIh z1A$2`jL&!>WS<1x_aj%c=nxT%0`mm~UnKxmX-1^HBiUaA2g*=aBOU%$d^H zt;FMA;HLgNqB?C8V7RY|4lKn|)HIpIrlbAe#1(j+7phUP}DusypmdP1UFEbLk zYa=U+f(%8lcsZS5Kxl<>!pK9NyX>|TvU1DU0hevttc;fz5>iT5!fwPenhX=63;;&@ z*qFo071zNp8`Bs!$G$@=o2;rh|0QMUGIEM3?2BeJzl(Q-?5r|90f5i1h1CTSmK)=4 zrm_=%6N2trz&vuj+bTExK7$0lw`G*(&_5Sd9}3G5*(sNtDpP$pp_ z$**1$2j>!lvz`e8-74e5T)bQ>N33z8sR|g%C&?nv|_?&(W+ z^TEq|VQokMNCv;Jg`~qZu%)hqV{cl8Gg=GPXPpR}+C7W|L(fECX+uluAZTh+{#9ui=XZ#D^5wxuP7Pb{KWy>oap}^{N zl2zxok>m%PLrxM8y20pt3_MA~T?d;`@rY^f>uZLl{vblfV;uEpK1CbS+0_ z-SCnw&xdkC-d_Yer-^vz5QqRwS&_vQ`0OO@?>3RKx}wa*_7UMG&Qn%Uw4O9^XP0ZR z^OOLNK&Fd4egIeVnXj~G-mZyM#^a}4ScWfsaMeN*VV4-pSHt}f3#Zd5vly>bvM7;I z3|G}NxH|&HibmmjPyzx+l^l_*s3#<<=MGv!HQeyW@N{8dmPJ{ll7DrUV?bcU2e<)g=*MgH6qau09u;aC~M75X)V)^M%K#%3m(el?Omk~fby%I zP+XDmfz|*h_nx7A9?9n~a%KT^{7v7IJ3e`*cdag8Gk{+5j*E;Ln>)FtXu+|~!bd5N zY%tk9EX-_7WVIWZ-nOBxl*D{M&qTk3g4Uirxd6pW{cnmrH!2LXl=b8`x0 zsT&#LdcqLixaF$l=7bF4j7(cefO!asA5&81u=_?WC2B7hWbP87<9ixcLmu89`=BHS zJ0n7OdCc@!w#aUs1Q~Z%8Q;NhcQCpMe4S4DmFt%v@+m<7PEDdiBRGhrtNH2X_Jt+< z!|T$D{Q`q=A@;SIoX_^(&Z1c=v$V=;cafqK8o7bNNv67S*9UJo{p<^W?Uh)Z*_BVV zu(5JRI1XH{?7vW)rCrM?GoH2PDtF)7w?->KlOsa$@=F%{p~`9jq_r_k)|YfQ>`oJl-Ja^JQ}U zE77{m0p1cXGviw89Md-D%zRdSNAA=P@nb>c3Fxj2m?I>q0}@`$?pQJTci=zw4j9)) z+G$kTsg3O#BSuW4FA9jX42FzM_BUY9?iha*HGqld>l z;iF18WIAGd5f?tj=3*Wc$xbevBXmVBl}*%|#y_i^^a3LsT~~Jd|6*hQt34in7&NUe zCCp-SzSNmwSQ#L0WI?CPxV@`GD@Ga$Q8kd|y01!ORQWJQlgE8>TD2F${>tNE6&?6| z>L^LnmKte`teF=&ZgnIPoL4S3K0PgB*?P^m207S!QCmBZu?(~`FtRg1A?<%Gpu%=| zAneNKhZdD!pVux{LAWF4$QelvM)1-vG_Py*0`k&$ki0;K*2S%|Nn+mFq4@_dgQLLV+4~|v2m3)`J5*ZAnFaRSfsErw*b<6^zhDhr_KaPlpg(P)6H$+ z^6fzmC%mj1J9Q3+1*8r8JI4XzbjsLv+&q8)$Yc#LFFQH?-+)N>=; zSfCC2miO7lzsTz%ai-P0p3I@Sc7~Yi)rBZKM;!O{xx9#!{PV!qw6-j(ZO8qPMP-#a z^#qkVj$K(3PV4<`C8IQF1$B+T zlv2{5_=~U5SYx_V__JrvvNk7d4X4dZbh}QrWi0}VVJQSG^dpM~Aj1#?`*m4l)}f_o z8#?+0z|KH**E1*gUJa|#;SF9wQCCh%5(k;4yTABhJnnaFH~mh%rL z!YU=EL$L8B2HC4=?NL~*P|8`pkaHQdGoZD~MB`0{A{3E%00aBcYh(QO`A{Ta1~B5Y zwIlo1SFyfCEnW81LCn5-a8Wqky<2RO177bu!&+Suo`=}P&T&`;n*|!xV=*3pr`S4K8B15FL9eZ{9n@3S>vvj;8R2QLg`Kt^FD9X7P7f{S?}t9p-$C-c3 z*wC`xRfyihkLKQlY7SPcI!N3Qa4o`oH5SVLGi;Yx#k&iYDdUq>vyQMji?=HA&m z4UUU!lSEAlOMdJ*rOY3zy9)Qg;aJhp@_EJ9v)b8^(ss>Nq`+ zjn-l(6~bzk3X3OGyHU1yy&STq_n`1FEc<0UADUiF67Iz`0A6vKx5Mbh0s1<2+-th- zZj$Tw>)tZ6@1g^L;Gur$U|=2qO=bi25@OQJ%s+)cxh-UdXA0eGbqaU}8UZrVg0;WH<~p&=?8>(-B#pbJe4x^w9U}kk0+v-q`D}U!U>PlM|UOtwy!3+gMpVqdFoXd-)Se z%wQJ;<2&BUrcGurRPjmF?pUFnm?r-&-&KSf97!AB9TzaB>d+EncwC!sVVw?7IXZ17 zvJ~~%@G6$4v6a0~f18JCD!ct}?62wm9^a;5hh~a$=@?BqtaGu6Fz4~%pESW<6s|fy zS1U6Zx5e8B)xnSCkGeXOORvsN?+a~2><^%;^0n&J>sB?9D}u?gGgNQU0wyQF&{63) z==pMImZ1I#W!4ED^;fpZ5UG(6tFd0jEQrWU%pm!=eitmB_qP;cgGFIV&YuJaLY+FN zMjVl>%uO`4Wu;Z)9y;2sJ)Kok>2*Dm(Mqmf+asFCMJAgY1zu4%2B;ntdM!;YOG>az z5^}dktVP@o<}-l^{Z6ifefQjI-Y6An;b|*0%w#pus^Ir&K%L-6`6Q2jQ-YS~9?;u? zzdSB$RmoQj6fT$w&DFqU(IdSvgx{s7;m-_yr5_6Dc=~{Wk^E%PUMF~zh%B5U?o*E8 z1T%a<$0DaRcia3X>@7fPn)I)xyv6vTPw+?2eR%%kNV59n)29XTpCmf#qxOZc-P|m( zUHsd#Xh! zsU}l5sDuc*s*XN6KAZ{MLKsA?-{v4j0(xA&}<2dd# z8e7vsB6OH+b}(NS?t1!VYCNO|+-k%wt9=e2b;w5=2$H{ONsKMsQ~15t)zx(4^v$oL z7ZFDze$bWid+Ufl8L^DcXa;K2q|Zwi4xm>l<@y|~&7+dofk2;ZfCu^x4({as`Rtq$ z8mpu+?`R^*)!247*-cRfxsoC%p_WYL_fB;b+Ib=#n=AfZfJL()HGVe4975+U1`fUN zt|y@~T+EuD4%e%F)!41JTA}@qN&Hy$6^4v!LJOtZ{*| zGn1Bu)YLsyAhS2%Y$99Kw0r=u0Yf`5!>=Q%(TuY9A);{IYJr$>{0@1zP3*d%#v(j* zMpvOjnbR~!5YV9ZkP}33C+?)q@WCz)K@w#;NGciMUw4opGi-?tRH^fVH%$m}Zg_2U9%nW}I zSv#nbNz;&+L}K<=Zcs~(H^QQ__x$n6*JJ=U8+(McNmK=ZhxzAf({Wo{b!(%+pr-KF zj7X8W3K^oHS$#BFoX-15)9wy3q@^ z?I(40sL&8ERU;{{Q>WH0XBvL>&z9YPOhE;s%xzM$ARs>@6WxxzNI4-WQ;|c%KRfJ1 zA7uE6-v@A|C+mOryJqKdX7`{%6SECvW`z`xltza)8MVUMSK%oM$6Dg3Vy;OS!A+Wg4gDA;VWJ zn0X)NsXEmy`zY`4FZb$vCip+I*#jx=S$tCkwqhd-j?Pd^IP>u_zu)%R``uprsIGSE zhp)akzV;AuUfnp7Z|IU^RHPqTGDwJ{UdiX0uVuKn^X%g2kDi&sC{QxP`2mw%q)xaw zu4in+%Wj+WFbn$`>YKPXhauyz3?{+J>8tIWpk6v-dKg2C4%WSBl^nES(*Ksi6LV^8 zV)>8JU5aZxcGT5zTue!XfIznbWxY2`Nxv9_MdHiulj!P^-FLZbCo6bUOPxy~7IpQJ#&~KQmey3_B6Lx;Z zqHAB1jbOU>(XcI?y3w;IEF5-`w558TnA53}hK)Mgo&7_3lxx9<`c~UeaHMv?Ro(uc z?97SCYn6N1$oaHQJIPz4&GrcIcz7YAC9b|8$;?jIF~aQ>!4XH`Gso)Al_8 diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json deleted file mode 100644 index 0bedcf2f..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725b..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Base.lproj/LaunchScreen.storyboard b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f2e259c7..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Base.lproj/Main.storyboard b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c28516..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Info.plist b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Info.plist deleted file mode 100644 index 3dd22eac..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Krow Staff App MVP - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - staff_app_mvp - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Runner-Bridging-Header.h b/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Runner-Bridging-Header.h deleted file mode 100644 index 308a2a56..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/Runner/Runner-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import "GeneratedPluginRegistrant.h" diff --git a/apps/mobile/prototypes/staff_mobile_application/ios/RunnerTests/RunnerTests.swift b/apps/mobile/prototypes/staff_mobile_application/ios/RunnerTests/RunnerTests.swift deleted file mode 100644 index 86a7c3b1..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/ios/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Flutter -import UIKit -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/.guides/config.json b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/.guides/config.json deleted file mode 100644 index e37ed06f..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/.guides/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "description": "A set of guides for interacting with the generated firebase dataconnect sdk", - "mcpServers": { - "firebase": { - "command": "npx", - "args": ["-y", "firebase-tools@latest", "experimental:mcp"] - } - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/.guides/setup.md b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/.guides/setup.md deleted file mode 100644 index 4a3737fe..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/.guides/setup.md +++ /dev/null @@ -1,15 +0,0 @@ -# Setup - -This guide will walk you through setting up your environment to use the Firebase Data Connect SDK. Mostly using -documentation listed [here](https://firebase.google.com/docs/flutter/setup?platform=ios#install-cli-tools). - -1. Make sure you have the latest Firebase CLI tools installed. Follow the instructions [here](https://firebase.google.com/docs/cli#setup_update_cli) to install. -2. Log into your Firebase account: -```sh -firebase login -``` -3. Install the FlutterFire CLI by running the following command from any directory: -```sh -dart pub global activate flutterfire_cli -``` -4. Make sure the user has initialized Firebase already based on the instructions [here](https://firebase.google.com/docs/flutter/setup?platform=ios#initialize-firebase). diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/.guides/usage.md b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/.guides/usage.md deleted file mode 100644 index 28407bc2..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/.guides/usage.md +++ /dev/null @@ -1,31 +0,0 @@ -# Basic Usage - -```dart -ExampleConnector.instance.CreateMovie(createMovieVariables).execute(); -ExampleConnector.instance.UpsertUser(upsertUserVariables).execute(); -ExampleConnector.instance.AddReview(addReviewVariables).execute(); -ExampleConnector.instance.DeleteReview(deleteReviewVariables).execute(); -ExampleConnector.instance.ListMovies().execute(); -ExampleConnector.instance.ListUsers().execute(); -ExampleConnector.instance.ListUserReviews().execute(); -ExampleConnector.instance.GetMovieById(getMovieByIdVariables).execute(); -ExampleConnector.instance.SearchMovie(searchMovieVariables).execute(); - -``` - -## Optional Fields - -Some operations may have optional fields. In these cases, the Flutter SDK exposes a builder method, and will have to be set separately. - -Optional fields can be discovered based on classes that have `Optional` object types. - -This is an example of a mutation with an optional field: - -```dart -await ExampleConnector.instance.SearchMovie({ ... }) -.titleInput(...) -.execute(); -``` - -Note: the above example is a mutation, but the same logic applies to query operations as well. Additionally, `createMovie` is an example, and may not be available to the user. - diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/README.md b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/README.md deleted file mode 100644 index 2104decc..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/README.md +++ /dev/null @@ -1,446 +0,0 @@ -# dataconnect_generated SDK - -## Installation -```sh -flutter pub get firebase_data_connect -flutterfire configure -``` -For more information, see [Flutter for Firebase installation documentation](https://firebase.google.com/docs/data-connect/flutter-sdk#use-core). - -## Data Connect instance -Each connector creates a static class, with an instance of the `DataConnect` class that can be used to connect to your Data Connect backend and call operations. - -### Connecting to the emulator - -```dart -String host = 'localhost'; // or your host name -int port = 9399; // or your port number -ExampleConnector.instance.dataConnect.useDataConnectEmulator(host, port); -``` - -You can also call queries and mutations by using the connector class. -## Queries - -### ListMovies -#### Required Arguments -```dart -// No required arguments -ExampleConnector.instance.listMovies().execute(); -``` - - - -#### Return Type -`execute()` returns a `QueryResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -/// Result of a query request. Created to hold extra variables in the future. -class QueryResult extends OperationResult { - QueryResult(super.dataConnect, super.data, super.ref); -} - -final result = await ExampleConnector.instance.listMovies(); -ListMoviesData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -final ref = ExampleConnector.instance.listMovies().ref(); -ref.execute(); - -ref.subscribe(...); -``` - - -### ListUsers -#### Required Arguments -```dart -// No required arguments -ExampleConnector.instance.listUsers().execute(); -``` - - - -#### Return Type -`execute()` returns a `QueryResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -/// Result of a query request. Created to hold extra variables in the future. -class QueryResult extends OperationResult { - QueryResult(super.dataConnect, super.data, super.ref); -} - -final result = await ExampleConnector.instance.listUsers(); -ListUsersData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -final ref = ExampleConnector.instance.listUsers().ref(); -ref.execute(); - -ref.subscribe(...); -``` - - -### ListUserReviews -#### Required Arguments -```dart -// No required arguments -ExampleConnector.instance.listUserReviews().execute(); -``` - - - -#### Return Type -`execute()` returns a `QueryResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -/// Result of a query request. Created to hold extra variables in the future. -class QueryResult extends OperationResult { - QueryResult(super.dataConnect, super.data, super.ref); -} - -final result = await ExampleConnector.instance.listUserReviews(); -ListUserReviewsData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -final ref = ExampleConnector.instance.listUserReviews().ref(); -ref.execute(); - -ref.subscribe(...); -``` - - -### GetMovieById -#### Required Arguments -```dart -String id = ...; -ExampleConnector.instance.getMovieById( - id: id, -).execute(); -``` - - - -#### Return Type -`execute()` returns a `QueryResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -/// Result of a query request. Created to hold extra variables in the future. -class QueryResult extends OperationResult { - QueryResult(super.dataConnect, super.data, super.ref); -} - -final result = await ExampleConnector.instance.getMovieById( - id: id, -); -GetMovieByIdData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -String id = ...; - -final ref = ExampleConnector.instance.getMovieById( - id: id, -).ref(); -ref.execute(); - -ref.subscribe(...); -``` - - -### SearchMovie -#### Required Arguments -```dart -// No required arguments -ExampleConnector.instance.searchMovie().execute(); -``` - -#### Optional Arguments -We return a builder for each query. For SearchMovie, we created `SearchMovieBuilder`. For queries and mutations with optional parameters, we return a builder class. -The builder pattern allows Data Connect to distinguish between fields that haven't been set and fields that have been set to null. A field can be set by calling its respective setter method like below: -```dart -class SearchMovieVariablesBuilder { - ... - - SearchMovieVariablesBuilder titleInput(String? t) { - _titleInput.value = t; - return this; - } - SearchMovieVariablesBuilder genre(String? t) { - _genre.value = t; - return this; - } - - ... -} -ExampleConnector.instance.searchMovie() -.titleInput(titleInput) -.genre(genre) -.execute(); -``` - -#### Return Type -`execute()` returns a `QueryResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -/// Result of a query request. Created to hold extra variables in the future. -class QueryResult extends OperationResult { - QueryResult(super.dataConnect, super.data, super.ref); -} - -final result = await ExampleConnector.instance.searchMovie(); -SearchMovieData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -final ref = ExampleConnector.instance.searchMovie().ref(); -ref.execute(); - -ref.subscribe(...); -``` - -## Mutations - -### CreateMovie -#### Required Arguments -```dart -String title = ...; -String genre = ...; -String imageUrl = ...; -ExampleConnector.instance.createMovie( - title: title, - genre: genre, - imageUrl: imageUrl, -).execute(); -``` - - - -#### Return Type -`execute()` returns a `OperationResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -final result = await ExampleConnector.instance.createMovie( - title: title, - genre: genre, - imageUrl: imageUrl, -); -CreateMovieData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -String title = ...; -String genre = ...; -String imageUrl = ...; - -final ref = ExampleConnector.instance.createMovie( - title: title, - genre: genre, - imageUrl: imageUrl, -).ref(); -ref.execute(); -``` - - -### UpsertUser -#### Required Arguments -```dart -String username = ...; -ExampleConnector.instance.upsertUser( - username: username, -).execute(); -``` - - - -#### Return Type -`execute()` returns a `OperationResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -final result = await ExampleConnector.instance.upsertUser( - username: username, -); -UpsertUserData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -String username = ...; - -final ref = ExampleConnector.instance.upsertUser( - username: username, -).ref(); -ref.execute(); -``` - - -### AddReview -#### Required Arguments -```dart -String movieId = ...; -int rating = ...; -String reviewText = ...; -ExampleConnector.instance.addReview( - movieId: movieId, - rating: rating, - reviewText: reviewText, -).execute(); -``` - - - -#### Return Type -`execute()` returns a `OperationResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -final result = await ExampleConnector.instance.addReview( - movieId: movieId, - rating: rating, - reviewText: reviewText, -); -AddReviewData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -String movieId = ...; -int rating = ...; -String reviewText = ...; - -final ref = ExampleConnector.instance.addReview( - movieId: movieId, - rating: rating, - reviewText: reviewText, -).ref(); -ref.execute(); -``` - - -### DeleteReview -#### Required Arguments -```dart -String movieId = ...; -ExampleConnector.instance.deleteReview( - movieId: movieId, -).execute(); -``` - - - -#### Return Type -`execute()` returns a `OperationResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -final result = await ExampleConnector.instance.deleteReview( - movieId: movieId, -); -DeleteReviewData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -String movieId = ...; - -final ref = ExampleConnector.instance.deleteReview( - movieId: movieId, -).ref(); -ref.execute(); -``` - diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/add_review.dart b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/add_review.dart deleted file mode 100644 index fc78c415..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/add_review.dart +++ /dev/null @@ -1,139 +0,0 @@ -part of 'generated.dart'; - -class AddReviewVariablesBuilder { - String movieId; - int rating; - String reviewText; - - final FirebaseDataConnect _dataConnect; - AddReviewVariablesBuilder(this._dataConnect, {required this.movieId,required this.rating,required this.reviewText,}); - Deserializer dataDeserializer = (dynamic json) => AddReviewData.fromJson(jsonDecode(json)); - Serializer varsSerializer = (AddReviewVariables vars) => jsonEncode(vars.toJson()); - Future> execute() { - return ref().execute(); - } - - MutationRef ref() { - AddReviewVariables vars= AddReviewVariables(movieId: movieId,rating: rating,reviewText: reviewText,); - return _dataConnect.mutation("AddReview", dataDeserializer, varsSerializer, vars); - } -} - -@immutable -class AddReviewReviewUpsert { - final String userId; - final String movieId; - AddReviewReviewUpsert.fromJson(dynamic json): - - userId = nativeFromJson(json['userId']), - movieId = nativeFromJson(json['movieId']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final AddReviewReviewUpsert otherTyped = other as AddReviewReviewUpsert; - return userId == otherTyped.userId && - movieId == otherTyped.movieId; - - } - @override - int get hashCode => Object.hashAll([userId.hashCode, movieId.hashCode]); - - - Map toJson() { - Map json = {}; - json['userId'] = nativeToJson(userId); - json['movieId'] = nativeToJson(movieId); - return json; - } - - AddReviewReviewUpsert({ - required this.userId, - required this.movieId, - }); -} - -@immutable -class AddReviewData { - final AddReviewReviewUpsert review_upsert; - AddReviewData.fromJson(dynamic json): - - review_upsert = AddReviewReviewUpsert.fromJson(json['review_upsert']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final AddReviewData otherTyped = other as AddReviewData; - return review_upsert == otherTyped.review_upsert; - - } - @override - int get hashCode => review_upsert.hashCode; - - - Map toJson() { - Map json = {}; - json['review_upsert'] = review_upsert.toJson(); - return json; - } - - AddReviewData({ - required this.review_upsert, - }); -} - -@immutable -class AddReviewVariables { - final String movieId; - final int rating; - final String reviewText; - @Deprecated('fromJson is deprecated for Variable classes as they are no longer required for deserialization.') - AddReviewVariables.fromJson(Map json): - - movieId = nativeFromJson(json['movieId']), - rating = nativeFromJson(json['rating']), - reviewText = nativeFromJson(json['reviewText']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final AddReviewVariables otherTyped = other as AddReviewVariables; - return movieId == otherTyped.movieId && - rating == otherTyped.rating && - reviewText == otherTyped.reviewText; - - } - @override - int get hashCode => Object.hashAll([movieId.hashCode, rating.hashCode, reviewText.hashCode]); - - - Map toJson() { - Map json = {}; - json['movieId'] = nativeToJson(movieId); - json['rating'] = nativeToJson(rating); - json['reviewText'] = nativeToJson(reviewText); - return json; - } - - AddReviewVariables({ - required this.movieId, - required this.rating, - required this.reviewText, - }); -} - diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/create_movie.dart b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/create_movie.dart deleted file mode 100644 index abdd637c..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/create_movie.dart +++ /dev/null @@ -1,134 +0,0 @@ -part of 'generated.dart'; - -class CreateMovieVariablesBuilder { - String title; - String genre; - String imageUrl; - - final FirebaseDataConnect _dataConnect; - CreateMovieVariablesBuilder(this._dataConnect, {required this.title,required this.genre,required this.imageUrl,}); - Deserializer dataDeserializer = (dynamic json) => CreateMovieData.fromJson(jsonDecode(json)); - Serializer varsSerializer = (CreateMovieVariables vars) => jsonEncode(vars.toJson()); - Future> execute() { - return ref().execute(); - } - - MutationRef ref() { - CreateMovieVariables vars= CreateMovieVariables(title: title,genre: genre,imageUrl: imageUrl,); - return _dataConnect.mutation("CreateMovie", dataDeserializer, varsSerializer, vars); - } -} - -@immutable -class CreateMovieMovieInsert { - final String id; - CreateMovieMovieInsert.fromJson(dynamic json): - - id = nativeFromJson(json['id']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final CreateMovieMovieInsert otherTyped = other as CreateMovieMovieInsert; - return id == otherTyped.id; - - } - @override - int get hashCode => id.hashCode; - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - return json; - } - - CreateMovieMovieInsert({ - required this.id, - }); -} - -@immutable -class CreateMovieData { - final CreateMovieMovieInsert movie_insert; - CreateMovieData.fromJson(dynamic json): - - movie_insert = CreateMovieMovieInsert.fromJson(json['movie_insert']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final CreateMovieData otherTyped = other as CreateMovieData; - return movie_insert == otherTyped.movie_insert; - - } - @override - int get hashCode => movie_insert.hashCode; - - - Map toJson() { - Map json = {}; - json['movie_insert'] = movie_insert.toJson(); - return json; - } - - CreateMovieData({ - required this.movie_insert, - }); -} - -@immutable -class CreateMovieVariables { - final String title; - final String genre; - final String imageUrl; - @Deprecated('fromJson is deprecated for Variable classes as they are no longer required for deserialization.') - CreateMovieVariables.fromJson(Map json): - - title = nativeFromJson(json['title']), - genre = nativeFromJson(json['genre']), - imageUrl = nativeFromJson(json['imageUrl']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final CreateMovieVariables otherTyped = other as CreateMovieVariables; - return title == otherTyped.title && - genre == otherTyped.genre && - imageUrl == otherTyped.imageUrl; - - } - @override - int get hashCode => Object.hashAll([title.hashCode, genre.hashCode, imageUrl.hashCode]); - - - Map toJson() { - Map json = {}; - json['title'] = nativeToJson(title); - json['genre'] = nativeToJson(genre); - json['imageUrl'] = nativeToJson(imageUrl); - return json; - } - - CreateMovieVariables({ - required this.title, - required this.genre, - required this.imageUrl, - }); -} - diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/delete_review.dart b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/delete_review.dart deleted file mode 100644 index e62dd741..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/delete_review.dart +++ /dev/null @@ -1,129 +0,0 @@ -part of 'generated.dart'; - -class DeleteReviewVariablesBuilder { - String movieId; - - final FirebaseDataConnect _dataConnect; - DeleteReviewVariablesBuilder(this._dataConnect, {required this.movieId,}); - Deserializer dataDeserializer = (dynamic json) => DeleteReviewData.fromJson(jsonDecode(json)); - Serializer varsSerializer = (DeleteReviewVariables vars) => jsonEncode(vars.toJson()); - Future> execute() { - return ref().execute(); - } - - MutationRef ref() { - DeleteReviewVariables vars= DeleteReviewVariables(movieId: movieId,); - return _dataConnect.mutation("DeleteReview", dataDeserializer, varsSerializer, vars); - } -} - -@immutable -class DeleteReviewReviewDelete { - final String userId; - final String movieId; - DeleteReviewReviewDelete.fromJson(dynamic json): - - userId = nativeFromJson(json['userId']), - movieId = nativeFromJson(json['movieId']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final DeleteReviewReviewDelete otherTyped = other as DeleteReviewReviewDelete; - return userId == otherTyped.userId && - movieId == otherTyped.movieId; - - } - @override - int get hashCode => Object.hashAll([userId.hashCode, movieId.hashCode]); - - - Map toJson() { - Map json = {}; - json['userId'] = nativeToJson(userId); - json['movieId'] = nativeToJson(movieId); - return json; - } - - DeleteReviewReviewDelete({ - required this.userId, - required this.movieId, - }); -} - -@immutable -class DeleteReviewData { - final DeleteReviewReviewDelete? review_delete; - DeleteReviewData.fromJson(dynamic json): - - review_delete = json['review_delete'] == null ? null : DeleteReviewReviewDelete.fromJson(json['review_delete']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final DeleteReviewData otherTyped = other as DeleteReviewData; - return review_delete == otherTyped.review_delete; - - } - @override - int get hashCode => review_delete.hashCode; - - - Map toJson() { - Map json = {}; - if (review_delete != null) { - json['review_delete'] = review_delete!.toJson(); - } - return json; - } - - DeleteReviewData({ - this.review_delete, - }); -} - -@immutable -class DeleteReviewVariables { - final String movieId; - @Deprecated('fromJson is deprecated for Variable classes as they are no longer required for deserialization.') - DeleteReviewVariables.fromJson(Map json): - - movieId = nativeFromJson(json['movieId']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final DeleteReviewVariables otherTyped = other as DeleteReviewVariables; - return movieId == otherTyped.movieId; - - } - @override - int get hashCode => movieId.hashCode; - - - Map toJson() { - Map json = {}; - json['movieId'] = nativeToJson(movieId); - return json; - } - - DeleteReviewVariables({ - required this.movieId, - }); -} - diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/generated.dart b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/generated.dart deleted file mode 100644 index 580adbb3..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/generated.dart +++ /dev/null @@ -1,93 +0,0 @@ -library dataconnect_generated; -import 'package:firebase_data_connect/firebase_data_connect.dart'; -import 'package:flutter/foundation.dart'; -import 'dart:convert'; - -part 'create_movie.dart'; - -part 'upsert_user.dart'; - -part 'add_review.dart'; - -part 'delete_review.dart'; - -part 'list_movies.dart'; - -part 'list_users.dart'; - -part 'list_user_reviews.dart'; - -part 'get_movie_by_id.dart'; - -part 'search_movie.dart'; - - - - - - - -class ExampleConnector { - - - CreateMovieVariablesBuilder createMovie ({required String title, required String genre, required String imageUrl, }) { - return CreateMovieVariablesBuilder(dataConnect, title: title,genre: genre,imageUrl: imageUrl,); - } - - - UpsertUserVariablesBuilder upsertUser ({required String username, }) { - return UpsertUserVariablesBuilder(dataConnect, username: username,); - } - - - AddReviewVariablesBuilder addReview ({required String movieId, required int rating, required String reviewText, }) { - return AddReviewVariablesBuilder(dataConnect, movieId: movieId,rating: rating,reviewText: reviewText,); - } - - - DeleteReviewVariablesBuilder deleteReview ({required String movieId, }) { - return DeleteReviewVariablesBuilder(dataConnect, movieId: movieId,); - } - - - ListMoviesVariablesBuilder listMovies () { - return ListMoviesVariablesBuilder(dataConnect, ); - } - - - ListUsersVariablesBuilder listUsers () { - return ListUsersVariablesBuilder(dataConnect, ); - } - - - ListUserReviewsVariablesBuilder listUserReviews () { - return ListUserReviewsVariablesBuilder(dataConnect, ); - } - - - GetMovieByIdVariablesBuilder getMovieById ({required String id, }) { - return GetMovieByIdVariablesBuilder(dataConnect, id: id,); - } - - - SearchMovieVariablesBuilder searchMovie () { - return SearchMovieVariablesBuilder(dataConnect, ); - } - - - static ConnectorConfig connectorConfig = ConnectorConfig( - 'us-central1', - 'example', - 'client-krow-poc', - ); - - ExampleConnector({required this.dataConnect}); - static ExampleConnector get instance { - return ExampleConnector( - dataConnect: FirebaseDataConnect.instanceFor( - connectorConfig: connectorConfig, - sdkType: CallerSDKType.generated)); - } - - FirebaseDataConnect dataConnect; -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/get_movie_by_id.dart b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/get_movie_by_id.dart deleted file mode 100644 index 154704ac..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/get_movie_by_id.dart +++ /dev/null @@ -1,297 +0,0 @@ -part of 'generated.dart'; - -class GetMovieByIdVariablesBuilder { - String id; - - final FirebaseDataConnect _dataConnect; - GetMovieByIdVariablesBuilder(this._dataConnect, {required this.id,}); - Deserializer dataDeserializer = (dynamic json) => GetMovieByIdData.fromJson(jsonDecode(json)); - Serializer varsSerializer = (GetMovieByIdVariables vars) => jsonEncode(vars.toJson()); - Future> execute() { - return ref().execute(); - } - - QueryRef ref() { - GetMovieByIdVariables vars= GetMovieByIdVariables(id: id,); - return _dataConnect.query("GetMovieById", dataDeserializer, varsSerializer, vars); - } -} - -@immutable -class GetMovieByIdMovie { - final String id; - final String title; - final String imageUrl; - final String? genre; - final GetMovieByIdMovieMetadata? metadata; - final List reviews; - GetMovieByIdMovie.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - title = nativeFromJson(json['title']), - imageUrl = nativeFromJson(json['imageUrl']), - genre = json['genre'] == null ? null : nativeFromJson(json['genre']), - metadata = json['metadata'] == null ? null : GetMovieByIdMovieMetadata.fromJson(json['metadata']), - reviews = (json['reviews'] as List) - .map((e) => GetMovieByIdMovieReviews.fromJson(e)) - .toList(); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final GetMovieByIdMovie otherTyped = other as GetMovieByIdMovie; - return id == otherTyped.id && - title == otherTyped.title && - imageUrl == otherTyped.imageUrl && - genre == otherTyped.genre && - metadata == otherTyped.metadata && - reviews == otherTyped.reviews; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, title.hashCode, imageUrl.hashCode, genre.hashCode, metadata.hashCode, reviews.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['title'] = nativeToJson(title); - json['imageUrl'] = nativeToJson(imageUrl); - if (genre != null) { - json['genre'] = nativeToJson(genre); - } - if (metadata != null) { - json['metadata'] = metadata!.toJson(); - } - json['reviews'] = reviews.map((e) => e.toJson()).toList(); - return json; - } - - GetMovieByIdMovie({ - required this.id, - required this.title, - required this.imageUrl, - this.genre, - this.metadata, - required this.reviews, - }); -} - -@immutable -class GetMovieByIdMovieMetadata { - final double? rating; - final int? releaseYear; - final String? description; - GetMovieByIdMovieMetadata.fromJson(dynamic json): - - rating = json['rating'] == null ? null : nativeFromJson(json['rating']), - releaseYear = json['releaseYear'] == null ? null : nativeFromJson(json['releaseYear']), - description = json['description'] == null ? null : nativeFromJson(json['description']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final GetMovieByIdMovieMetadata otherTyped = other as GetMovieByIdMovieMetadata; - return rating == otherTyped.rating && - releaseYear == otherTyped.releaseYear && - description == otherTyped.description; - - } - @override - int get hashCode => Object.hashAll([rating.hashCode, releaseYear.hashCode, description.hashCode]); - - - Map toJson() { - Map json = {}; - if (rating != null) { - json['rating'] = nativeToJson(rating); - } - if (releaseYear != null) { - json['releaseYear'] = nativeToJson(releaseYear); - } - if (description != null) { - json['description'] = nativeToJson(description); - } - return json; - } - - GetMovieByIdMovieMetadata({ - this.rating, - this.releaseYear, - this.description, - }); -} - -@immutable -class GetMovieByIdMovieReviews { - final String? reviewText; - final DateTime reviewDate; - final int? rating; - final GetMovieByIdMovieReviewsUser user; - GetMovieByIdMovieReviews.fromJson(dynamic json): - - reviewText = json['reviewText'] == null ? null : nativeFromJson(json['reviewText']), - reviewDate = nativeFromJson(json['reviewDate']), - rating = json['rating'] == null ? null : nativeFromJson(json['rating']), - user = GetMovieByIdMovieReviewsUser.fromJson(json['user']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final GetMovieByIdMovieReviews otherTyped = other as GetMovieByIdMovieReviews; - return reviewText == otherTyped.reviewText && - reviewDate == otherTyped.reviewDate && - rating == otherTyped.rating && - user == otherTyped.user; - - } - @override - int get hashCode => Object.hashAll([reviewText.hashCode, reviewDate.hashCode, rating.hashCode, user.hashCode]); - - - Map toJson() { - Map json = {}; - if (reviewText != null) { - json['reviewText'] = nativeToJson(reviewText); - } - json['reviewDate'] = nativeToJson(reviewDate); - if (rating != null) { - json['rating'] = nativeToJson(rating); - } - json['user'] = user.toJson(); - return json; - } - - GetMovieByIdMovieReviews({ - this.reviewText, - required this.reviewDate, - this.rating, - required this.user, - }); -} - -@immutable -class GetMovieByIdMovieReviewsUser { - final String id; - final String username; - GetMovieByIdMovieReviewsUser.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - username = nativeFromJson(json['username']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final GetMovieByIdMovieReviewsUser otherTyped = other as GetMovieByIdMovieReviewsUser; - return id == otherTyped.id && - username == otherTyped.username; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, username.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['username'] = nativeToJson(username); - return json; - } - - GetMovieByIdMovieReviewsUser({ - required this.id, - required this.username, - }); -} - -@immutable -class GetMovieByIdData { - final GetMovieByIdMovie? movie; - GetMovieByIdData.fromJson(dynamic json): - - movie = json['movie'] == null ? null : GetMovieByIdMovie.fromJson(json['movie']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final GetMovieByIdData otherTyped = other as GetMovieByIdData; - return movie == otherTyped.movie; - - } - @override - int get hashCode => movie.hashCode; - - - Map toJson() { - Map json = {}; - if (movie != null) { - json['movie'] = movie!.toJson(); - } - return json; - } - - GetMovieByIdData({ - this.movie, - }); -} - -@immutable -class GetMovieByIdVariables { - final String id; - @Deprecated('fromJson is deprecated for Variable classes as they are no longer required for deserialization.') - GetMovieByIdVariables.fromJson(Map json): - - id = nativeFromJson(json['id']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final GetMovieByIdVariables otherTyped = other as GetMovieByIdVariables; - return id == otherTyped.id; - - } - @override - int get hashCode => id.hashCode; - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - return json; - } - - GetMovieByIdVariables({ - required this.id, - }); -} - diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/list_movies.dart b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/list_movies.dart deleted file mode 100644 index 4a67d768..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/list_movies.dart +++ /dev/null @@ -1,105 +0,0 @@ -part of 'generated.dart'; - -class ListMoviesVariablesBuilder { - - final FirebaseDataConnect _dataConnect; - ListMoviesVariablesBuilder(this._dataConnect, ); - Deserializer dataDeserializer = (dynamic json) => ListMoviesData.fromJson(jsonDecode(json)); - - Future> execute() { - return ref().execute(); - } - - QueryRef ref() { - - return _dataConnect.query("ListMovies", dataDeserializer, emptySerializer, null); - } -} - -@immutable -class ListMoviesMovies { - final String id; - final String title; - final String imageUrl; - final String? genre; - ListMoviesMovies.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - title = nativeFromJson(json['title']), - imageUrl = nativeFromJson(json['imageUrl']), - genre = json['genre'] == null ? null : nativeFromJson(json['genre']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListMoviesMovies otherTyped = other as ListMoviesMovies; - return id == otherTyped.id && - title == otherTyped.title && - imageUrl == otherTyped.imageUrl && - genre == otherTyped.genre; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, title.hashCode, imageUrl.hashCode, genre.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['title'] = nativeToJson(title); - json['imageUrl'] = nativeToJson(imageUrl); - if (genre != null) { - json['genre'] = nativeToJson(genre); - } - return json; - } - - ListMoviesMovies({ - required this.id, - required this.title, - required this.imageUrl, - this.genre, - }); -} - -@immutable -class ListMoviesData { - final List movies; - ListMoviesData.fromJson(dynamic json): - - movies = (json['movies'] as List) - .map((e) => ListMoviesMovies.fromJson(e)) - .toList(); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListMoviesData otherTyped = other as ListMoviesData; - return movies == otherTyped.movies; - - } - @override - int get hashCode => movies.hashCode; - - - Map toJson() { - Map json = {}; - json['movies'] = movies.map((e) => e.toJson()).toList(); - return json; - } - - ListMoviesData({ - required this.movies, - }); -} - diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/list_user_reviews.dart b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/list_user_reviews.dart deleted file mode 100644 index d6053f58..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/list_user_reviews.dart +++ /dev/null @@ -1,192 +0,0 @@ -part of 'generated.dart'; - -class ListUserReviewsVariablesBuilder { - - final FirebaseDataConnect _dataConnect; - ListUserReviewsVariablesBuilder(this._dataConnect, ); - Deserializer dataDeserializer = (dynamic json) => ListUserReviewsData.fromJson(jsonDecode(json)); - - Future> execute() { - return ref().execute(); - } - - QueryRef ref() { - - return _dataConnect.query("ListUserReviews", dataDeserializer, emptySerializer, null); - } -} - -@immutable -class ListUserReviewsUser { - final String id; - final String username; - final List reviews; - ListUserReviewsUser.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - username = nativeFromJson(json['username']), - reviews = (json['reviews'] as List) - .map((e) => ListUserReviewsUserReviews.fromJson(e)) - .toList(); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListUserReviewsUser otherTyped = other as ListUserReviewsUser; - return id == otherTyped.id && - username == otherTyped.username && - reviews == otherTyped.reviews; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, username.hashCode, reviews.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['username'] = nativeToJson(username); - json['reviews'] = reviews.map((e) => e.toJson()).toList(); - return json; - } - - ListUserReviewsUser({ - required this.id, - required this.username, - required this.reviews, - }); -} - -@immutable -class ListUserReviewsUserReviews { - final int? rating; - final DateTime reviewDate; - final String? reviewText; - final ListUserReviewsUserReviewsMovie movie; - ListUserReviewsUserReviews.fromJson(dynamic json): - - rating = json['rating'] == null ? null : nativeFromJson(json['rating']), - reviewDate = nativeFromJson(json['reviewDate']), - reviewText = json['reviewText'] == null ? null : nativeFromJson(json['reviewText']), - movie = ListUserReviewsUserReviewsMovie.fromJson(json['movie']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListUserReviewsUserReviews otherTyped = other as ListUserReviewsUserReviews; - return rating == otherTyped.rating && - reviewDate == otherTyped.reviewDate && - reviewText == otherTyped.reviewText && - movie == otherTyped.movie; - - } - @override - int get hashCode => Object.hashAll([rating.hashCode, reviewDate.hashCode, reviewText.hashCode, movie.hashCode]); - - - Map toJson() { - Map json = {}; - if (rating != null) { - json['rating'] = nativeToJson(rating); - } - json['reviewDate'] = nativeToJson(reviewDate); - if (reviewText != null) { - json['reviewText'] = nativeToJson(reviewText); - } - json['movie'] = movie.toJson(); - return json; - } - - ListUserReviewsUserReviews({ - this.rating, - required this.reviewDate, - this.reviewText, - required this.movie, - }); -} - -@immutable -class ListUserReviewsUserReviewsMovie { - final String id; - final String title; - ListUserReviewsUserReviewsMovie.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - title = nativeFromJson(json['title']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListUserReviewsUserReviewsMovie otherTyped = other as ListUserReviewsUserReviewsMovie; - return id == otherTyped.id && - title == otherTyped.title; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, title.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['title'] = nativeToJson(title); - return json; - } - - ListUserReviewsUserReviewsMovie({ - required this.id, - required this.title, - }); -} - -@immutable -class ListUserReviewsData { - final ListUserReviewsUser? user; - ListUserReviewsData.fromJson(dynamic json): - - user = json['user'] == null ? null : ListUserReviewsUser.fromJson(json['user']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListUserReviewsData otherTyped = other as ListUserReviewsData; - return user == otherTyped.user; - - } - @override - int get hashCode => user.hashCode; - - - Map toJson() { - Map json = {}; - if (user != null) { - json['user'] = user!.toJson(); - } - return json; - } - - ListUserReviewsData({ - this.user, - }); -} - diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/list_users.dart b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/list_users.dart deleted file mode 100644 index 5fead7eb..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/list_users.dart +++ /dev/null @@ -1,93 +0,0 @@ -part of 'generated.dart'; - -class ListUsersVariablesBuilder { - - final FirebaseDataConnect _dataConnect; - ListUsersVariablesBuilder(this._dataConnect, ); - Deserializer dataDeserializer = (dynamic json) => ListUsersData.fromJson(jsonDecode(json)); - - Future> execute() { - return ref().execute(); - } - - QueryRef ref() { - - return _dataConnect.query("ListUsers", dataDeserializer, emptySerializer, null); - } -} - -@immutable -class ListUsersUsers { - final String id; - final String username; - ListUsersUsers.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - username = nativeFromJson(json['username']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListUsersUsers otherTyped = other as ListUsersUsers; - return id == otherTyped.id && - username == otherTyped.username; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, username.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['username'] = nativeToJson(username); - return json; - } - - ListUsersUsers({ - required this.id, - required this.username, - }); -} - -@immutable -class ListUsersData { - final List users; - ListUsersData.fromJson(dynamic json): - - users = (json['users'] as List) - .map((e) => ListUsersUsers.fromJson(e)) - .toList(); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListUsersData otherTyped = other as ListUsersData; - return users == otherTyped.users; - - } - @override - int get hashCode => users.hashCode; - - - Map toJson() { - Map json = {}; - json['users'] = users.map((e) => e.toJson()).toList(); - return json; - } - - ListUsersData({ - required this.users, - }); -} - diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/search_movie.dart b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/search_movie.dart deleted file mode 100644 index 19e5f2d7..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/search_movie.dart +++ /dev/null @@ -1,167 +0,0 @@ -part of 'generated.dart'; - -class SearchMovieVariablesBuilder { - Optional _titleInput = Optional.optional(nativeFromJson, nativeToJson); - Optional _genre = Optional.optional(nativeFromJson, nativeToJson); - - final FirebaseDataConnect _dataConnect; - SearchMovieVariablesBuilder titleInput(String? t) { - _titleInput.value = t; - return this; - } - SearchMovieVariablesBuilder genre(String? t) { - _genre.value = t; - return this; - } - - SearchMovieVariablesBuilder(this._dataConnect, ); - Deserializer dataDeserializer = (dynamic json) => SearchMovieData.fromJson(jsonDecode(json)); - Serializer varsSerializer = (SearchMovieVariables vars) => jsonEncode(vars.toJson()); - Future> execute() { - return ref().execute(); - } - - QueryRef ref() { - SearchMovieVariables vars= SearchMovieVariables(titleInput: _titleInput,genre: _genre,); - return _dataConnect.query("SearchMovie", dataDeserializer, varsSerializer, vars); - } -} - -@immutable -class SearchMovieMovies { - final String id; - final String title; - final String? genre; - final String imageUrl; - SearchMovieMovies.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - title = nativeFromJson(json['title']), - genre = json['genre'] == null ? null : nativeFromJson(json['genre']), - imageUrl = nativeFromJson(json['imageUrl']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final SearchMovieMovies otherTyped = other as SearchMovieMovies; - return id == otherTyped.id && - title == otherTyped.title && - genre == otherTyped.genre && - imageUrl == otherTyped.imageUrl; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, title.hashCode, genre.hashCode, imageUrl.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['title'] = nativeToJson(title); - if (genre != null) { - json['genre'] = nativeToJson(genre); - } - json['imageUrl'] = nativeToJson(imageUrl); - return json; - } - - SearchMovieMovies({ - required this.id, - required this.title, - this.genre, - required this.imageUrl, - }); -} - -@immutable -class SearchMovieData { - final List movies; - SearchMovieData.fromJson(dynamic json): - - movies = (json['movies'] as List) - .map((e) => SearchMovieMovies.fromJson(e)) - .toList(); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final SearchMovieData otherTyped = other as SearchMovieData; - return movies == otherTyped.movies; - - } - @override - int get hashCode => movies.hashCode; - - - Map toJson() { - Map json = {}; - json['movies'] = movies.map((e) => e.toJson()).toList(); - return json; - } - - SearchMovieData({ - required this.movies, - }); -} - -@immutable -class SearchMovieVariables { - late final OptionaltitleInput; - late final Optionalgenre; - @Deprecated('fromJson is deprecated for Variable classes as they are no longer required for deserialization.') - SearchMovieVariables.fromJson(Map json) { - - - titleInput = Optional.optional(nativeFromJson, nativeToJson); - titleInput.value = json['titleInput'] == null ? null : nativeFromJson(json['titleInput']); - - - genre = Optional.optional(nativeFromJson, nativeToJson); - genre.value = json['genre'] == null ? null : nativeFromJson(json['genre']); - - } - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final SearchMovieVariables otherTyped = other as SearchMovieVariables; - return titleInput == otherTyped.titleInput && - genre == otherTyped.genre; - - } - @override - int get hashCode => Object.hashAll([titleInput.hashCode, genre.hashCode]); - - - Map toJson() { - Map json = {}; - if(titleInput.state == OptionalState.set) { - json['titleInput'] = titleInput.toJson(); - } - if(genre.state == OptionalState.set) { - json['genre'] = genre.toJson(); - } - return json; - } - - SearchMovieVariables({ - required this.titleInput, - required this.genre, - }); -} - diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/upsert_user.dart b/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/upsert_user.dart deleted file mode 100644 index f797b726..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/dataconnect_generated/upsert_user.dart +++ /dev/null @@ -1,122 +0,0 @@ -part of 'generated.dart'; - -class UpsertUserVariablesBuilder { - String username; - - final FirebaseDataConnect _dataConnect; - UpsertUserVariablesBuilder(this._dataConnect, {required this.username,}); - Deserializer dataDeserializer = (dynamic json) => UpsertUserData.fromJson(jsonDecode(json)); - Serializer varsSerializer = (UpsertUserVariables vars) => jsonEncode(vars.toJson()); - Future> execute() { - return ref().execute(); - } - - MutationRef ref() { - UpsertUserVariables vars= UpsertUserVariables(username: username,); - return _dataConnect.mutation("UpsertUser", dataDeserializer, varsSerializer, vars); - } -} - -@immutable -class UpsertUserUserUpsert { - final String id; - UpsertUserUserUpsert.fromJson(dynamic json): - - id = nativeFromJson(json['id']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final UpsertUserUserUpsert otherTyped = other as UpsertUserUserUpsert; - return id == otherTyped.id; - - } - @override - int get hashCode => id.hashCode; - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - return json; - } - - UpsertUserUserUpsert({ - required this.id, - }); -} - -@immutable -class UpsertUserData { - final UpsertUserUserUpsert user_upsert; - UpsertUserData.fromJson(dynamic json): - - user_upsert = UpsertUserUserUpsert.fromJson(json['user_upsert']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final UpsertUserData otherTyped = other as UpsertUserData; - return user_upsert == otherTyped.user_upsert; - - } - @override - int get hashCode => user_upsert.hashCode; - - - Map toJson() { - Map json = {}; - json['user_upsert'] = user_upsert.toJson(); - return json; - } - - UpsertUserData({ - required this.user_upsert, - }); -} - -@immutable -class UpsertUserVariables { - final String username; - @Deprecated('fromJson is deprecated for Variable classes as they are no longer required for deserialization.') - UpsertUserVariables.fromJson(Map json): - - username = nativeFromJson(json['username']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final UpsertUserVariables otherTyped = other as UpsertUserVariables; - return username == otherTyped.username; - - } - @override - int get hashCode => username.hashCode; - - - Map toJson() { - Map json = {}; - json['username'] = nativeToJson(username); - return json; - } - - UpsertUserVariables({ - required this.username, - }); -} - diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/main.dart b/apps/mobile/prototypes/staff_mobile_application/lib/main.dart deleted file mode 100644 index b62f5adf..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/main.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:firebase_core/firebase_core.dart'; -import 'package:flutter/foundation.dart' show kIsWeb; -import 'theme.dart'; -import 'router.dart'; -import 'widgets/web_mobile_frame.dart'; - -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - //await Firebase.initializeApp(); - - const app = AppRoot(); - - runApp(ProviderScope(child: kIsWeb ? const WebMobileFrame(child: app) : app)); -} - -class AppRoot extends ConsumerWidget { - const AppRoot({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return MaterialApp.router( - title: 'Krow Staff App', - theme: AppTheme.lightTheme, - routerConfig: router, - debugShowCheckedModeBanner: false, - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/models/shift.dart b/apps/mobile/prototypes/staff_mobile_application/lib/models/shift.dart deleted file mode 100644 index d1864145..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/models/shift.dart +++ /dev/null @@ -1,59 +0,0 @@ -class Shift { - final String id; - final String title; - final String clientName; - final String? logoUrl; - final double hourlyRate; - final String location; - final String locationAddress; - final String date; - final String startTime; - final String endTime; - final String createdDate; - final bool? tipsAvailable; - final bool? travelTime; - final bool? mealProvided; - final bool? parkingAvailable; - final bool? gasCompensation; - final String? description; - final String? instructions; - final List? managers; - final double? latitude; - final double? longitude; - final String? status; - final int? durationDays; // For multi-day shifts - - Shift({ - required this.id, - required this.title, - required this.clientName, - this.logoUrl, - required this.hourlyRate, - required this.location, - required this.locationAddress, - required this.date, - required this.startTime, - required this.endTime, - required this.createdDate, - this.tipsAvailable, - this.travelTime, - this.mealProvided, - this.parkingAvailable, - this.gasCompensation, - this.description, - this.instructions, - this.managers, - this.latitude, - this.longitude, - this.status, - this.durationDays, - }); -} - -class ShiftManager { - final String name; - final String phone; - final String? avatar; - - ShiftManager({required this.name, required this.phone, this.avatar}); -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/router.dart b/apps/mobile/prototypes/staff_mobile_application/lib/router.dart deleted file mode 100644 index e6287855..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/router.dart +++ /dev/null @@ -1,198 +0,0 @@ -import 'package:go_router/go_router.dart'; -import 'screens/auth/get_started_screen.dart'; -import 'screens/auth/phone_verification_screen.dart'; -import 'screens/auth/profile_setup_screen.dart'; -import 'screens/worker/worker_home_screen.dart'; -import 'screens/worker/shifts_screen.dart'; -import 'screens/worker/payments_screen.dart'; -import 'screens/worker/clock_in_screen.dart'; -import 'screens/worker/benefits_screen.dart'; -import 'screens/worker/availability_screen.dart'; -import 'screens/worker/earnings_screen.dart'; -import 'screens/worker/early_pay_screen.dart'; -import 'screens/worker/jobs_screen.dart'; -import 'screens/worker/worker_profile_screen.dart'; -import 'screens/worker/worker_profile/support/faqs_screen.dart'; -import 'screens/worker/worker_profile/support/privacy_screen.dart'; -import 'screens/worker/worker_profile/support/messages_screen.dart'; -import 'screens/worker/worker_profile/level_up/krow_university_screen.dart'; -import 'screens/worker/worker_profile/level_up/trainings_screen.dart'; -import 'screens/worker/worker_profile/level_up/leaderboard_screen.dart'; -import 'screens/worker/worker_profile/finances/bank_account_screen.dart'; -import 'screens/worker/worker_profile/finances/time_card_screen.dart'; -import 'screens/worker/worker_profile/compliance/documents_screen.dart'; -import 'screens/worker/worker_profile/compliance/certificates_screen.dart'; -import 'screens/worker/worker_profile/compliance/tax_forms_screen.dart'; -import 'screens/worker/worker_profile/compliance/taxforms/form_i9_screen.dart'; -import 'screens/worker/worker_profile/compliance/taxforms/form_w4_screen.dart'; -import 'screens/worker/worker_profile/onboarding/personal_info_screen.dart'; -import 'screens/worker/worker_profile/onboarding/emergency_contact_screen.dart'; -import 'screens/worker/worker_profile/onboarding/experience_screen.dart'; -import 'screens/worker/worker_profile/onboarding/attire_screen.dart'; -import 'screens/worker/shift_details_screen.dart'; -import 'widgets/scaffold_with_nav_bar.dart'; - -final router = GoRouter( - initialLocation: '/get-started', - routes: [ - GoRoute( - path: '/get-started', - builder: (context, state) => const GetStartedScreen(), - ), - GoRoute( - path: '/phone-verification', - builder: (context, state) { - final mode = state.uri.queryParameters['mode'] ?? 'signup'; - return PhoneVerificationScreen(mode: mode); - }, - ), - GoRoute( - path: '/profile-setup', - builder: (context, state) => const ProfileSetupScreen(), - ), - GoRoute( - path: '/benefits', - builder: (context, state) => const BenefitsScreen(), - ), - GoRoute( - path: '/availability', - builder: (context, state) => const AvailabilityScreen(), - ), - GoRoute( - path: '/earnings', - builder: (context, state) => const EarningsScreen(), - ), - GoRoute( - path: '/early-pay', - builder: (context, state) => const EarlyPayScreen(), - ), - GoRoute(path: '/jobs', builder: (context, state) => const JobsScreen()), - GoRoute(path: '/faqs', builder: (context, state) => const FAQsScreen()), - GoRoute( - path: '/privacy', - builder: (context, state) => const PrivacyScreen(), - ), - GoRoute( - path: '/messages', - builder: (context, state) => const MessagesScreen(), - ), - GoRoute( - path: '/krow-university', - builder: (context, state) => const KrowUniversityScreen(), - ), - GoRoute( - path: '/trainings', - builder: (context, state) => const TrainingsScreen(), - ), - GoRoute( - path: '/leaderboard', - builder: (context, state) => const LeaderboardScreen(), - ), - GoRoute( - path: '/bank-account', - builder: (context, state) => const BankAccountScreen(), - ), - GoRoute( - path: '/time-card', - builder: (context, state) => const TimeCardScreen(), - ), - GoRoute( - path: '/documents', - builder: (context, state) => const DocumentsScreen(), - ), - GoRoute( - path: '/certificates', - builder: (context, state) => const CertificatesScreen(), - ), - GoRoute( - path: '/tax-forms', - builder: (context, state) => const TaxFormsScreen(), - ), - GoRoute( - path: '/taxforms/i9', - builder: (context, state) => const FormI9Screen(), - ), - GoRoute( - path: '/taxforms/w4', - builder: (context, state) => const FormW4Screen(), - ), - GoRoute( - path: '/personal-info', - builder: (context, state) => const PersonalInfoScreen(), - ), - GoRoute( - path: '/emergency-contact', - builder: (context, state) => const EmergencyContactScreen(), - ), - GoRoute( - path: '/experience', - builder: (context, state) => const ExperienceScreen(), - ), - GoRoute(path: '/attire', builder: (context, state) => const AttireScreen()), - GoRoute( - path: '/shift-details/:id', - builder: (context, state) { - final id = state.pathParameters['id']!; - final shift = - state.extra - as dynamic; // Cast to dynamic first to avoid type issues if import is missing in router - return ShiftDetailsScreen(shiftId: id, shift: shift); - }, - ), - StatefulShellRoute.indexedStack( - builder: (context, state, navigationShell) { - return ScaffoldWithNavBar(navigationShell: navigationShell); - }, - branches: [ - // Index 0: Shifts - StatefulShellBranch( - routes: [ - GoRoute( - path: '/shifts', - builder: (context, state) { - final tab = state.uri.queryParameters['tab']; - return ShiftsScreen(initialTab: tab); - }, - ), - ], - ), - // Index 1: Payments - StatefulShellBranch( - routes: [ - GoRoute( - path: '/payments', - builder: (context, state) => const PaymentsScreen(), - ), - ], - ), - // Index 2: Home - StatefulShellBranch( - routes: [ - GoRoute( - path: '/worker-home', - builder: (context, state) => const WorkerHomeScreen(), - ), - ], - ), - // Index 3: Clock In - StatefulShellBranch( - routes: [ - GoRoute( - path: '/clock-in', - builder: (context, state) => const ClockInScreen(), - ), - ], - ), - // Index 4: Profile - StatefulShellBranch( - routes: [ - GoRoute( - path: '/worker-profile', - builder: (context, state) => const WorkerProfileScreen(), - ), - ], - ), - ], - ), - ], -); diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/auth/get_started_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/auth/get_started_screen.dart deleted file mode 100644 index e6100c9d..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/auth/get_started_screen.dart +++ /dev/null @@ -1,182 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:google_fonts/google_fonts.dart'; -import '../../theme.dart'; - -class GetStartedScreen extends StatelessWidget { - const GetStartedScreen({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFF1A2234), - body: SafeArea( - child: Column( - children: [ - const SizedBox(height: 32), - // Logo - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24.0), - child: Image.network( - 'https://qtrypzzcjebvfcihiynt.supabase.co/storage/v1/object/public/base44-prod/public/692e9622b387da7cdcd95980/29a493751_PNG3Krow.png', - height: 40, - ), - ), - - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // Hero Image - Container( - width: 288, - height: 288, - margin: const EdgeInsets.only(bottom: 32), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: const Color(0xFF3A4A5A).withOpacity(0.5), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: ClipOval( - child: Image.network( - 'https://images.unsplash.com/photo-1577219491135-ce391730fb2c?w=400&h=400&fit=crop&crop=faces', - fit: BoxFit.cover, - ), - ), - ), - ), - - // Pagination dots - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 24, - height: 8, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(4), - ), - ), - const SizedBox(width: 8), - Container( - width: 8, - height: 8, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.4), - borderRadius: BorderRadius.circular(4), - ), - ), - const SizedBox(width: 8), - Container( - width: 8, - height: 8, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.4), - borderRadius: BorderRadius.circular(4), - ), - ), - ], - ), - - const SizedBox(height: 32), - - // Text content - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24.0), - child: Column( - children: [ - RichText( - textAlign: TextAlign.center, - text: TextSpan( - style: GoogleFonts.instrumentSans( - fontSize: 30, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - children: const [ - TextSpan(text: 'Work, Grow, '), - TextSpan( - text: 'Elevate', - style: TextStyle(color: AppColors.krowYellow), - ), - ], - ), - ), - const SizedBox(height: 16), - Text( - 'Build your career in hospitality with flexibility and freedom.', - textAlign: TextAlign.center, - style: GoogleFonts.instrumentSans( - fontSize: 16, - color: Colors.grey[400], - height: 1.5, - ), - ), - ], - ), - ), - ], - ), - ), - - // Bottom buttons - Padding( - padding: const EdgeInsets.fromLTRB(24, 0, 24, 40), - child: Column( - children: [ - SizedBox( - width: double.infinity, - height: 56, - child: ElevatedButton( - onPressed: () { - // Navigate to PhoneVerification (Sign Up) - context.push('/phone-verification'); - }, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowYellow, - foregroundColor: const Color(0xFF1A2234), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28), - ), - textStyle: GoogleFonts.instrumentSans( - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - child: const Text('Sign Up'), - ), - ), - const SizedBox(height: 12), - SizedBox( - width: double.infinity, - height: 56, - child: OutlinedButton( - onPressed: () { - // Navigate to PhoneVerification (Log In) - context.push('/phone-verification?mode=login'); - }, - style: OutlinedButton.styleFrom( - side: const BorderSide(color: Colors.grey, width: 2), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28), - ), - textStyle: GoogleFonts.instrumentSans( - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - child: const Text('Log In'), - ), - ), - ], - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/auth/phone_verification_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/auth/phone_verification_screen.dart deleted file mode 100644 index c52a279c..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/auth/phone_verification_screen.dart +++ /dev/null @@ -1,486 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; - -class PhoneVerificationScreen extends StatefulWidget { - final String mode; - - const PhoneVerificationScreen({super.key, this.mode = 'signup'}); - - @override - State createState() => - _PhoneVerificationScreenState(); -} - -class _PhoneVerificationScreenState extends State { - String step = 'phone'; // phone, code - String phoneNumber = ''; - String countryCode = '+1'; - List code = ['', '', '', '', '', '']; - bool isLoading = false; - String error = ''; - int countdown = 0; - - final List _codeFocusNodes = List.generate( - 6, - (index) => FocusNode(), - ); - final List _codeControllers = List.generate( - 6, - (index) => TextEditingController(), - ); - - @override - void dispose() { - for (var node in _codeFocusNodes) { - node.dispose(); - } - for (var controller in _codeControllers) { - controller.dispose(); - } - super.dispose(); - } - - void _startTimer() { - if (countdown > 0) return; - setState(() { - countdown = 30; - }); - _tick(); - } - - void _tick() { - if (countdown > 0) { - Future.delayed(const Duration(seconds: 1), () { - if (mounted) { - setState(() { - countdown--; - }); - _tick(); - } - }); - } - } - - void _handleSendCode() async { - if (phoneNumber.length != 10) { - setState(() { - error = 'Please enter a valid 10-digit phone number'; - }); - return; - } - - setState(() { - isLoading = true; - error = ''; - }); - - await Future.delayed(const Duration(milliseconds: 1500)); - - if (mounted) { - setState(() { - isLoading = false; - step = 'code'; - }); - _startTimer(); - } - } - - void _handleVerifyCode() async { - String fullCode = code.join(''); - if (fullCode.length != 6) return; - - setState(() { - isLoading = true; - error = ''; - }); - - await Future.delayed(const Duration(milliseconds: 1500)); - - if (mounted) { - if (fullCode == '123456' || fullCode.length == 6) { - // Accept any 6 digit code for MVP - setState(() { - isLoading = false; - }); - if (widget.mode == 'login') { - context.go('/worker-home'); - } else { - context.go('/profile-setup'); - } - } else { - setState(() { - isLoading = false; - error = 'Invalid code. Please try again.'; - }); - } - } - } - - void _handleCodeChange(int index, String value) { - if (value.isNotEmpty && !RegExp(r'^\d*$').hasMatch(value)) return; - - setState(() { - code[index] = value; - error = ''; - }); - - if (value.isNotEmpty && index < 5) { - _codeFocusNodes[index + 1].requestFocus(); - } - - if (value.isNotEmpty && index == 5 && code.every((d) => d.isNotEmpty)) { - _handleVerifyCode(); - } - } - - void _handleResend() async { - if (countdown > 0) return; - setState(() { - isLoading = true; - }); - await Future.delayed(const Duration(seconds: 1)); - if (mounted) { - setState(() { - isLoading = false; - code = ['', '', '', '', '', '']; - for (var c in _codeControllers) c.clear(); - }); - _startTimer(); - } - } - - @override - Widget build(BuildContext context) { - // Specific colors for this screen - const Color bg = Color(0xFFF5F5F0); - const Color inputBg = Color(0xFFE8E8E0); - const Color textMain = Color(0xFF333F48); - const Color textSub = Color(0xFF666666); - - return Scaffold( - backgroundColor: bg, - appBar: AppBar( - backgroundColor: bg, - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.arrowLeft, color: textMain), - onPressed: () { - if (step == 'code') { - setState(() { - step = 'phone'; - code = ['', '', '', '', '', '']; - for (var c in _codeControllers) c.clear(); - }); - } else { - context.pop(); - } - }, - ), - title: Text( - 'Phone Verification', - style: TextStyle( - color: textMain, - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - centerTitle: true, - ), - body: SafeArea( - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 24.0, - vertical: 32.0, - ), - child: step == 'phone' - ? _buildPhoneStep(textMain, textSub, inputBg) - : _buildCodeStep(textMain, textSub), - ), - ), - Padding( - padding: const EdgeInsets.all(24.0), - child: Column( - children: [ - SizedBox( - width: double.infinity, - height: 56, - child: ElevatedButton( - onPressed: - (isLoading || - (step == 'phone' - ? phoneNumber.length != 10 - : code.any((d) => d.isEmpty))) - ? null - : (step == 'phone' - ? _handleSendCode - : _handleVerifyCode), - style: ElevatedButton.styleFrom( - backgroundColor: textMain, - foregroundColor: Colors.white, - disabledBackgroundColor: inputBg, - disabledForegroundColor: const Color(0xFF999999), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: isLoading - ? const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - color: Colors.white, - ), - ) - : Text( - step == 'phone' ? 'Send Code' : 'Continue', - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - ), - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Having trouble? ', - style: TextStyle(color: textSub, fontSize: 14), - ), - Text( - 'Contact Support', - style: TextStyle( - color: textMain, - fontWeight: FontWeight.w600, - fontSize: 14, - ), - ), - ], - ), - ], - ), - ), - ], - ), - ), - ); - } - - Widget _buildPhoneStep(Color textMain, Color textSub, Color inputBg) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Verify your phone number', - style: TextStyle( - color: textMain, - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 8), - Text( - 'We\'ll send you a verification code to get started.', - style: TextStyle(color: textSub, fontSize: 14), - ), - const SizedBox(height: 32), - Text('Phone Number', style: TextStyle(color: textSub, fontSize: 12)), - const SizedBox(height: 8), - Row( - children: [ - Container( - width: 100, - height: 48, - decoration: BoxDecoration( - color: inputBg, - borderRadius: BorderRadius.circular(8), - ), - alignment: Alignment.center, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text('🇺🇸', style: TextStyle(fontSize: 20)), - const SizedBox(width: 4), - Text(countryCode, style: TextStyle(color: textMain)), - ], - ), - ), - const SizedBox(width: 8), - Expanded( - child: Container( - height: 48, - decoration: BoxDecoration( - color: inputBg, - borderRadius: BorderRadius.circular(8), - ), - child: TextField( - keyboardType: TextInputType.phone, - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly, - LengthLimitingTextInputFormatter(10), - ], - onChanged: (value) { - setState(() { - phoneNumber = value; - error = ''; - }); - }, - style: TextStyle(color: textMain), - decoration: const InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 16), - hintText: 'Enter your number', - hintStyle: TextStyle(color: Color(0xFF999999)), - ), - ), - ), - ), - ], - ), - if (error.isNotEmpty) - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Text( - error, - style: const TextStyle(color: Colors.red, fontSize: 14), - ), - ), - ], - ); - } - - Widget _buildCodeStep(Color textMain, Color textSub) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Enter verification code', - style: TextStyle( - color: textMain, - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 8), - Text.rich( - TextSpan( - text: 'We sent a 6-digit code to ', - style: TextStyle(color: textSub, fontSize: 14), - children: [ - TextSpan( - text: '$countryCode $phoneNumber', - style: TextStyle(color: textMain, fontWeight: FontWeight.w600), - ), - const TextSpan(text: '. Enter it below to verify your account.'), - ], - ), - ), - const SizedBox(height: 32), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: List.generate(6, (index) { - return SizedBox( - width: 48, - height: 56, - child: TextField( - controller: _codeControllers[index], - focusNode: _codeFocusNodes[index], - keyboardType: TextInputType.number, - textAlign: TextAlign.center, - maxLength: 1, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w600, - color: textMain, - ), - decoration: InputDecoration( - counterText: '', - filled: true, - fillColor: Colors.white, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: error.isNotEmpty - ? Colors.red.withValues(alpha: 0.3) - : (code[index].isNotEmpty - ? textMain - : const Color(0xFFE0E0E0)), - width: 2, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide(color: textMain, width: 2), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide( - color: error.isNotEmpty - ? Colors.red.withValues(alpha: 0.3) - : (code[index].isNotEmpty - ? textMain - : const Color(0xFFE0E0E0)), - width: 2, - ), - ), - ), - onChanged: (value) => _handleCodeChange(index, value), - ), - ); - }), - ), - if (error.isNotEmpty) - Padding( - padding: const EdgeInsets.only(top: 16.0), - child: Center( - child: Text( - error, - style: const TextStyle(color: Colors.red, fontSize: 14), - ), - ), - ), - const SizedBox(height: 24), - Center( - child: GestureDetector( - onTap: _handleResend, - child: Text.rich( - TextSpan( - children: [ - TextSpan( - text: error.isNotEmpty ? '' : 'Didn\'t get the code? ', - style: TextStyle( - color: countdown > 0 - ? const Color(0xFF999999) - : Colors.red, - ), - ), - TextSpan( - text: countdown > 0 - ? 'Resend in ${countdown}s' - : 'Resend code', - style: TextStyle( - color: countdown > 0 - ? const Color(0xFF999999) - : Colors.red, - fontWeight: countdown > 0 - ? FontWeight.normal - : FontWeight.w600, - ), - ), - ], - ), - ), - ), - ), - ], - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/auth/profile_setup_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/auth/profile_setup_screen.dart deleted file mode 100644 index a2b20e41..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/auth/profile_setup_screen.dart +++ /dev/null @@ -1,796 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import '../../theme.dart'; -import '../../services/mock_service.dart'; - -class ProfileSetupScreen extends StatefulWidget { - const ProfileSetupScreen({super.key}); - - @override - State createState() => _ProfileSetupScreenState(); -} - -class _ProfileSetupScreenState extends State { - int _currentStep = 0; - bool _isCreatingProfile = false; - - // Form Data - String _fullName = ''; - String _bio = ''; - String? _photoUrl; - final List _preferredLocations = []; - double _maxDistanceMiles = 25; - final List _skills = []; - final List _industries = []; - - // Input Controllers - final TextEditingController _locationController = TextEditingController(); - - // Constants - static const List> _steps = [ - {'id': 'basic', 'title': 'Basic Info', 'icon': LucideIcons.user}, - {'id': 'location', 'title': 'Location', 'icon': LucideIcons.mapPin}, - {'id': 'experience', 'title': 'Experience', 'icon': LucideIcons.briefcase}, - ]; - - static const List _allSkills = [ - 'Food Service', - 'Bartending', - 'Warehouse', - 'Retail', - 'Events', - 'Customer Service', - 'Cleaning', - 'Security', - 'Driving', - 'Cooking', - ]; - - static const List _allIndustries = [ - 'Hospitality', - 'Food Service', - 'Warehouse', - 'Events', - 'Retail', - 'Healthcare', - ]; - - // Logic - void _handleNext() { - if (_currStepValid()) { - if (_currentStep < _steps.length - 1) { - setState(() => _currentStep++); - } else { - _submitProfile(); - } - } - } - - void _handleBack() { - if (_currentStep > 0) { - setState(() => _currentStep--); - } - } - - bool _currStepValid() { - switch (_currentStep) { - case 0: - return _fullName.trim().length >= 2; - case 1: - return _preferredLocations.isNotEmpty; - case 2: - return _skills.isNotEmpty; - default: - return true; - } - } - - Future _submitProfile() async { - setState(() => _isCreatingProfile = true); - - await mockService.createWorkerProfile({ - 'full_name': _fullName, - 'bio': _bio, - 'preferred_locations': _preferredLocations, - 'max_distance_miles': _maxDistanceMiles, - 'skills': _skills, - 'industries': _industries, - }); - - if (mounted) { - context.go('/worker-home'); - } - } - - void _addLocation() { - final loc = _locationController.text.trim(); - if (loc.isNotEmpty && !_preferredLocations.contains(loc)) { - setState(() { - _preferredLocations.add(loc); - _locationController.clear(); - }); - } - } - - void _removeLocation(String loc) { - setState(() { - _preferredLocations.remove(loc); - }); - } - - void _toggleSkill(String skill) { - setState(() { - if (_skills.contains(skill)) { - _skills.remove(skill); - } else { - _skills.add(skill); - } - }); - } - - void _toggleIndustry(String industry) { - setState(() { - if (_industries.contains(industry)) { - _industries.remove(industry); - } else { - _industries.add(industry); - } - }); - } - - @override - Widget build(BuildContext context) { - final double progress = (_currentStep + 1) / _steps.length; - - return Scaffold( - backgroundColor: Colors.white, - body: SafeArea( - child: Column( - children: [ - // Progress Bar - LinearProgressIndicator( - value: progress, - backgroundColor: Colors.grey[100], - color: AppColors.krowBlue, // #0032A0 - minHeight: 4, - ), - - // Header (Back + Step Count) - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (_currentStep > 0) - GestureDetector( - onTap: _handleBack, - child: const Row( - children: [ - Icon( - LucideIcons.arrowLeft, - size: 20, - color: AppColors.krowMuted, - ), - SizedBox(width: 8), - Text( - 'Back', - style: TextStyle( - color: AppColors.krowMuted, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ) - else - const SizedBox(width: 60), // Placeholder to keep alignment - Text( - 'Step ${_currentStep + 1} of ${_steps.length}', - style: const TextStyle( - color: AppColors.krowMuted, - fontSize: 14, - ), - ), - ], - ), - ), - - // Step Indicators - Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: List.generate(_steps.length, (index) { - final step = _steps[index]; - final isActive = index == _currentStep; - final isCompleted = index < _currentStep; - - Color bgColor; - Color iconColor; - if (isCompleted) { - bgColor = Colors.green; - iconColor = Colors.white; - } else if (isActive) { - bgColor = AppColors.krowBlue; - iconColor = Colors.white; - } else { - bgColor = Colors.grey[100]!; - iconColor = Colors.grey[400]!; - } - - return Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: bgColor, - shape: BoxShape.circle, - ), - child: Icon( - isCompleted - ? LucideIcons.check - : step['icon'] as IconData, - size: 20, - color: iconColor, - ), - ), - if (index < _steps.length - 1) - Container( - width: 30, - height: 2, - margin: const EdgeInsets.symmetric(horizontal: 4), - color: isCompleted ? Colors.green : Colors.grey[200], - ), - ], - ); - }), - ), - ), - - // Content Area - Expanded( - child: AnimatedSwitcher( - duration: const Duration(milliseconds: 300), - child: SingleChildScrollView( - key: ValueKey(_currentStep), - padding: const EdgeInsets.all(24), - child: _buildStepContent(), - ), - ), - ), - - // Footer - Container( - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - border: Border(top: BorderSide(color: Colors.grey[100]!)), - ), - child: SizedBox( - width: double.infinity, - height: 56, - child: ElevatedButton( - onPressed: (_currStepValid() && !_isCreatingProfile) - ? _handleNext - : null, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - disabledBackgroundColor: AppColors.krowBlue.withValues( - alpha: 0.5, - ), - ), - child: _isCreatingProfile - ? const SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator( - color: Colors.white, - strokeWidth: 2, - ), - ) - : Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - _currentStep == _steps.length - 1 - ? 'Complete Setup' - : 'Continue', - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - if (_currentStep < _steps.length - 1) ...const [ - SizedBox(width: 8), - Icon(LucideIcons.arrowRight, size: 20), - ], - ], - ), - ), - ), - ), - ], - ), - ), - ); - } - - Widget _buildStepContent() { - switch (_currentStep) { - case 0: - return _buildBasicInfoStep(); - case 1: - return _buildLocationStep(); - case 2: - return _buildExperienceStep(); - default: - return const SizedBox.shrink(); - } - } - - Widget _buildBasicInfoStep() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "Let's get to know you", - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - const Text( - "Tell us a bit about yourself", - style: TextStyle(fontSize: 16, color: AppColors.krowMuted), - ), - const SizedBox(height: 32), - - // Photo Upload - Center( - child: Stack( - children: [ - Container( - width: 112, - height: 112, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.grey[100], - border: Border.all(color: Colors.white, width: 4), - boxShadow: [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.1), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: _photoUrl != null - ? ClipOval( - child: Image.network(_photoUrl!, fit: BoxFit.cover), - ) - : const Icon( - LucideIcons.user, - size: 48, - color: Colors.grey, - ), - ), - Positioned( - bottom: 0, - right: 0, - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: AppColors.krowBlue, - shape: BoxShape.circle, - boxShadow: [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.2), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: const Icon( - LucideIcons.camera, - color: Colors.white, - size: 20, - ), - ), - ), - ], - ), - ), - const SizedBox(height: 32), - - // Full Name - const Text( - "Full Name *", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - TextField( - onChanged: (val) => setState(() => _fullName = val), - decoration: InputDecoration( - hintText: "John Smith", - hintStyle: TextStyle(color: Colors.grey[400]), - filled: true, - fillColor: Colors.white, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: BorderSide(color: Colors.grey[200]!), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: BorderSide(color: Colors.grey[200]!), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBlue), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - ), - ), - const SizedBox(height: 24), - - // Bio - const Text( - "Short Bio", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - TextField( - onChanged: (val) => setState(() => _bio = val), - decoration: InputDecoration( - hintText: "Experienced hospitality professional...", - hintStyle: TextStyle(color: Colors.grey[400]), - filled: true, - fillColor: Colors.white, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: BorderSide(color: Colors.grey[200]!), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: BorderSide(color: Colors.grey[200]!), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBlue), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - ), - ), - ], - ); - } - - Widget _buildLocationStep() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "Where do you want to work?", - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - const Text( - "Add your preferred work locations", - style: TextStyle(fontSize: 16, color: AppColors.krowMuted), - ), - const SizedBox(height: 32), - - // Add Location input - const Text( - "Add Location *", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - Row( - children: [ - Expanded( - child: TextField( - controller: _locationController, - onSubmitted: (_) => _addLocation(), - decoration: InputDecoration( - hintText: "City or ZIP code", - hintStyle: TextStyle(color: Colors.grey[400]), - filled: true, - fillColor: Colors.white, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: BorderSide(color: Colors.grey[200]!), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: BorderSide(color: Colors.grey[200]!), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBlue), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - ), - ), - ), - const SizedBox(width: 8), - SizedBox( - height: 48, - child: ElevatedButton( - onPressed: _addLocation, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - padding: const EdgeInsets.symmetric(horizontal: 24), - ), - child: const Text("Add"), - ), - ), - ], - ), - - const SizedBox(height: 16), - // Location Badges - if (_preferredLocations.isNotEmpty) - Wrap( - spacing: 8, - runSpacing: 8, - children: _preferredLocations.map((loc) { - return Container( - padding: const EdgeInsets.fromLTRB(12, 8, 8, 8), - decoration: BoxDecoration( - color: AppColors.krowBlue.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(20), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon( - LucideIcons.mapPin, - size: 14, - color: AppColors.krowBlue, - ), - const SizedBox(width: 6), - Text( - loc, - style: const TextStyle( - color: AppColors.krowBlue, - fontWeight: FontWeight.w500, - fontSize: 14, - ), - ), - const SizedBox(width: 6), - GestureDetector( - onTap: () => _removeLocation(loc), - child: const Icon( - LucideIcons.x, - size: 16, - color: AppColors.krowBlue, - ), - ), - ], - ), - ); - }).toList(), - ), - - const SizedBox(height: 32), - // Slider - Text( - "Max Distance: ${_maxDistanceMiles.round()} miles", - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - SliderTheme( - data: SliderTheme.of(context).copyWith( - activeTrackColor: AppColors.krowBlue, - inactiveTrackColor: Colors.grey[200], - thumbColor: AppColors.krowBlue, - overlayColor: AppColors.krowBlue.withValues(alpha: 0.1), - trackHeight: 6, - thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 10), - ), - child: Slider( - value: _maxDistanceMiles, - min: 5, - max: 50, - onChanged: (val) => setState(() => _maxDistanceMiles = val), - ), - ), - const Padding( - padding: EdgeInsets.symmetric(horizontal: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text("5 mi", style: TextStyle(color: Colors.grey, fontSize: 12)), - Text("50 mi", style: TextStyle(color: Colors.grey, fontSize: 12)), - ], - ), - ), - ], - ); - } - - Widget _buildExperienceStep() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "What are your skills?", - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - const Text( - "Select all that apply", - style: TextStyle(fontSize: 16, color: AppColors.krowMuted), - ), - const SizedBox(height: 32), - - // Skills - const Text( - "Skills *", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 12), - Wrap( - spacing: 8, - runSpacing: 8, - children: _allSkills.map((skill) { - final isSelected = _skills.contains(skill); - return GestureDetector( - onTap: () => _toggleSkill(skill), - child: AnimatedContainer( - duration: const Duration(milliseconds: 200), - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 10, - ), - decoration: BoxDecoration( - color: isSelected ? AppColors.krowBlue : Colors.white, - borderRadius: BorderRadius.circular(30), - border: Border.all( - color: isSelected ? AppColors.krowBlue : Colors.grey[300]!, - width: isSelected ? 0 : 1, - ), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (isSelected) - const Padding( - padding: EdgeInsets.only(right: 6), - child: Icon( - LucideIcons.check, - size: 16, - color: Colors.white, - ), - ), - Text( - skill, - style: TextStyle( - color: isSelected ? Colors.white : Colors.grey[700], - fontWeight: FontWeight.w500, - fontSize: 14, - ), - ), - ], - ), - ), - ); - }).toList(), - ), - - const SizedBox(height: 32), - // Industries - const Text( - "Preferred Industries", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 12), - Wrap( - spacing: 8, - runSpacing: 8, - children: _allIndustries.map((industry) { - final isSelected = _industries.contains(industry); - const activeBg = Color(0xFFF7E600); // React prop: bg-[#F7E600] - const activeText = Color(0xFF333F48); // React prop: text-[#333F48] - const activeBorder = Color(0xFFF7E600); - - return GestureDetector( - onTap: () => _toggleIndustry(industry), - child: AnimatedContainer( - duration: const Duration(milliseconds: 200), - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 10, - ), - decoration: BoxDecoration( - color: isSelected ? activeBg : Colors.white, - borderRadius: BorderRadius.circular(30), - border: Border.all( - color: isSelected ? activeBorder : Colors.grey[300]!, - width: isSelected ? 0 : 1, - ), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (isSelected) - const Padding( - padding: EdgeInsets.only(right: 6), - child: Icon( - LucideIcons.check, - size: 16, - color: activeText, - ), - ), - Text( - industry, - style: TextStyle( - color: isSelected ? activeText : Colors.grey[700], - fontWeight: FontWeight.w500, - fontSize: 14, - ), - ), - ], - ), - ), - ); - }).toList(), - ), - ], - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/availability_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/availability_screen.dart deleted file mode 100644 index 313b5d95..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/availability_screen.dart +++ /dev/null @@ -1,784 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:intl/intl.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; - -class AvailabilityScreen extends StatefulWidget { - const AvailabilityScreen({super.key}); - - @override - State createState() => _AvailabilityScreenState(); -} - -class _AvailabilityScreenState extends State { - late DateTime _currentWeekStart; - late DateTime _selectedDate; - - // Mock Availability State - // Map of day name (lowercase) to availability status - Map _availability = { - 'monday': true, - 'tuesday': true, - 'wednesday': true, - 'thursday': true, - 'friday': true, - 'saturday': false, - 'sunday': false, - }; - - // Map of day name to time slot map - Map> _timeSlotAvailability = { - 'monday': {'morning': true, 'afternoon': true, 'evening': true}, - 'tuesday': {'morning': true, 'afternoon': true, 'evening': true}, - 'wednesday': {'morning': true, 'afternoon': true, 'evening': true}, - 'thursday': {'morning': true, 'afternoon': true, 'evening': true}, - 'friday': {'morning': true, 'afternoon': true, 'evening': true}, - 'saturday': {'morning': false, 'afternoon': false, 'evening': false}, - 'sunday': {'morning': false, 'afternoon': false, 'evening': false}, - }; - - final List _dayNames = [ - 'sunday', - 'monday', - 'tuesday', - 'wednesday', - 'thursday', - 'friday', - 'saturday', - ]; - - final List> _timeSlots = [ - { - 'slotId': 'morning', - 'label': 'Morning', - 'timeRange': '4:00 AM - 12:00 PM', - 'icon': LucideIcons.sunrise, - 'bg': const Color(0xFFE6EBF9), // bg-[#0032A0]/10 - 'iconColor': const Color(0xFF0032A0), - }, - { - 'slotId': 'afternoon', - 'label': 'Afternoon', - 'timeRange': '12:00 PM - 6:00 PM', - 'icon': LucideIcons.sun, - 'bg': const Color(0xFFCCD6EC), // bg-[#0032A0]/20 - 'iconColor': const Color(0xFF0032A0), - }, - { - 'slotId': 'evening', - 'label': 'Evening', - 'timeRange': '6:00 PM - 12:00 AM', - 'icon': LucideIcons.moon, - 'bg': const Color(0xFFEBEDEE), // bg-[#333F48]/10 - 'iconColor': const Color(0xFF333F48), - }, - ]; - - @override - void initState() { - super.initState(); - final today = DateTime.now(); - // Calculate start of week (assuming week starts on Sunday based on typical calendar logic, - // but React code navigates based on diff. Let's match React logic: - // const diff = today.getDate() - day + (day === 0 ? -6 : 1); -> This suggests Monday start actually? - // React: day === 0 (Sun) ? -6 : 1. If today is Mon(1), 1-1+1 = 1 (Mon). If Sun(0), 0-0-6 = -6 (Prev Mon). - // So React week starts Monday. - - // Dart equivalent for Monday start: - final day = today.weekday; // Mon=1, Sun=7 - final diff = day - 1; - _currentWeekStart = today.subtract(Duration(days: diff)); - // Reset time to midnight - _currentWeekStart = DateTime( - _currentWeekStart.year, - _currentWeekStart.month, - _currentWeekStart.day, - ); - - _selectedDate = today; - } - - List _getWeekDates() { - return List.generate( - 7, - (index) => _currentWeekStart.add(Duration(days: index)), - ); - } - - String _formatDay(DateTime date) { - return DateFormat('EEE').format(date); - } - - bool _isToday(DateTime date) { - final now = DateTime.now(); - return date.year == now.year && - date.month == now.month && - date.day == now.day; - } - - bool _isSelected(DateTime date) { - return date.year == _selectedDate.year && - date.month == _selectedDate.month && - date.day == _selectedDate.day; - } - - void _navigateWeek(int direction) { - setState(() { - _currentWeekStart = _currentWeekStart.add(Duration(days: direction * 7)); - }); - } - - void _toggleDayAvailability(String dayName) { - setState(() { - _availability[dayName] = !(_availability[dayName] ?? false); - // React code also updates mutation. We mock this. - }); - } - - String _getDayKey(DateTime date) { - // DateTime.weekday: Mon=1...Sun=7. - // _dayNames array: 0=Sun, 1=Mon... - // React code: date.getDay() -> 0=Sun, 1=Mon. - // So we use date.weekday % 7 to match 0-6 index for Sunday-Saturday if we want to index _dayNames correctly? - // Wait, React uses: dayNames = ['sunday', 'monday', ...]. - // And getDay() returns 0 for Sunday. So dayNames[0] is 'sunday'. - // Dart weekday: 7 is Sunday. 7 % 7 = 0. - return _dayNames[date.weekday % 7]; - } - - void _toggleTimeSlot(String slotId) { - final dayKey = _getDayKey(_selectedDate); - final currentDaySlots = - _timeSlotAvailability[dayKey] ?? - {'morning': true, 'afternoon': true, 'evening': true}; - final newValue = !(currentDaySlots[slotId] ?? true); - - setState(() { - _timeSlotAvailability[dayKey] = {...currentDaySlots, slotId: newValue}; - }); - } - - bool _isTimeSlotActive(String slotId) { - final dayKey = _getDayKey(_selectedDate); - final daySlots = _timeSlotAvailability[dayKey]; - if (daySlots == null) return true; - return daySlots[slotId] != false; - } - - String _getMonthYear() { - final middleDate = _currentWeekStart.add(const Duration(days: 3)); - return DateFormat('MMMM yyyy').format(middleDate); - } - - void _quickSet(String type) { - Map newAvailability = {}; - - switch (type) { - case 'all': - for (var day in _dayNames) newAvailability[day] = true; - break; - case 'weekdays': - for (var day in _dayNames) - newAvailability[day] = (day != 'saturday' && day != 'sunday'); - break; - case 'weekends': - for (var day in _dayNames) - newAvailability[day] = (day == 'saturday' || day == 'sunday'); - break; - case 'clear': - for (var day in _dayNames) newAvailability[day] = false; - break; - } - - setState(() { - _availability = newAvailability; - }); - } - - @override - Widget build(BuildContext context) { - final selectedDayKey = _getDayKey(_selectedDate); - final isSelectedDayAvailable = _availability[selectedDayKey] ?? false; - final weekDates = _getWeekDates(); - - return Scaffold( - backgroundColor: const Color( - 0xFFFAFBFC, - ), // slate-50 to white gradient approximation - body: SingleChildScrollView( - padding: const EdgeInsets.only(bottom: 100), - child: Column( - children: [ - _buildHeader(), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - _buildQuickSet(), - const SizedBox(height: 24), - _buildWeekNavigation(weekDates), - const SizedBox(height: 24), - _buildSelectedDayAvailability( - selectedDayKey, - isSelectedDayAvailable, - ), - const SizedBox(height: 24), - _buildInfoCard(), - ], - ), - ), - ], - ), - ), - ); - } - - Widget _buildHeader() { - return Container( - padding: const EdgeInsets.fromLTRB(20, 60, 20, 20), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - IconButton( - icon: const Icon( - LucideIcons.arrowLeft, - color: AppColors.krowCharcoal, - ), - onPressed: () => context.pop(), - ), - const SizedBox(width: 12), - // The rest of the original content in the `Row` will follow here. - // This part of the replacement will maintain the avatar and text content. - // Note: The avatar and text were originally part of the same `Row` as the `GestureDetector`. - // I will place them back into a nested `Row` to maintain the visual structure. - Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - border: Border.all( - color: AppColors.krowBlue.withOpacity(0.2), - width: 2, - ), - shape: BoxShape.circle, - ), - child: Center( - child: CircleAvatar( - backgroundColor: AppColors.krowBlue.withOpacity( - 0.1, - ), - radius: 18, - child: const Text( - 'K', // Mock initial - style: TextStyle( - color: AppColors.krowBlue, - fontWeight: FontWeight.bold, - fontSize: 14, - ), - ), - ), - ), - ), - const SizedBox(width: 12), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'My Availability', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Text( - 'Set when you can work', - style: TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - ), - ], - ), - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: AppColors.krowBlue.withOpacity(0.1), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.calendar, - color: AppColors.krowBlue, - size: 20, - ), - ), - ], - ), - ], - ), - ); - } - - Widget _buildQuickSet() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: AppColors.krowBlue.withOpacity(0.1), - borderRadius: BorderRadius.circular(16), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Quick Set Availability', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF333F48), - ), - ), - const SizedBox(height: 12), - Row( - children: [ - Expanded( - child: _buildQuickSetButton('All Week', () => _quickSet('all')), - ), - const SizedBox(width: 8), - Expanded( - child: _buildQuickSetButton( - 'Weekdays', - () => _quickSet('weekdays'), - ), - ), - const SizedBox(width: 8), - Expanded( - child: _buildQuickSetButton( - 'Weekends', - () => _quickSet('weekends'), - ), - ), - const SizedBox(width: 8), - Expanded( - child: _buildQuickSetButton( - 'Clear All', - () => _quickSet('clear'), - isDestructive: true, - ), - ), - ], - ), - ], - ), - ); - } - - Widget _buildQuickSetButton( - String label, - VoidCallback onTap, { - bool isDestructive = false, - }) { - return SizedBox( - height: 32, - child: OutlinedButton( - onPressed: onTap, - style: OutlinedButton.styleFrom( - padding: EdgeInsets.zero, - side: BorderSide( - color: isDestructive - ? Colors.red.withOpacity(0.2) - : AppColors.krowBlue.withOpacity(0.2), - ), - backgroundColor: - Colors.transparent, // React has hover effect, plain here - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - foregroundColor: isDestructive ? Colors.red : AppColors.krowBlue, - ), - child: Text( - label, - style: const TextStyle(fontSize: 10, fontWeight: FontWeight.w500), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - ); - } - - Widget _buildWeekNavigation(List weekDates) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: Colors.grey.shade100), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - children: [ - // Nav Header - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _buildNavButton( - LucideIcons.chevronLeft, - () => _navigateWeek(-1), - ), - Text( - _getMonthYear(), - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ), - _buildNavButton( - LucideIcons.chevronRight, - () => _navigateWeek(1), - ), - ], - ), - ), - // Days Row - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: weekDates.map((date) => _buildDayItem(date)).toList(), - ), - ], - ), - ); - } - - Widget _buildNavButton(IconData icon, VoidCallback onTap) { - return GestureDetector( - onTap: onTap, - child: Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - color: Color(0xFFF1F5F9), // slate-100 - shape: BoxShape.circle, - ), - child: Icon(icon, size: 20, color: AppColors.krowMuted), - ), - ); - } - - Widget _buildDayItem(DateTime date) { - final isSelected = _isSelected(date); - final dayKey = _getDayKey(date); - final isAvailable = _availability[dayKey] ?? false; - final isToday = _isToday(date); - - return Expanded( - child: GestureDetector( - onTap: () => setState(() => _selectedDate = date), - child: Container( - margin: const EdgeInsets.symmetric(horizontal: 2), - padding: const EdgeInsets.symmetric(vertical: 12), - decoration: BoxDecoration( - color: isSelected - ? AppColors.krowBlue - : (isAvailable - ? const Color(0xFFECFDF5) - : const Color(0xFFF8FAFC)), // emerald-50 or slate-50 - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: isSelected - ? AppColors.krowBlue - : (isAvailable - ? const Color(0xFFA7F3D0) - : Colors.transparent), // emerald-200 - ), - boxShadow: isSelected - ? [ - BoxShadow( - color: AppColors.krowBlue.withOpacity(0.3), - blurRadius: 8, - offset: const Offset(0, 4), - ), - ] - : null, - ), - child: Stack( - clipBehavior: Clip.none, - alignment: Alignment.center, - children: [ - Column( - children: [ - Text( - date.day.toString().padLeft(2, '0'), - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: isSelected - ? Colors.white - : (isAvailable - ? const Color(0xFF047857) - : AppColors.krowMuted), // emerald-700 - ), - ), - const SizedBox(height: 2), - Text( - _formatDay(date), - style: TextStyle( - fontSize: 10, - color: isSelected - ? Colors.white.withOpacity(0.8) - : (isAvailable - ? const Color(0xFF047857) - : AppColors.krowMuted), - ), - ), - ], - ), - if (isToday && !isSelected) - Positioned( - bottom: -8, - child: Container( - width: 6, - height: 6, - decoration: const BoxDecoration( - color: AppColors.krowBlue, - shape: BoxShape.circle, - ), - ), - ), - ], - ), - ), - ), - ); - } - - Widget _buildSelectedDayAvailability( - String selectedDayKey, - bool isAvailable, - ) { - final dateStr = DateFormat('EEEE, MMM d').format(_selectedDate); - - return Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: Colors.grey.shade100), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - children: [ - // Header Row - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - dateStr, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ), - Text( - isAvailable ? 'You are available' : 'Not available', - style: const TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - ), - ), - ], - ), - Switch( - value: isAvailable, - onChanged: (val) => _toggleDayAvailability(selectedDayKey), - activeColor: AppColors.krowBlue, - ), - ], - ), - - const SizedBox(height: 16), - - // Time Slots - ..._timeSlots.map((slot) { - final isActive = _isTimeSlotActive(slot['slotId']); - // Determine styles based on state - final isEnabled = - isAvailable; // If day is off, slots are disabled visually - - // Container style - Color bgColor; - Color borderColor; - - if (!isEnabled) { - bgColor = const Color(0xFFF8FAFC); // slate-50 - borderColor = const Color(0xFFF1F5F9); // slate-100 - } else if (isActive) { - bgColor = AppColors.krowBlue.withOpacity(0.05); - borderColor = AppColors.krowBlue.withOpacity(0.2); - } else { - bgColor = const Color(0xFFF8FAFC); // slate-50 - borderColor = const Color(0xFFE2E8F0); // slate-200 - } - - // Text colors - final titleColor = (isEnabled && isActive) - ? AppColors.krowCharcoal - : AppColors.krowMuted; - final subtitleColor = (isEnabled && isActive) - ? AppColors.krowMuted - : Colors.grey.shade400; - - return GestureDetector( - onTap: isEnabled ? () => _toggleTimeSlot(slot['slotId']) : null, - child: AnimatedContainer( - duration: const Duration(milliseconds: 200), - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: bgColor, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: borderColor, width: 2), - ), - child: Row( - children: [ - // Icon - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: slot['bg'], - borderRadius: BorderRadius.circular(12), - ), - child: Icon( - slot['icon'], - color: slot['iconColor'], - size: 20, - ), - ), - const SizedBox(width: 12), - // Text - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - slot['label'], - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: titleColor, - ), - ), - Text( - slot['timeRange'], - style: TextStyle( - fontSize: 12, - color: subtitleColor, - ), - ), - ], - ), - ), - // Checkbox indicator - if (isEnabled && isActive) - Container( - width: 24, - height: 24, - decoration: const BoxDecoration( - color: AppColors.krowBlue, - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.check, - size: 16, - color: Colors.white, - ), - ) - else if (isEnabled && !isActive) - Container( - width: 24, - height: 24, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: const Color(0xFFCBD5E1), - width: 2, - ), // slate-300 - ), - ), - ], - ), - ), - ); - }).toList(), - ], - ), - ); - } - - Widget _buildInfoCard() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: AppColors.krowBlue.withOpacity(0.05), - borderRadius: BorderRadius.circular(12), - ), - child: const Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon(LucideIcons.clock, size: 20, color: AppColors.krowBlue), - SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Auto-Match uses your availability', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - SizedBox(height: 2), - Text( - "When enabled, you'll only be matched with shifts during your available times.", - style: TextStyle(fontSize: 12, color: AppColors.krowMuted), - ), - ], - ), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/benefits_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/benefits_screen.dart deleted file mode 100644 index ed8b728f..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/benefits_screen.dart +++ /dev/null @@ -1,534 +0,0 @@ -import 'dart:math'; -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; - -class BenefitsScreen extends StatefulWidget { - const BenefitsScreen({super.key}); - - @override - State createState() => _BenefitsScreenState(); -} - -class _BenefitsScreenState extends State { - final List> _benefitsData = [ - { - 'id': 'sick', - 'title': 'Sick Days', - 'currentHours': 10, - 'totalHours': 40, - 'color': const Color(0xFF10B981), - 'description': 'You need at least 8 hours to request sick leave', - 'history': [ - {'date': '1 Jan, 2024', 'status': 'Pending'}, - {'date': '28 Jan, 2024', 'status': 'Submitted'}, - {'date': '5 Feb, 2024', 'status': 'Submitted'}, - {'date': '28 Jan, 2024', 'status': 'Submitted'}, - {'date': '5 Feb, 2024', 'status': 'Submitted'}, - ], - 'requestLabel': 'Request Payment for Sick Leave', - }, - { - 'id': 'vacation', - 'title': 'Vacation', - 'currentHours': 40, - 'totalHours': 40, - 'color': const Color(0xFF10B981), - 'description': 'You need 40 hours to claim vacation pay', - 'history': [], - 'requestLabel': 'Request Payment for Vacation', - 'notice': - 'Listed certificates are mandatory for employees. If the employee does not have the complete certificates, they can\'t proceed with their registration.', - }, - { - 'id': 'holidays', - 'title': 'Holidays', - 'currentHours': 24, - 'totalHours': 24, - 'color': const Color(0xFF10B981), - 'description': 'Pay holidays: Thanksgiving, Christmas, New Year', - 'history': [], - 'requestLabel': 'Request Payment for Holiday', - 'notice': - 'Listed certificates are mandatory for employees. If the employee does not have the complete certificates, they can\'t proceed with their registration.', - }, - ]; - - bool _showSuccess = false; - String _successType = ''; - - void _handleRequest(Map benefit) { - setState(() { - _successType = benefit['title']; - _showSuccess = true; - }); - } - - @override - Widget build(BuildContext context) { - return Stack( - children: [ - Scaffold( - backgroundColor: AppColors.krowBackground, - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: IconButton( - icon: const Icon( - LucideIcons.chevronLeft, - color: AppColors.krowMuted, - ), - onPressed: () => - context.canPop() ? context.pop() : context.go('/worker-home'), - ), - title: const Text( - 'Your Benefits Overview', - style: TextStyle( - color: AppColors.krowCharcoal, - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - centerTitle: true, - bottom: PreferredSize( - preferredSize: const Size.fromHeight(24), - child: Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Text( - 'Manage and track your earned benefits here', - style: TextStyle(color: AppColors.krowMuted, fontSize: 14), - ), - ), - ), - shape: const Border(bottom: BorderSide(color: Color(0xFFF1F5F9))), - ), - body: ListView.separated( - padding: const EdgeInsets.all(20), - itemCount: _benefitsData.length, - separatorBuilder: (context, index) => const SizedBox(height: 16), - itemBuilder: (context, index) { - return _BenefitCard( - benefit: _benefitsData[index], - onRequest: () => _handleRequest(_benefitsData[index]), - ); - }, - ), - ), - if (_showSuccess) - _SuccessModal( - type: _successType, - onClose: () => setState(() => _showSuccess = false), - ), - ], - ); - } -} - -class _BenefitCard extends StatefulWidget { - final Map benefit; - final VoidCallback onRequest; - - const _BenefitCard({required this.benefit, required this.onRequest}); - - @override - State<_BenefitCard> createState() => _BenefitCardState(); -} - -class _BenefitCardState extends State<_BenefitCard> { - bool _expanded = false; - - @override - Widget build(BuildContext context) { - final history = widget.benefit['history'] as List; - final hasHistory = history.isNotEmpty; - final notice = widget.benefit['notice'] as String?; - - return Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFF1F5F9)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.02), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _CircularProgress( - current: widget.benefit['currentHours'], - total: widget.benefit['totalHours'], - color: widget.benefit['color'], - ), - const SizedBox(width: 16), - Expanded( - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - widget.benefit['title'], - style: const TextStyle( - fontWeight: FontWeight.w600, - fontSize: 16, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 2), - Text( - widget.benefit['description'], - style: const TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - const Icon( - LucideIcons.info, - size: 20, - color: Color(0xFFCBD5E1), - ), - ], - ), - ), - ], - ), - if (hasHistory) ...[ - const SizedBox(height: 16), - InkWell( - onTap: () => setState(() => _expanded = !_expanded), - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'SICK LEAVE HISTORY', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: AppColors.krowMuted, - letterSpacing: 0.5, - ), - ), - Icon( - _expanded - ? LucideIcons.chevronUp - : LucideIcons.chevronDown, - size: 16, - color: AppColors.krowMuted, - ), - ], - ), - ), - ), - AnimatedCrossFade( - firstChild: const SizedBox.shrink(), - secondChild: Column( - children: history.map((item) { - final isPending = item['status'] == 'Pending'; - return Padding( - padding: const EdgeInsets.symmetric(vertical: 4), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - item['date'], - style: const TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - ), - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 2, - ), - decoration: BoxDecoration( - color: isPending - ? const Color(0xFFF1F5F9) - : const Color(0xFFECFDF5), - borderRadius: BorderRadius.circular(12), - border: isPending - ? Border.all( - color: const Color(0xFFCBD5E1), - ) - : null, - ), - child: Text( - item['status'], - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: isPending - ? AppColors.krowMuted - : const Color(0xFF047857), - ), - ), - ), - ], - ), - ); - }).toList(), - ), - crossFadeState: _expanded - ? CrossFadeState.showSecond - : CrossFadeState.showFirst, - duration: const Duration(milliseconds: 200), - ), - ], - if (notice != null) ...[ - const SizedBox(height: 16), - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFFECFDF5), - borderRadius: BorderRadius.circular(12), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Icon( - LucideIcons.checkCircle, - size: 16, - color: Color(0xFF10B981), - ), - const SizedBox(width: 8), - Expanded( - child: Text( - notice, - style: const TextStyle( - fontSize: 12, - color: Color(0xFF047857), - ), - ), - ), - ], - ), - ), - ], - ], - ), - ), - Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: widget.onRequest, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0032A0), - foregroundColor: Colors.white, - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: Text( - widget.benefit['requestLabel'], - style: const TextStyle(fontWeight: FontWeight.w500), - ), - ), - ), - ), - ], - ), - ); - } -} - -class _CircularProgress extends StatelessWidget { - final int current; - final int total; - final Color color; - final double size; - - const _CircularProgress({ - required this.current, - required this.total, - required this.color, - this.size = 64, - }); - - @override - Widget build(BuildContext context) { - return SizedBox( - width: size, - height: size, - child: Stack( - fit: StackFit.expand, - children: [ - Transform.rotate( - angle: -pi / 2, - child: CustomPaint( - painter: _CircularProgressPainter( - progress: current / total, - color: color, - strokeWidth: 5, - ), - ), - ), - Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - '$current/$total', - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const Text( - 'hours', - style: TextStyle(fontSize: 10, color: Color(0xFF94A3B8)), - ), - ], - ), - ), - ], - ), - ); - } -} - -class _CircularProgressPainter extends CustomPainter { - final double progress; - final Color color; - final double strokeWidth; - - _CircularProgressPainter({ - required this.progress, - required this.color, - required this.strokeWidth, - }); - - @override - void paint(Canvas canvas, Size size) { - final center = Offset(size.width / 2, size.height / 2); - final radius = (size.width - strokeWidth) / 2; - - final bgPaint = Paint() - ..color = const Color(0xFFE2E8F0) - ..strokeWidth = strokeWidth - ..style = PaintingStyle.stroke; - - canvas.drawCircle(center, radius, bgPaint); - - final fgPaint = Paint() - ..color = color - ..strokeWidth = strokeWidth - ..style = PaintingStyle.stroke - ..strokeCap = StrokeCap.round; - - canvas.drawArc( - Rect.fromCircle(center: center, radius: radius), - 0, - 2 * pi * progress, - false, - fgPaint, - ); - } - - @override - bool shouldRepaint(covariant _CircularProgressPainter oldDelegate) { - return oldDelegate.progress != progress || oldDelegate.color != color; - } -} - -class _SuccessModal extends StatelessWidget { - final String type; - final VoidCallback onClose; - - const _SuccessModal({required this.type, required this.onClose}); - - @override - Widget build(BuildContext context) { - return Container( - color: Colors.black.withOpacity(0.5), - child: Center( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Container( - padding: const EdgeInsets.all(32), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(24), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 64, - height: 64, - decoration: const BoxDecoration( - color: Color(0xFFF1F5F9), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.thumbsUp, - size: 32, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 20), - const Text( - 'Request Submitted', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - Text( - 'Your ${type.toLowerCase()} request has been submitted successfully. You\'ll be notified once it\'s processed', - textAlign: TextAlign.center, - style: const TextStyle( - color: AppColors.krowMuted, - fontSize: 16, - ), - ), - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: onClose, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0032A0), - foregroundColor: Colors.white, - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: const Text('Back to Profile'), - ), - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/clock_in_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/clock_in_screen.dart deleted file mode 100644 index 9079b2e8..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/clock_in_screen.dart +++ /dev/null @@ -1,796 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import 'package:intl/intl.dart'; -import '../../theme.dart'; -import '../../widgets/clock_in/attendance_card.dart'; -import '../../widgets/clock_in/date_selector.dart'; -import '../../widgets/clock_in/swipe_to_check_in.dart'; -import '../../widgets/clock_in/lunch_break_modal.dart'; -import '../../widgets/clock_in/commute_tracker.dart'; -import '../../models/shift.dart'; - -class ClockInScreen extends StatefulWidget { - const ClockInScreen({super.key}); - - @override - State createState() => _ClockInScreenState(); -} - -class _ClockInScreenState extends State { - DateTime _selectedDate = DateTime.now(); - bool _isCheckedIn = false; - DateTime? _checkInTime; - DateTime? _checkOutTime; - String _checkInMode = 'swipe'; // 'swipe' or 'nfc' - - // Mock data matching React - // Setting shift for tomorrow to make CommuteTracker visible - final Shift? _todayShift = Shift( - id: '1', - title: 'Warehouse Assistant', - clientName: 'Amazon Warehouse', - logoUrl: - 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/06/Amazon_2024.svg/500px-Amazon_2024.svg.png', - hourlyRate: 22.50, - date: DateFormat('yyyy-MM-dd').format( - DateTime.now().add(const Duration(hours: 2)), - ), // Shift in 2 hours to trigger commute window - startTime: DateFormat( - 'HH:mm', - ).format(DateTime.now().add(const Duration(hours: 2))), - endTime: DateFormat( - 'HH:mm', - ).format(DateTime.now().add(const Duration(hours: 10))), - location: 'San Francisco, CA', - locationAddress: '123 Market St, San Francisco, CA 94105', - status: 'assigned', - createdDate: DateTime.now() - .subtract(const Duration(days: 2)) - .toIso8601String(), - latitude: 37.7749, - longitude: -122.4194, - description: 'General warehouse duties including packing and sorting.', - managers: [], - ); - - final List> _activityLog = [ - { - 'date': DateTime.now().subtract(const Duration(days: 1)), - 'start': '09:00 AM', - 'end': '05:00 PM', - 'hours': '8h', - }, - { - 'date': DateTime.now().subtract(const Duration(days: 2)), - 'start': '09:00 AM', - 'end': '05:00 PM', - 'hours': '8h', - }, - { - 'date': DateTime.now().subtract(const Duration(days: 3)), - 'start': '09:00 AM', - 'end': '05:00 PM', - 'hours': '8h', - }, - ]; - - @override - Widget build(BuildContext context) { - // Format times for display - final checkInStr = _checkInTime != null - ? DateFormat('h:mm a').format(_checkInTime!) - : '--:-- --'; - final checkOutStr = _checkOutTime != null - ? DateFormat('h:mm a').format(_checkOutTime!) - : '--:-- --'; - - return Scaffold( - body: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xFFF8FAFC), // slate-50 - Colors.white, - ], - ), - ), - child: SafeArea( - child: SingleChildScrollView( - padding: const EdgeInsets.only(bottom: 100), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildHeader(), - - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - children: [ - // Commute Tracker (shows before date selector when applicable) - if (_todayShift != null) - CommuteTracker( - shift: _todayShift, - hasLocationConsent: false, // Mock value - isCommuteModeOn: false, // Mock value - distanceMeters: 500, // Mock value for demo - etaMinutes: 8, // Mock value for demo - ), - - // Date Selector - DateSelector( - selectedDate: _selectedDate, - onSelect: (date) => - setState(() => _selectedDate = date), - shiftDates: [ - DateFormat('yyyy-MM-dd').format(DateTime.now()), - ], - ), - const SizedBox(height: 20), - - // Today Attendance Section - const Align( - alignment: Alignment.centerLeft, - child: Text( - "Today Attendance", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ), - const SizedBox(height: 12), - GridView.count( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - crossAxisCount: 2, - mainAxisSpacing: 12, - crossAxisSpacing: 12, - childAspectRatio: 1.0, - children: [ - AttendanceCard( - type: AttendanceType.checkin, - title: "Check In", - value: checkInStr, - subtitle: _checkInTime != null - ? "On Time" - : "Pending", - scheduledTime: "09:00 AM", - ), - AttendanceCard( - type: AttendanceType.checkout, - title: "Check Out", - value: checkOutStr, - subtitle: _checkOutTime != null - ? "Go Home" - : "Pending", - scheduledTime: "05:00 PM", - ), - AttendanceCard( - type: AttendanceType.breaks, - title: "Break Time", - value: "00:30 min", - subtitle: "Scheduled 00:30 min", - ), - const AttendanceCard( - type: AttendanceType.days, - title: "Total Days", - value: "28", - subtitle: "Working Days", - ), - ], - ), - const SizedBox(height: 24), - - // Your Activity Header - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - "Your Activity", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - GestureDetector( - onTap: () => context.push('/shifts'), - child: const Row( - children: [ - Text( - "View all", - style: TextStyle( - color: AppColors.krowBlue, - fontWeight: FontWeight.w500, - ), - ), - Icon( - LucideIcons.chevronRight, - size: 16, - color: AppColors.krowBlue, - ), - ], - ), - ), - ], - ), - const SizedBox(height: 12), - - // Check-in Mode Toggle - const Align( - alignment: Alignment.centerLeft, - child: Text( - "Check-in Method", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF334155), // slate-700 - ), - ), - ), - const SizedBox(height: 8), - Container( - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - color: const Color(0xFFF1F5F9), // slate-100 - borderRadius: BorderRadius.circular(12), - ), - child: Row( - children: [ - _buildModeTab("Swipe", LucideIcons.mapPin, 'swipe'), - _buildModeTab("NFC Tap", LucideIcons.wifi, 'nfc'), - ], - ), - ), - const SizedBox(height: 16), - - // Selected Shift Info Card - if (_todayShift != null) - Container( - padding: const EdgeInsets.all(12), - margin: const EdgeInsets.only(bottom: 16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: const Color(0xFFE2E8F0), - ), // slate-200 - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "TODAY'S SHIFT", - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w600, - color: AppColors.krowBlue, - letterSpacing: 0.5, - ), - ), - const SizedBox(height: 2), - Text( - _todayShift!.title, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFF1E293B), // slate-800 - ), - ), - Text( - "${_todayShift!.clientName} • ${_todayShift!.location}", - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), // slate-500 - ), - ), - ], - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - "9:00 AM - 5:00 PM", - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF475569), // slate-600 - ), - ), - Text( - "\$${_todayShift!.hourlyRate}/hr", - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: AppColors.krowBlue, - ), - ), - ], - ), - ], - ), - ), - - // Swipe To Check In / Checked Out State / No Shift State - if (_todayShift != null && !(_checkOutTime != null)) ...[ - SwipeToCheckIn( - isCheckedIn: _isCheckedIn, - mode: _checkInMode, - onCheckIn: () async { - // Show NFC dialog if mode is 'nfc' - if (_checkInMode == 'nfc') { - await _showNFCDialog(); - } else { - await Future.delayed(const Duration(seconds: 1)); - setState(() { - _isCheckedIn = true; - _checkInTime = DateTime.now(); - }); - } - }, - onCheckOut: () { - setState(() { - _checkOutTime = DateTime.now(); - }); - showDialog( - context: context, - builder: (context) => LunchBreakDialog( - onComplete: () { - setState(() { - _isCheckedIn = false; - _checkInTime = null; - _checkOutTime = null; - }); - }, - ), - ); - }, - ), - ] else if (_todayShift != null && - _checkOutTime != null) ...[ - // Shift Completed State - Container( - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: const Color(0xFFECFDF5), // emerald-50 - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: const Color(0xFFA7F3D0), - ), // emerald-200 - ), - child: Column( - children: [ - Container( - width: 48, - height: 48, - decoration: const BoxDecoration( - color: Color(0xFFD1FAE5), // emerald-100 - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.check, - color: Color(0xFF059669), // emerald-600 - size: 24, - ), - ), - const SizedBox(height: 12), - const Text( - "Shift Completed!", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF065F46), // emerald-800 - ), - ), - const SizedBox(height: 4), - const Text( - "Great work today", - style: TextStyle( - fontSize: 14, - color: Color(0xFF059669), // emerald-600 - ), - ), - ], - ), - ), - ] else ...[ - // No Shift State - Container( - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: const Color(0xFFF1F5F9), // slate-100 - borderRadius: BorderRadius.circular(16), - ), - child: Column( - children: [ - const Text( - "No confirmed shifts for today", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Color(0xFF475569), // slate-600 - ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 4), - const Text( - "Accept a shift to clock in", - style: TextStyle( - fontSize: 14, - color: Color(0xFF64748B), // slate-500 - ), - textAlign: TextAlign.center, - ), - ], - ), - ), - ], - - // Checked In Banner - if (_isCheckedIn && _checkInTime != null) ...[ - const SizedBox(height: 12), - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFFECFDF5), // emerald-50 - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: const Color(0xFFA7F3D0), - ), // emerald-200 - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "Checked in at", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF059669), - ), - ), - Text( - DateFormat('h:mm a').format(_checkInTime!), - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: Color(0xFF065F46), - ), - ), - ], - ), - Container( - width: 40, - height: 40, - decoration: const BoxDecoration( - color: Color(0xFFD1FAE5), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.check, - color: Color(0xFF059669), - ), - ), - ], - ), - ), - ], - - const SizedBox(height: 16), - - // Recent Activity List - ..._activityLog.map( - (activity) => Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFFF8F9FA), - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: const Color(0xFFF1F5F9), - ), // slate-100 - ), - child: Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: AppColors.krowBlue.withOpacity(0.1), - borderRadius: BorderRadius.circular(12), - ), - child: const Icon( - LucideIcons.mapPin, - color: AppColors.krowBlue, - size: 20, - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - DateFormat( - 'MMM d', - ).format(activity['date'] as DateTime), - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF0F172A), // slate-900 - ), - ), - Text( - "${activity['start']} - ${activity['end']}", - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), // slate-500 - ), - ), - ], - ), - ), - Text( - activity['hours'] as String, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: AppColors.krowBlue, - ), - ), - ], - ), - ), - ), - ], - ), - ), - ], - ), - ), - ), - ), - ); - } - - Widget _buildModeTab(String label, IconData icon, String value) { - final isSelected = _checkInMode == value; - return Expanded( - child: GestureDetector( - onTap: () => setState(() => _checkInMode = value), - child: Container( - padding: const EdgeInsets.symmetric(vertical: 8), - decoration: BoxDecoration( - color: isSelected ? Colors.white : Colors.transparent, - borderRadius: BorderRadius.circular(8), - boxShadow: isSelected - ? [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ] - : [], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - icon, - size: 16, - color: isSelected ? Colors.black : Colors.grey, - ), - const SizedBox(width: 6), - Text( - label, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: isSelected ? Colors.black : Colors.grey, - ), - ), - ], - ), - ), - ), - ); - } - - Widget _buildHeader() { - return Padding( - padding: const EdgeInsets.fromLTRB(20, 24, 20, 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - width: 48, - height: 48, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: AppColors.krowBlue.withOpacity(0.2), - width: 2, - ), - ), - child: CircleAvatar( - backgroundColor: AppColors.krowBlue.withOpacity(0.1), - child: const Text( - 'K', - style: TextStyle( - color: AppColors.krowBlue, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - const SizedBox(width: 12), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Good Morning', - style: TextStyle(color: AppColors.krowMuted, fontSize: 12), - ), - Text( - 'Krower', - style: TextStyle( - color: AppColors.krowCharcoal, - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - Text( - 'Warehouse Assistant', - style: TextStyle(color: AppColors.krowMuted, fontSize: 12), - ), - ], - ), - ], - ), - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular( - 20, - ), // Rounded full for this page per design - border: Border.all(color: Colors.grey.shade100), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: const Icon( - LucideIcons.bell, - color: AppColors.krowMuted, - size: 20, - ), - ), - ], - ), - ); - } - - Future _showNFCDialog() async { - bool scanned = false; - - await showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext dialogContext) { - return StatefulBuilder( - builder: (context, setState) { - return AlertDialog( - title: Text(scanned ? 'Tag Scanned!' : 'Scan NFC Tag'), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 96, - height: 96, - decoration: BoxDecoration( - color: scanned - ? Colors.green.shade50 - : Colors.blue.shade50, - shape: BoxShape.circle, - ), - child: Icon( - scanned ? LucideIcons.check : LucideIcons.nfc, - size: 48, - color: scanned - ? Colors.green.shade600 - : Colors.blue.shade600, - ), - ), - const SizedBox(height: 24), - Text( - scanned ? 'Processing check-in...' : 'Ready to scan', - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 8), - Text( - scanned - ? 'Please wait...' - : 'Hold your phone near the NFC tag at the clock-in station', - textAlign: TextAlign.center, - style: TextStyle(fontSize: 14, color: Colors.grey.shade600), - ), - if (!scanned) ...[ - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - height: 56, - child: ElevatedButton.icon( - onPressed: () async { - setState(() { - scanned = true; - }); - // Simulate NFC scan delay - await Future.delayed( - const Duration(milliseconds: 1000), - ); - Navigator.of(dialogContext).pop(); - // Perform check-in - if (mounted) { - this.setState(() { - _isCheckedIn = true; - _checkInTime = DateTime.now(); - }); - } - }, - icon: const Icon(LucideIcons.nfc, size: 24), - label: const Text( - 'Tap to Scan', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0047FF), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - ), - ), - ], - ], - ), - ); - }, - ); - }, - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/early_pay_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/early_pay_screen.dart deleted file mode 100644 index 1be026b4..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/early_pay_screen.dart +++ /dev/null @@ -1,899 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import '../../theme.dart'; - -class EarlyPayScreen extends StatefulWidget { - const EarlyPayScreen({super.key}); - - @override - State createState() => _EarlyPayScreenState(); -} - -class _EarlyPayScreenState extends State { - // State - String _enrollmentStep = 'info'; // info, terms, complete - bool _isEnrolled = false; - bool _agreedToTerms = false; - double _requestAmount = 0; - bool _showConfirmation = false; - bool _isLoading = false; - - // Mock Data - final double _availableAmount = 285.0; - - double get _serviceFee => _requestAmount * 0.05; - double get _netAmount => _requestAmount - _serviceFee; - - void _handleEnroll() async { - setState(() => _isLoading = true); - await Future.delayed(const Duration(seconds: 1)); // Mock API - setState(() { - _isLoading = false; - _enrollmentStep = 'complete'; - _isEnrolled = true; // For next time - }); - } - - void _handleRequest() async { - setState(() => _isLoading = true); - await Future.delayed(const Duration(seconds: 1)); // Mock API - setState(() { - _isLoading = false; - _showConfirmation = true; - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFF8FAFC), - body: Stack( - children: [ - Column( - children: [ - _buildHeader(), - Expanded( - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 24, - ), - child: _isEnrolled - ? _buildRequestFlow() - : _buildEnrollmentFlow(), - ), - ), - ), - ], - ), - if (_showConfirmation) _buildConfirmationModal(), - ], - ), - ); - } - - Widget _buildHeader() { - return Container( - padding: EdgeInsets.fromLTRB( - 20, - MediaQuery.of(context).padding.top + 20, - 20, - 32, - ), - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [Color(0xFF0047FF), Color(0xFF0032A0)], - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - GestureDetector( - onTap: () => context.go('/payments'), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 24, - ), - ), - const SizedBox(height: 16), - Row( - children: [ - Container( - width: 48, - height: 48, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(12), - ), - child: const Icon( - LucideIcons.zap, - color: Colors.white, - size: 24, - ), - ), - const SizedBox(width: 12), - const Text( - 'Early Pay', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ], - ), - const SizedBox(height: 8), - Text( - _isEnrolled - ? 'Get paid before payday' - : 'Access your earned wages instantly', - style: const TextStyle(color: Color(0xFFDBEAFE), fontSize: 14), - ), - ], - ), - ); - } - - Widget _buildEnrollmentFlow() { - if (_enrollmentStep == 'info') { - return Column( - children: [ - _buildInfoCard(), - const SizedBox(height: 16), - _buildFeeInfoCard(), - const SizedBox(height: 16), - _buildBenefitsCard(), - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: () => setState(() => _enrollmentStep = 'terms'), - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0047FF), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: const Text( - 'Continue to Terms', - style: TextStyle(fontWeight: FontWeight.w600), - ), - ), - ), - ], - ); - } else if (_enrollmentStep == 'terms') { - return Column( - children: [ - _buildTermsCard(), - const SizedBox(height: 16), - _buildTermsCheckbox(), - const SizedBox(height: 24), - Row( - children: [ - Expanded( - child: SizedBox( - height: 48, - child: OutlinedButton( - onPressed: () => setState(() => _enrollmentStep = 'info'), - style: OutlinedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: const Text('Back'), - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: SizedBox( - height: 48, - child: ElevatedButton( - onPressed: (_agreedToTerms && !_isLoading) - ? _handleEnroll - : null, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0047FF), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: Text(_isLoading ? 'Enrolling...' : 'Enroll Now'), - ), - ), - ), - ], - ), - ], - ); - } else { - // Complete - return Column( - children: [ - Container( - padding: const EdgeInsets.all(32), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - children: [ - Container( - width: 64, - height: 64, - decoration: const BoxDecoration( - color: Color(0xFFF0FDF4), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.checkCircle, - color: Color(0xFF16A34A), - size: 32, - ), - ), - const SizedBox(height: 16), - const Text( - 'You\'re All Set!', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 8), - const Text( - 'You can now access your earned wages anytime you need them.', - textAlign: TextAlign.center, - style: TextStyle(color: Color(0xFF475569)), - ), - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: () { - setState(() { - _isEnrolled = true; - // Reset requests flow - _requestAmount = 0; - }); - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0047FF), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: const Text( - 'Continue to Early Pay', - style: TextStyle(fontWeight: FontWeight.w600), - ), - ), - ), - ], - ), - ), - ], - ); - } - } - - Widget _buildRequestFlow() { - return Column( - children: [ - // Available Amount Card - Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - children: [ - const Text( - 'Available for Early Pay', - style: TextStyle(color: Color(0xFF475569), fontSize: 14), - ), - const SizedBox(height: 4), - Text( - '\$${_availableAmount.toStringAsFixed(0)}', - style: const TextStyle( - fontSize: 36, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 4), - const Text( - 'Based on completed shifts', - style: TextStyle(color: Color(0xFF64748B), fontSize: 12), - ), - const SizedBox(height: 24), - - // Slider - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Request Amount', - style: TextStyle(fontWeight: FontWeight.w600, fontSize: 14), - ), - Text( - '\$${_requestAmount.toStringAsFixed(0)}', - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF0047FF), - ), - ), - ], - ), - const SizedBox(height: 8), - SliderTheme( - data: SliderTheme.of(context).copyWith( - trackHeight: 6, - activeTrackColor: const Color(0xFF0047FF), - inactiveTrackColor: const Color(0xFFE2E8F0), - thumbColor: Colors.white, - thumbShape: const RoundSliderThumbShape( - enabledThumbRadius: 10, - ), - overlayColor: const Color(0xFF0047FF).withOpacity(0.1), - ), - child: Slider( - value: _requestAmount, - min: 0, - max: _availableAmount, - divisions: (_availableAmount / 5).floor(), - onChanged: (val) => setState(() => _requestAmount = val), - ), - ), - const Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - '\$0', - style: TextStyle(color: Color(0xFF64748B), fontSize: 12), - ), - Text( - '\$285', // Matches available amount - style: TextStyle(color: Color(0xFF64748B), fontSize: 12), - ), - ], - ), - - // Breakdown - if (_requestAmount > 0) ...[ - const SizedBox(height: 24), - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFFF8FAFC), - borderRadius: BorderRadius.circular(12), - ), - child: Column( - children: [ - _buildBreakdownRow( - 'Requested Amount', - '\$${_requestAmount.toStringAsFixed(2)}', - ), - const SizedBox(height: 8), - _buildBreakdownRow( - 'Service Fee (5%)', - '-\$${_serviceFee.toStringAsFixed(2)}', - isFee: true, - ), - const Divider(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'You Receive', - style: TextStyle( - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), - ), - ), - Text( - '\$${_netAmount.toStringAsFixed(2)}', - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Color(0xFF0047FF), - ), - ), - ], - ), - ], - ), - ), - ], - - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: (_requestAmount > 0 && !_isLoading) - ? _handleRequest - : null, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0047FF), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: Text( - _isLoading ? 'Processing...' : 'Request Early Pay', - ), - ), - ), - ], - ), - ), - - const SizedBox(height: 16), - _buildRequestInfoCard(), - ], - ); - } - - Widget _buildInfoCard() { - return Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'How Early Pay Works', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 16), - _buildStep( - 1, - 'Work Your Shift', - 'Complete your scheduled shifts as normal', - ), - const SizedBox(height: 16), - _buildStep( - 2, - 'Request Early Pay', - 'Access up to 50% of earned wages before payday', - ), - const SizedBox(height: 16), - _buildStep( - 3, - 'Get Paid Instantly', - 'Funds transferred to your account within minutes', - ), - ], - ), - ); - } - - Widget _buildStep(int num, String title, String desc) { - return Row( - children: [ - Container( - width: 40, - height: 40, - decoration: const BoxDecoration( - color: Color(0xFFEFF6FF), - shape: BoxShape.circle, - ), - child: Center( - child: Text( - '$num', - style: const TextStyle( - fontWeight: FontWeight.bold, - color: Color(0xFF2563EB), - ), - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - fontWeight: FontWeight.w600, - fontSize: 14, - color: Color(0xFF0F172A), - ), - ), - Text( - desc, - style: const TextStyle(color: Color(0xFF475569), fontSize: 12), - ), - ], - ), - ), - ], - ); - } - - Widget _buildFeeInfoCard() { - return Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: const Color(0xFFFFFBEB), - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Icon(LucideIcons.info, color: Color(0xFFD97706), size: 20), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: const [ - Text( - 'Service Fee', - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 14, - color: Color(0xFF0F172A), - ), - ), - SizedBox(height: 4), - Text( - 'A 5% service fee applies to each Early Pay request. This fee covers the cost of instant transfer and processing.\n\nExample: Request \'100, receive \'95 (5% = \'5 fee)', - style: TextStyle(color: Color(0xFF475569), fontSize: 12), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildBenefitsCard() { - return Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Key Benefits', - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 14, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 12), - _buildCheckItem('No hidden fees or interest charges'), - const SizedBox(height: 8), - _buildCheckItem('Optional service - use only when you need it'), - const SizedBox(height: 8), - _buildCheckItem('Instant transfers to your bank account'), - const SizedBox(height: 8), - _buildCheckItem('No credit check or impact on credit score'), - ], - ), - ); - } - - Widget _buildCheckItem(String text) { - return Row( - children: [ - const Icon(LucideIcons.checkCircle, size: 16, color: Color(0xFF16A34A)), - const SizedBox(width: 8), - Text( - text, - style: const TextStyle(fontSize: 12, color: Color(0xFF475569)), - ), - ], - ); - } - - Widget _buildTermsCard() { - return Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Terms & Conditions', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 16), - SizedBox( - height: 300, - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Early Pay Service Agreement', - style: TextStyle(fontWeight: FontWeight.w600, fontSize: 14), - ), - const SizedBox(height: 8), - const Text( - 'By enrolling in Krow Early Pay, you agree to the following terms...', - style: TextStyle(fontSize: 12, color: Color(0xFF475569)), - ), - const SizedBox(height: 12), - _buildTermItem( - '1. Service Description', - 'Early Pay allows you to access up to 50% of your earned wages...', - ), - _buildTermItem( - '2. Fees and Charges', - 'A service fee of 5% will be deducted from each request...', - ), - _buildTermItem( - '3. Eligibility', - 'You must have completed at least one shift with verified hours...', - ), - _buildTermItem( - '4. Voluntary Participation', - 'Participation is optional...', - ), - // Add more if needed - ], - ), - ), - ), - ], - ), - ); - } - - Widget _buildTermItem(String title, String desc) { - return Padding( - padding: const EdgeInsets.only(bottom: 12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 13), - ), - Text( - desc, - style: const TextStyle(fontSize: 12, color: Color(0xFF475569)), - ), - ], - ), - ); - } - - Widget _buildTermsCheckbox() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFE2E8F0), width: 2), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 24, - height: 24, - child: Checkbox( - value: _agreedToTerms, - onChanged: (val) => setState(() => _agreedToTerms = val ?? false), - activeColor: const Color(0xFF0047FF), - ), - ), - const SizedBox(width: 12), - const Expanded( - child: Text( - 'I have read and agree to the Early Pay Terms & Conditions. I understand that a 5% service fee applies to each request and that participation is voluntary.', - style: TextStyle(fontSize: 12, color: Color(0xFF475569)), - ), - ), - ], - ), - ); - } - - Widget _buildBreakdownRow(String label, String value, {bool isFee = false}) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - label, - style: const TextStyle(color: Color(0xFF475569), fontSize: 14), - ), - Text( - value, - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 14, - color: isFee ? const Color(0xFFD97706) : const Color(0xFF0F172A), - ), - ), - ], - ); - } - - Widget _buildRequestInfoCard() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFFEFF6FF), - borderRadius: BorderRadius.circular(16), - ), - child: Row( - children: [ - const Icon(LucideIcons.clock, color: Color(0xFF2563EB), size: 20), - const SizedBox(width: 12), - const Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Instant Transfer', - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 14, - color: Color(0xFF0F172A), - ), - ), - Text( - 'Funds are typically transferred to your account within minutes of approval.', - style: TextStyle(color: Color(0xFF475569), fontSize: 12), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildConfirmationModal() { - return GestureDetector( - onTap: () => setState(() => _showConfirmation = false), - child: Container( - color: Colors.black.withOpacity(0.5), - child: Center( - child: GestureDetector( - onTap: () {}, // consume tap - child: Container( - margin: const EdgeInsets.all(20), - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 64, - height: 64, - decoration: const BoxDecoration( - color: Color(0xFFF0FDF4), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.checkCircle, - color: Color(0xFF16A34A), - size: 32, - ), - ), - const SizedBox(height: 16), - const Text( - 'Transfer Initiated!', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 8), - Text( - '\$${_netAmount.toStringAsFixed(2)} is being transferred to your account. You should see it within minutes.', - textAlign: TextAlign.center, - style: const TextStyle(color: Color(0xFF475569)), - ), - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: () { - context.go('/payments'); - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0047FF), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: const Text('Back to Earnings'), - ), - ), - ], - ), - ), - ), - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/earnings_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/earnings_screen.dart deleted file mode 100644 index 9563598c..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/earnings_screen.dart +++ /dev/null @@ -1,667 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; - -class EarningsScreen extends StatefulWidget { - const EarningsScreen({super.key}); - - @override - State createState() => _EarningsScreenState(); -} - -class _EarningsScreenState extends State { - String _period = 'week'; - - // Mock Data - final double _totalEarnings = 12450.75; - final double _weeklyEarnings = 412.00; - final double _monthlyEarnings = 1650.50; - final double _pendingEarnings = 285.50; - - final List> _recentPayments = [ - {'date': 'Dec 15', 'amount': 285.50, 'shifts': 3, 'status': 'PAID'}, - {'date': 'Dec 8', 'amount': 412.00, 'shifts': 4, 'status': 'PAID'}, - {'date': 'Dec 1', 'amount': 198.75, 'shifts': 2, 'status': 'PAID'}, - ]; - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFFAFBFC), - body: SingleChildScrollView( - padding: const EdgeInsets.only(bottom: 24), - child: Column( - children: [ - _buildHeader(), - Transform.translate( - offset: const Offset(0, -20), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - children: [ - _buildQuickStats(), - const SizedBox(height: 20), - _buildPendingEarnings(), - const SizedBox(height: 20), - _buildActions(), - const SizedBox(height: 20), - _buildPaymentHistory(), - const SizedBox(height: 20), - _buildSavingsGoal(), - ], - ), - ), - ), - ], - ), - ), - ); - } - - Widget _buildHeader() { - return Container( - padding: const EdgeInsets.only(top: 60, left: 20, right: 20, bottom: 40), - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Color(0xFF059669), - Color(0xFF0F766E), - ], // emerald-600 to teal-700 - ), - ), - child: Column( - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - const Text( - 'Earnings', - style: TextStyle( - color: Colors.white, - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 24), - const Text( - 'Total Earnings', - style: TextStyle( - color: Color(0xFFA7F3D0), // emerald-200 - fontSize: 14, - ), - ), - const SizedBox(height: 4), - Text( - '\$${_totalEarnings.toStringAsFixed(2)}', - style: const TextStyle( - color: Colors.white, - fontSize: 36, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 24), - Container( - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(12), - ), - child: Row( - children: [ - _buildTab('week', 'Week'), - _buildTab('month', 'Month'), - _buildTab('year', 'Year'), - ], - ), - ), - ], - ), - ); - } - - Widget _buildTab(String value, String label) { - final isSelected = _period == value; - return Expanded( - child: GestureDetector( - onTap: () => setState(() => _period = value), - child: Container( - padding: const EdgeInsets.symmetric(vertical: 8), - decoration: BoxDecoration( - color: isSelected ? Colors.white : Colors.transparent, - borderRadius: BorderRadius.circular(8), - ), - child: Text( - label, - textAlign: TextAlign.center, - style: TextStyle( - color: isSelected ? const Color(0xFF047857) : Colors.white, - fontWeight: FontWeight.w500, - fontSize: 14, - ), - ), - ), - ), - ); - } - - Widget _buildQuickStats() { - return Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: const Color(0xFFD1FAE5), // emerald-100 - borderRadius: BorderRadius.circular(8), - ), - child: const Icon( - LucideIcons.trendingUp, - size: 16, - color: Color(0xFF059669), - ), - ), - const SizedBox(width: 8), - const Text( - 'This Week', - style: TextStyle( - color: AppColors.krowMuted, - fontSize: 12, - ), - ), - ], - ), - const SizedBox(height: 12), - Text( - '\$${_weeklyEarnings.toStringAsFixed(2)}', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: const Color(0xFFDBEAFE), // blue-100 - borderRadius: BorderRadius.circular(8), - ), - child: const Icon( - LucideIcons.calendar, - size: 16, - color: Color(0xFF2563EB), - ), - ), - const SizedBox(width: 8), - const Text( - 'This Month', - style: TextStyle( - color: AppColors.krowMuted, - fontSize: 12, - ), - ), - ], - ), - const SizedBox(height: 12), - Text( - '\$${_monthlyEarnings.toStringAsFixed(2)}', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - ), - ), - ], - ); - } - - Widget _buildPendingEarnings() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [ - Color(0xFFFFFBEB), - Color(0xFFFEFCE8), - ], // amber-50 to yellow-50 - ), - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - width: 48, - height: 48, - decoration: BoxDecoration( - color: const Color(0xFFFEF3C7), // amber-100 - borderRadius: BorderRadius.circular(12), - ), - child: const Icon( - LucideIcons.wallet, - color: Color(0xFFD97706), - size: 24, - ), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Pending Payout', - style: TextStyle(color: AppColors.krowMuted, fontSize: 14), - ), - Text( - '\$${_pendingEarnings.toStringAsFixed(2)}', - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - ], - ), - ElevatedButton( - onPressed: () { - // Navigate to early pay screen - context.push('/early-pay'); - }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.transparent, - padding: EdgeInsets.zero, - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [ - Color(0xFFF59E0B), - Color(0xFFF97316), - ], // amber-500 to orange-500 - ), - borderRadius: BorderRadius.circular(12), - ), - child: const Row( - children: [ - Icon(LucideIcons.zap, size: 16, color: Colors.white), - SizedBox(width: 4), - Text( - 'Instant Pay', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.w600, - fontSize: 14, - ), - ), - ], - ), - ), - ), - ], - ), - ); - } - - Widget _buildActions() { - return Row( - children: [ - Expanded( - child: OutlinedButton( - onPressed: () { - // Navigate to tax forms screen - context.push('/tax-forms'); - }, - style: OutlinedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 16), - side: const BorderSide(color: AppColors.krowBorder), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - backgroundColor: Colors.white, - ), - child: const Column( - children: [ - Icon( - LucideIcons.fileText, - color: AppColors.krowMuted, - size: 20, - ), - SizedBox(height: 8), - Text( - 'Tax Documents', - style: TextStyle(color: AppColors.krowCharcoal, fontSize: 14), - ), - ], - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: OutlinedButton( - onPressed: () {}, - style: OutlinedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 16), - side: const BorderSide(color: AppColors.krowBorder), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - backgroundColor: Colors.white, - ), - child: const Column( - children: [ - Icon( - LucideIcons.download, - color: AppColors.krowMuted, - size: 20, - ), - SizedBox(height: 8), - Text( - 'Export Report', - style: TextStyle(color: AppColors.krowCharcoal, fontSize: 14), - ), - ], - ), - ), - ), - ], - ); - } - - Widget _buildPaymentHistory() { - return Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Payment History', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ), - GestureDetector( - onTap: () {}, // Navigate to full history - child: const Row( - children: [ - Text( - 'View all', - style: TextStyle( - color: Color(0xFF7C3AED), // violet-600 - fontWeight: FontWeight.w500, - fontSize: 14, - ), - ), - Icon( - LucideIcons.chevronRight, - size: 16, - color: Color(0xFF7C3AED), - ), - ], - ), - ), - ], - ), - const SizedBox(height: 12), - ..._recentPayments.map( - (payment) => Padding( - padding: const EdgeInsets.only(bottom: 12), - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - width: 40, - height: 40, - decoration: const BoxDecoration( - color: Color(0xFFD1FAE5), // emerald-100 - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.dollarSign, - color: Color(0xFF059669), - size: 20, - ), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - '\$${payment['amount'].toStringAsFixed(2)}', - style: const TextStyle( - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ), - Text( - '${payment['shifts']} shifts • ${payment['date']}', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), - decoration: BoxDecoration( - color: const Color(0xFFD1FAE5), // emerald-100 - borderRadius: BorderRadius.circular(12), - ), - child: const Text( - 'PAID', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF047857), - ), - ), - ), - ], - ), - ), - ), - ), - ], - ); - } - - Widget _buildSavingsGoal() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [ - Color(0xFFF5F3FF), - Color(0xFFFAF5FF), - ], // violet-50 to purple-50 - ), - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Savings Goal', - style: TextStyle( - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ), - TextButton( - onPressed: () {}, - style: TextButton.styleFrom( - padding: EdgeInsets.zero, - minimumSize: Size.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - child: const Text( - 'Edit', - style: TextStyle(color: Color(0xFF7C3AED)), // violet-600 - ), - ), - ], - ), - const SizedBox(height: 12), - const Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Emergency Fund', - style: TextStyle(fontSize: 14, color: AppColors.krowMuted), - ), - Text( - '\$850 / \$1,000', - style: TextStyle( - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - const SizedBox(height: 8), - Container( - height: 8, - width: double.infinity, - decoration: BoxDecoration( - color: const Color(0xFFEDE9FE), // violet-100 - borderRadius: BorderRadius.circular(4), - ), - child: FractionallySizedBox( - alignment: Alignment.centerLeft, - widthFactor: 0.85, - child: Container( - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [ - Color(0xFF8B5CF6), - Color(0xFFA855F7), - ], // violet-500 to purple-500 - ), - borderRadius: BorderRadius.circular(4), - ), - ), - ), - ), - const SizedBox(height: 8), - const Text( - '🎯 \$150 to go! Keep it up!', - style: TextStyle(fontSize: 12, color: AppColors.krowMuted), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/jobs_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/jobs_screen.dart deleted file mode 100644 index 9eab049d..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/jobs_screen.dart +++ /dev/null @@ -1,219 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; - -import '../../theme.dart'; -import '../../services/mock_service.dart'; -import '../../models/shift.dart'; -import '../../widgets/shift_card.dart'; - -class JobsScreen extends ConsumerStatefulWidget { - const JobsScreen({super.key}); - - @override - ConsumerState createState() => _JobsScreenState(); -} - -class _JobsScreenState extends ConsumerState { - String _searchQuery = ''; - late Future> _jobsFuture; - - // Filter state - - @override - void initState() { - super.initState(); - _jobsFuture = mockService.getRecommendedShifts(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFFAFBFC), - body: SafeArea( - child: Column( - children: [ - _buildHeader(), - Expanded( - child: FutureBuilder>( - future: _jobsFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center(child: CircularProgressIndicator()); - } - - if (snapshot.hasError) { - return Center(child: Text('Error: ${snapshot.error}')); - } - - final allShifts = snapshot.data ?? []; - - // Simple Mock Filtering - final filteredShifts = allShifts.where((shift) { - // Search - if (_searchQuery.isNotEmpty) { - final q = _searchQuery.toLowerCase(); - if (!shift.title.toLowerCase().contains(q) && - !shift.clientName.toLowerCase().contains(q)) { - return false; - } - } - - return true; - }).toList(); - - return Column( - children: [ - // Results Count - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ), - child: Row( - children: [ - Text( - '${filteredShifts.length}', - style: const TextStyle( - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const Text( - ' shifts available', - style: TextStyle(color: AppColors.krowMuted), - ), - ], - ), - ), - - // List - Expanded( - child: filteredShifts.isEmpty - ? _buildEmptyState() - : ListView.builder( - padding: const EdgeInsets.symmetric( - horizontal: 20, - ), - itemCount: filteredShifts.length, - - itemBuilder: (context, index) { - final shift = filteredShifts[index]; - return ShiftCard( - shift: shift, - compact: true, - disableTapNavigation: true, // Disable navigation for Jobs screen - ); - }, - ), - ), - ], - ); - }, - ), - ), - ], - ), - ), - ); - } - - Widget _buildHeader() { - return Container( - color: Colors.white.withOpacity(0.8), - padding: const EdgeInsets.fromLTRB(20, 16, 20, 0), - child: Column( - children: [ - Row( - children: [ - GestureDetector( - onTap: () => - context.go('/worker-home'), // Use go to return to shell - child: Container( - width: 40, - height: 40, - decoration: const BoxDecoration( - color: Color(0xFFF1F5F9), // slate-100 - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: AppColors.krowMuted, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - const Text( - 'Find Shifts', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - const SizedBox(height: 16), - - // Search - Container( - height: 48, - decoration: BoxDecoration( - color: AppColors.krowYellow.withOpacity(0.2), - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBlue.withOpacity(0.1)), - ), - child: TextField( - onChanged: (val) => setState(() => _searchQuery = val), - decoration: const InputDecoration( - prefixIcon: Icon( - LucideIcons.search, - color: AppColors.krowMuted, - ), - hintText: 'Search by role, location...', - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 12), - ), - ), - ), - const SizedBox(height: 16), - ], - ), - ); - } - - Widget _buildEmptyState() { - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 64, - height: 64, - decoration: BoxDecoration( - color: const Color(0xFFF1F5F9), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.search, - size: 32, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 16), - const Text( - 'No shifts found', - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), - ), - const SizedBox(height: 4), - const Text( - 'Try adjusting your filters', - style: TextStyle(color: AppColors.krowMuted), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/payments_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/payments_screen.dart deleted file mode 100644 index e91863c4..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/payments_screen.dart +++ /dev/null @@ -1,272 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../widgets/payments/payment_stats_card.dart'; -import '../../widgets/payments/pending_pay_card.dart'; -import '../../widgets/payments/payment_history_item.dart'; - -class PaymentsScreen extends StatefulWidget { - const PaymentsScreen({super.key}); - - @override - State createState() => _PaymentsScreenState(); -} - -class _PaymentsScreenState extends State { - String _period = 'week'; - - // Mock data matching React - final double _weeklyEarnings = 847.50; - final double _monthlyEarnings = 3240; - final double _pendingEarnings = 285; - final double _totalEarnings = 12450; - - final List> _recentPayments = [ - { - 'date': 'Sat, Dec 6', - 'title': 'Cook', - 'location': 'LA Convention Center', - 'address': '1201 S Figueroa St, Los Angeles, CA 90015', - 'workedTime': '2:00 PM - 10:00 PM', - 'amount': 160.00, - 'status': 'PAID', - 'hours': 8, - 'rate': 20, - }, - { - 'date': 'Fri, Dec 5', - 'title': 'Server', - 'location': 'The Grand Hotel', - 'address': '456 Main St, Los Angeles, CA 90012', - 'workedTime': '5:00 PM - 11:00 PM', - 'amount': 176.00, - 'status': 'PAID', - 'hours': 8, - 'rate': 22, - }, - { - 'date': 'Thu, Dec 4', - 'title': 'Bartender', - 'location': 'Club Luxe', - 'address': '789 Sunset Blvd, Los Angeles, CA 90028', - 'workedTime': '6:00 PM - 2:00 AM', - 'amount': 225.00, - 'status': 'PAID', - 'hours': 9, - 'rate': 25, - }, - ]; - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFF8FAFC), // slate-50 matches React - body: SingleChildScrollView( - child: Column( - children: [ - // Header Section with Gradient - Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [Color(0xFF0032A0), Color(0xFF333F48)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - padding: EdgeInsets.fromLTRB( - 20, - MediaQuery.of(context).padding.top + 24, - 20, - 32, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "Earnings", - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - const SizedBox(height: 24), - - // Main Balance - Center( - child: Column( - children: [ - const Text( - "Total Earnings", - style: TextStyle( - color: Color(0xFFF8E08E), - fontSize: 14, - ), - ), - const SizedBox(height: 4), - Text( - "\$${_totalEarnings.toStringAsFixed(0).replaceAllMapped(RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'), (Match m) => '${m[1]},')}", - style: const TextStyle( - fontSize: 36, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ], - ), - ), - const SizedBox(height: 16), - - // Period Tabs - Container( - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(12), - ), - child: Row( - children: [ - _buildTab("Week", 'week'), - _buildTab("Month", 'month'), - _buildTab("Year", 'year'), - ], - ), - ), - ], - ), - ), - - // Main Content - Offset upwards - Transform.translate( - offset: const Offset(0, -16), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Quick Stats - Row( - children: [ - Expanded( - child: PaymentStatsCard( - icon: LucideIcons.trendingUp, - iconColor: const Color(0xFF059669), - label: "This Week", - amount: "\$${_weeklyEarnings}", // React shows 847.5 - ), - ), - const SizedBox(width: 12), - Expanded( - child: PaymentStatsCard( - icon: LucideIcons.calendar, - iconColor: const Color(0xFF2563EB), - label: "This Month", - amount: "\$${_monthlyEarnings.toStringAsFixed(0)}", - ), - ), - ], - ), - const SizedBox(height: 16), - - // Pending Pay - PendingPayCard( - amount: _pendingEarnings, - onCashOut: () { - context.push('/early-pay'); - }, - ), - const SizedBox(height: 24), - - // Recent Payments - const Text( - "Recent Payments", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - const SizedBox(height: 12), - Column( - children: _recentPayments.asMap().entries.map((entry) { - final payment = entry.value; - return Padding( - padding: const EdgeInsets.only(bottom: 8), - child: PaymentHistoryItem( - amount: (payment['amount'] as num).toDouble(), - title: payment['title'], - location: payment['location'], - address: payment['address'], - date: payment['date'], - workedTime: payment['workedTime'], - hours: payment['hours'], - rate: (payment['rate'] as num).toDouble(), - status: payment['status'], - ), - ); - }).toList(), - ), - const SizedBox(height: 16), - - // Export History Button - SizedBox( - width: double.infinity, - height: 48, - child: OutlinedButton.icon( - onPressed: () { - // Show snackbar with "PDF Exported" message - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('PDF Exported'), - duration: Duration(seconds: 2), - ), - ); - }, - icon: const Icon(LucideIcons.download, size: 16), - label: const Text("Export History"), - style: OutlinedButton.styleFrom( - foregroundColor: const Color(0xFF0F172A), - side: const BorderSide(color: Color(0xFFE2E8F0)), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - ), - ), - const SizedBox(height: 32), - ], - ), - ), - ), - ], - ), - ), - ); - } - - Widget _buildTab(String label, String value) { - final isSelected = _period == value; - return Expanded( - child: GestureDetector( - onTap: () => setState(() => _period = value), - child: Container( - padding: const EdgeInsets.symmetric(vertical: 8), - decoration: BoxDecoration( - color: isSelected ? Colors.white : Colors.transparent, - borderRadius: BorderRadius.circular(8), - ), - child: Center( - child: Text( - label, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: isSelected ? const Color(0xFF0032A0) : Colors.white, - ), - ), - ), - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/shift_details_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/shift_details_screen.dart deleted file mode 100644 index 93544cc4..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/shift_details_screen.dart +++ /dev/null @@ -1,809 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:intl/intl.dart'; -import '../../theme.dart'; -import '../../models/shift.dart'; - -class ShiftDetailsScreen extends StatefulWidget { - final String shiftId; - final Shift? shift; // Optional: pass shift object directly if available - - const ShiftDetailsScreen({super.key, required this.shiftId, this.shift}); - - @override - State createState() => _ShiftDetailsScreenState(); -} - -class _ShiftDetailsScreenState extends State { - late Shift _shift; - bool _isLoading = true; - bool _showDetails = true; - bool _isApplying = false; - - // Mock Managers - final List> _managers = [ - {'name': 'John Smith', 'phone': '+1 123 456 7890'}, - {'name': 'Jane Doe', 'phone': '+1 123 456 7890'}, - ]; - - @override - void initState() { - super.initState(); - _loadShift(); - } - - void _loadShift() async { - if (widget.shift != null) { - _shift = widget.shift!; - setState(() => _isLoading = false); - } else { - // Simulate fetch - await Future.delayed(const Duration(milliseconds: 500)); - // Fallback mock if not passed - if (mounted) { - setState(() { - _shift = Shift( - id: widget.shiftId, - title: 'Event Server', - clientName: 'Grand Hotel', - logoUrl: null, - hourlyRate: 25.0, - date: DateFormat('yyyy-MM-dd').format(DateTime.now()), - startTime: '16:00', - endTime: '22:00', - location: 'Downtown', - locationAddress: '123 Main St, New York, NY', - status: 'open', - createdDate: DateTime.now().toIso8601String(), - description: - 'Provide exceptional customer service. Respond to guest requests or concerns promptly and professionally.', - managers: [], - ); - _isLoading = false; - }); - } - } - } - - String _formatTime(String time) { - if (time.isEmpty) return ''; - try { - final parts = time.split(':'); - final hour = int.parse(parts[0]); - final minute = int.parse(parts[1]); - final dt = DateTime(2022, 1, 1, hour, minute); - return DateFormat('h:mma').format(dt).toLowerCase(); - } catch (e) { - return time; - } - } - - String _formatDate(String dateStr) { - if (dateStr.isEmpty) return ''; - try { - final date = DateTime.parse(dateStr); - return DateFormat('MMMM d').format(date); - } catch (e) { - return dateStr; - } - } - - double _calculateHours(String start, String end) { - try { - final startParts = start.split(':').map(int.parse).toList(); - final endParts = end.split(':').map(int.parse).toList(); - double h = - (endParts[0] - startParts[0]) + (endParts[1] - startParts[1]) / 60; - if (h < 0) h += 24; - return h; - } catch (e) { - return 0; - } - } - - @override - Widget build(BuildContext context) { - if (_isLoading) { - return const Scaffold( - backgroundColor: AppColors.krowBackground, - body: Center(child: CircularProgressIndicator()), - ); - } - - final hours = _calculateHours(_shift.startTime, _shift.endTime); - final totalPay = _shift.hourlyRate * hours; - - return Scaffold( - backgroundColor: AppColors.krowBackground, - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.chevronLeft, color: AppColors.krowMuted), - onPressed: () => context.pop(), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1.0), - child: Container(color: AppColors.krowBorder, height: 1.0), - ), - ), - body: Stack( - children: [ - SingleChildScrollView( - padding: const EdgeInsets.fromLTRB(20, 20, 20, 120), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Pending Badge (Mock logic) - Align( - alignment: Alignment.centerRight, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 4, - ), - decoration: BoxDecoration( - color: AppColors.krowYellow.withOpacity(0.3), - borderRadius: BorderRadius.circular(20), - ), - child: const Text( - 'Pending 6h ago', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - ), - ), - const SizedBox(height: 16), - - // Header - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 56, - height: 56, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: _shift.logoUrl != null - ? ClipRRect( - borderRadius: BorderRadius.circular(12), - child: Image.network( - _shift.logoUrl!, - fit: BoxFit.contain, - ), - ) - : Center( - child: Text( - _shift.clientName[0], - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowBlue, - ), - ), - ), - ), - const SizedBox(width: 16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - _shift.title, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - '\$${_shift.hourlyRate.toStringAsFixed(0)}/h', - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Text( - '(exp.total \$${totalPay.toStringAsFixed(0)})', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - ), - Text( - _shift.clientName, - style: const TextStyle(color: AppColors.krowMuted), - ), - ], - ), - ), - ], - ), - const SizedBox(height: 16), - - // Tags - Row( - children: [ - _buildTag( - LucideIcons.zap, - 'Immediate start', - AppColors.krowBlue.withOpacity(0.1), - AppColors.krowBlue, - ), - const SizedBox(width: 8), - _buildTag( - LucideIcons.star, - 'No experience', - AppColors.krowYellow.withOpacity(0.3), - AppColors.krowCharcoal, - ), - ], - ), - const SizedBox(height: 24), - - // Additional Details - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - children: [ - InkWell( - onTap: () => - setState(() => _showDetails = !_showDetails), - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'ADDITIONAL DETAILS', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - letterSpacing: 0.5, - color: AppColors.krowMuted, - ), - ), - Icon( - _showDetails - ? LucideIcons.chevronUp - : LucideIcons.chevronDown, - color: AppColors.krowMuted, - size: 20, - ), - ], - ), - ), - ), - if (_showDetails) - Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: Column( - children: [ - _buildDetailRow('Tips', 'Yes', true), - _buildDetailRow('Travel Time', 'Yes', true), - _buildDetailRow('Meal Provided', 'No', false), - _buildDetailRow('Parking Available', 'Yes', true), - _buildDetailRow('Gas Compensation', 'No', false), - ], - ), - ), - ], - ), - ), - const SizedBox(height: 16), - - // Date & Duration Grid - Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'START', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 8), - Text( - _formatDate(_shift.date), - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const Text( - 'Date', - style: TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 12), - Text( - _formatTime(_shift.startTime), - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const Text( - 'Time', - style: TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - ), - const SizedBox(width: 16), - Expanded( - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'DURATION', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 8), - Text( - '${hours.toStringAsFixed(0)} hours', - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const Text( - 'Shift duration', - style: TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 12), - const Text( - '1 hour', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const Text( - 'Break duration', - style: TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - ), - ], - ), - const SizedBox(height: 16), - - // Location - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'LOCATION', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - _shift.location, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Text( - _shift.locationAddress, - style: const TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - OutlinedButton.icon( - onPressed: () { - // Show snackbar with the address - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - _shift.locationAddress ?? _shift.location, - ), - duration: const Duration(seconds: 3), - ), - ); - }, - icon: const Icon(LucideIcons.navigation, size: 14), - label: const Text('Get direction'), - style: OutlinedButton.styleFrom( - foregroundColor: AppColors.krowCharcoal, - side: const BorderSide( - color: AppColors.krowBorder, - ), - textStyle: const TextStyle(fontSize: 12), - ), - ), - ], - ), - const SizedBox(height: 16), - Container( - height: 160, - width: double.infinity, - decoration: BoxDecoration( - color: const Color(0xFFF1F3F5), - borderRadius: BorderRadius.circular(12), - ), - child: const Center( - child: Icon( - LucideIcons.map, - color: AppColors.krowMuted, - size: 48, - ), - ), - ), - ], - ), - ), - const SizedBox(height: 16), - - // Manager Contact - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'MANAGER CONTACT DETAILS', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 16), - ..._managers - .map( - (manager) => Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [ - AppColors.krowBlue, - Color(0xFF0830B8), - ], - ), - borderRadius: BorderRadius.circular( - 8, - ), - ), - child: const Center( - child: Icon( - LucideIcons.user, - color: Colors.white, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - manager['name']!, - style: const TextStyle( - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ), - Text( - manager['phone']!, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - ), - OutlinedButton.icon( - onPressed: () { - // Show snackbar with the phone number - ScaffoldMessenger.of( - context, - ).showSnackBar( - SnackBar( - content: Text(manager['phone']!), - duration: const Duration(seconds: 3), - ), - ); - }, - icon: const Icon( - LucideIcons.phone, - size: 14, - color: Color(0xFF059669), - ), - label: const Text( - 'Call', - style: TextStyle( - color: Color(0xFF059669), - ), - ), - style: OutlinedButton.styleFrom( - side: const BorderSide( - color: Color(0xFFA7F3D0), - ), - backgroundColor: const Color(0xFFECFDF5), - textStyle: const TextStyle(fontSize: 12), - ), - ), - ], - ), - ), - ) - .toList(), - ], - ), - ), - const SizedBox(height: 16), - - // Additional Info - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'ADDITIONAL INFO', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 12), - Text( - _shift.description ?? - 'Providing Exceptional Customer Service.', - style: const TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - height: 1.5, - ), - ), - ], - ), - ), - ], - ), - ), - - // Bottom Actions - Positioned( - bottom: 0, - left: 0, - right: 0, - child: Container( - padding: const EdgeInsets.all(20), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: AppColors.krowBorder)), - ), - child: SafeArea( - top: false, - child: Column( - children: [ - SizedBox( - width: double.infinity, - height: 56, - child: ElevatedButton( - onPressed: () async { - setState(() => _isApplying = true); - await Future.delayed(const Duration(seconds: 1)); - if (mounted) { - setState(() => _isApplying = false); - context.pop(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Shift Accepted!'), - backgroundColor: Color(0xFF10B981), - ), - ); - } - }, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: _isApplying - ? const SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator( - color: Colors.white, - ), - ) - : const Text( - 'Accept shift', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Colors.white, - ), - ), - ), - ), - const SizedBox(height: 12), - SizedBox( - width: double.infinity, - height: 48, - child: TextButton( - onPressed: () => context.pop(), - child: const Text( - 'Decline shift', - style: TextStyle( - color: Color(0xFFEF4444), - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - ), - ), - ], - ), - ), - ), - ), - ], - ), - ); - } - - Widget _buildTag(IconData icon, String label, Color bg, Color text) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), - decoration: BoxDecoration( - color: bg, - borderRadius: BorderRadius.circular(20), - ), - child: Row( - children: [ - Icon(icon, size: 14, color: text), - const SizedBox(width: 4), - Text( - label, - style: TextStyle( - color: text, - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ], - ), - ); - } - - Widget _buildDetailRow(String label, String value, bool isPositive) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 6), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - label, - style: const TextStyle(fontSize: 14, color: AppColors.krowMuted), - ), - Text( - value, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: isPositive ? const Color(0xFF059669) : AppColors.krowMuted, - ), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/shifts_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/shifts_screen.dart deleted file mode 100644 index c46bfa5f..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/shifts_screen.dart +++ /dev/null @@ -1,1268 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:intl/intl.dart'; -import '../../theme.dart'; -import '../../models/shift.dart'; -import '../../widgets/shifts/my_shift_card.dart'; -import '../../widgets/shifts/shift_assignment_card.dart'; - -class ShiftsScreen extends StatefulWidget { - final String? initialTab; - const ShiftsScreen({super.key, this.initialTab}); - - @override - State createState() => _ShiftsScreenState(); -} - -class _ShiftsScreenState extends State { - late String _activeTab; - String _searchQuery = ''; - // ignore: unused_field - String? _cancelledShiftDemo; // 'lastMinute' or 'advance' - String _jobType = 'all'; // all, one-day, multi-day, long-term - - // Calendar State - DateTime _selectedDate = DateTime.now(); - int _weekOffset = 0; - - @override - void initState() { - super.initState(); - _activeTab = widget.initialTab ?? 'myshifts'; - } - - @override - void didUpdateWidget(ShiftsScreen oldWidget) { - super.didUpdateWidget(oldWidget); - if (widget.initialTab != null && widget.initialTab != _activeTab) { - setState(() { - _activeTab = widget.initialTab!; - }); - } - } - - // Mock Data - final List _pendingAssignments = [ - Shift( - id: 'p1', - title: 'Event Server', - clientName: 'Grand Hotel', - logoUrl: null, - hourlyRate: 25.0, - date: DateFormat( - 'yyyy-MM-dd', - ).format(DateTime.now().add(const Duration(days: 2))), - startTime: '16:00', - endTime: '22:00', - location: 'Downtown', - locationAddress: '123 Main St', - status: 'pending', - createdDate: DateTime.now().toIso8601String(), - ), - ]; - - final List _myShifts = [ - Shift( - id: 'm1', - title: 'Warehouse Assistant', - clientName: 'Amazon', - logoUrl: - 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/06/Amazon_2024.svg/500px-Amazon_2024.svg.png', - hourlyRate: 22.5, - date: DateFormat( - 'yyyy-MM-dd', - ).format(DateTime.now().add(const Duration(days: 1))), - startTime: '09:00', - endTime: '17:00', - location: 'Logistics Park', - locationAddress: '456 Industrial Way', - status: 'confirmed', - createdDate: DateTime.now().toIso8601String(), - description: 'Standard warehouse duties. Safety boots required.', - ), - ]; - - final List _availableJobs = [ - Shift( - id: 'a1', - title: 'Bartender', - clientName: 'Club Luxe', - logoUrl: null, - hourlyRate: 30.0, - date: DateFormat( - 'yyyy-MM-dd', - ).format(DateTime.now().add(const Duration(days: 3))), - startTime: '20:00', - endTime: '02:00', - location: 'City Center', - locationAddress: '789 Nightlife Blvd', - status: 'open', - createdDate: DateTime.now().toIso8601String(), - description: 'Experience mixing cocktails required.', - ), - Shift( - id: 'a2', - title: 'Line Cook (Multi-Day)', - clientName: 'Bistro Roma', - logoUrl: null, - hourlyRate: 24.0, - date: DateFormat( - 'yyyy-MM-dd', - ).format(DateTime.now().add(const Duration(days: 4))), - startTime: '15:00', - endTime: '23:00', - location: 'Little Italy', - locationAddress: '321 Pasta Ln', - status: 'open', - createdDate: DateTime.now().toIso8601String(), - description: 'Italian cuisine experience preferred. 3-day event.', - durationDays: 3, - ), - Shift( - id: 'a3', - title: 'Warehouse Manager (Long Term)', - clientName: 'Logistics Co', - logoUrl: null, - hourlyRate: 35.0, - date: DateFormat( - 'yyyy-MM-dd', - ).format(DateTime.now().add(const Duration(days: 1))), - startTime: '08:00', - endTime: '17:00', - location: 'Port Area', - locationAddress: '100 Dock St', - status: 'open', - createdDate: DateTime.now().toIso8601String(), - description: 'Long term supervisory role.', - ), - Shift( - id: 'a4', - title: 'Event Server', - clientName: 'Grand Hotel', - logoUrl: null, - hourlyRate: 22.0, - date: DateFormat('yyyy-MM-dd').format(DateTime.now()), - startTime: '18:00', - endTime: '23:00', - location: 'Downtown', - locationAddress: '456 Main St', - status: 'open', - createdDate: DateTime.now().toIso8601String(), - description: 'Wedding reception service. Black tie attire required.', - ), - Shift( - id: 'a5', - title: 'Retail Associate (Multi-Day)', - clientName: 'Fashion Outlet', - logoUrl: null, - hourlyRate: 18.0, - date: DateFormat( - 'yyyy-MM-dd', - ).format(DateTime.now().add(const Duration(days: 2))), - startTime: '10:00', - endTime: '18:00', - location: 'Shopping Mall', - locationAddress: '200 Retail Plaza', - status: 'open', - createdDate: DateTime.now().toIso8601String(), - description: 'Weekend sale event. Customer service experience needed.', - durationDays: 2, - ), - Shift( - id: 'a6', - title: 'Construction Helper', - clientName: 'BuildCo', - logoUrl: null, - hourlyRate: 28.0, - date: DateFormat( - 'yyyy-MM-dd', - ).format(DateTime.now().add(const Duration(days: 1))), - startTime: '07:00', - endTime: '15:00', - location: 'North District', - locationAddress: '789 Construction Site', - status: 'open', - createdDate: DateTime.now().toIso8601String(), - description: 'General labor. Safety equipment provided.', - ), - Shift( - id: 'a7', - title: 'Office Administrator (Long Term)', - clientName: 'Tech Startup', - logoUrl: null, - hourlyRate: 32.0, - date: DateFormat( - 'yyyy-MM-dd', - ).format(DateTime.now().add(const Duration(days: 7))), - startTime: '09:00', - endTime: '17:00', - location: 'Tech Hub', - locationAddress: '500 Innovation Dr', - status: 'open', - createdDate: DateTime.now().toIso8601String(), - description: - '6-month contract position. Office management experience required.', - ), - Shift( - id: 'a8', - title: 'Delivery Driver', - clientName: 'QuickShip', - logoUrl: null, - hourlyRate: 25.0, - date: DateFormat('yyyy-MM-dd').format(DateTime.now()), - startTime: '12:00', - endTime: '20:00', - location: 'Citywide', - locationAddress: '100 Logistics Center', - status: 'open', - createdDate: DateTime.now().toIso8601String(), - description: 'Valid driver license required. Own vehicle preferred.', - ), - Shift( - id: 'a9', - title: 'Conference Staff (Multi-Day)', - clientName: 'TechCon 2024', - logoUrl: null, - hourlyRate: 26.0, - date: DateFormat( - 'yyyy-MM-dd', - ).format(DateTime.now().add(const Duration(days: 5))), - startTime: '08:00', - endTime: '18:00', - location: 'Convention Center', - locationAddress: '300 Conference Dr', - status: 'open', - createdDate: DateTime.now().toIso8601String(), - description: '4-day tech conference. Registration and attendee support.', - durationDays: 4, - ), - Shift( - id: 'a10', - title: 'Festival Vendor (Multi-Day)', - clientName: 'Summer Music Fest', - logoUrl: null, - hourlyRate: 20.0, - date: DateFormat( - 'yyyy-MM-dd', - ).format(DateTime.now().add(const Duration(days: 10))), - startTime: '11:00', - endTime: '23:00', - location: 'City Park', - locationAddress: '400 Park Ave', - status: 'open', - createdDate: DateTime.now().toIso8601String(), - description: '5-day music festival. Food and beverage service.', - durationDays: 5, - ), - ]; - - final List _historyShifts = [ - Shift( - id: 'h1', - title: 'Event Staff', - clientName: 'Convention Center', - logoUrl: null, - hourlyRate: 20.0, - date: DateFormat( - 'yyyy-MM-dd', - ).format(DateTime.now().subtract(const Duration(days: 5))), - startTime: '08:00', - endTime: '16:00', - location: 'South Hall', - locationAddress: '555 Exhibit Dr', - status: 'completed', - createdDate: DateTime.now() - .subtract(const Duration(days: 10)) - .toIso8601String(), - ), - ]; - - List _getCalendarDays() { - final now = DateTime.now(); - // In Dart, weekday is 1(Mon)..7(Sun). - // React logic: currentDay is 0(Sun)..6(Sat). - // React: daysSinceFriday = (currentDay + 2) % 7. - // Let's map Dart weekday to React day index: - // Mon(1)->1, Tue(2)->2, ..., Sat(6)->6, Sun(7)->0. - int reactDayIndex = now.weekday == 7 ? 0 : now.weekday; - int daysSinceFriday = (reactDayIndex + 2) % 7; - - // Start date is now - daysSinceFriday + (weekOffset * 7) - final start = now - .subtract(Duration(days: daysSinceFriday)) - .add(Duration(days: _weekOffset * 7)); - // Reset to midnight - final startDate = DateTime(start.year, start.month, start.day); - - return List.generate(7, (index) => startDate.add(Duration(days: index))); - } - - bool _isSameDay(DateTime a, DateTime b) { - return a.year == b.year && a.month == b.month && a.day == b.day; - } - - void _confirmShift(String id) { - setState(() { - final index = _pendingAssignments.indexWhere((shift) => shift.id == id); - if (index != -1) { - final confirmedShift = _pendingAssignments.removeAt(index); - // In a real app, this would be added to _myShifts with status 'confirmed' - // For now, just remove from pending and show snackbar - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Shift ${confirmedShift.title} confirmed! (Placeholder)'), - duration: const Duration(seconds: 2), - ), - ); - } - }); - } - - void _declineShift(String id) { - setState(() { - final index = _pendingAssignments.indexWhere((shift) => shift.id == id); - if (index != -1) { - final declinedShift = _pendingAssignments.removeAt(index); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Shift ${declinedShift.title} declined. (Placeholder)'), - duration: const Duration(seconds: 2), - ), - ); - } - }); - } - - @override - Widget build(BuildContext context) { - // Filter available jobs based on search and job type - final filteredJobs = _availableJobs.where((s) { - final matchesSearch = - s.title.toLowerCase().contains(_searchQuery.toLowerCase()) || - s.location.toLowerCase().contains(_searchQuery.toLowerCase()) || - s.clientName.toLowerCase().contains(_searchQuery.toLowerCase()); - - if (!matchesSearch) return false; - - if (_jobType == 'all') return true; - if (_jobType == 'one-day') { - // Mock: Consider anything without "Long Term" in title as one day for demo - return !s.title.contains('Long Term') && !s.title.contains('Multi-Day'); - } - if (_jobType == 'multi-day') { - return s.title.contains('Multi-Day'); - } - if (_jobType == 'long-term') { - return s.title.contains('Long Term'); - } - return true; - }).toList(); - - // Calculate dates for current week view - final calendarDays = _getCalendarDays(); - final weekStartDate = calendarDays.first; - final weekEndDate = calendarDays.last; - - // Filter my shifts by week - final visibleMyShifts = _myShifts.where((s) { - final sDateStr = s.date; - final wStartStr = DateFormat('yyyy-MM-dd').format(weekStartDate); - final wEndStr = DateFormat('yyyy-MM-dd').format(weekEndDate); - return sDateStr.compareTo(wStartStr) >= 0 && - sDateStr.compareTo(wEndStr) <= 0; - }).toList(); - - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: Column( - children: [ - // Header - Container( - color: AppColors.krowBlue, - padding: EdgeInsets.fromLTRB( - 20, - MediaQuery.of(context).padding.top + 20, - 20, - 24, // React: pb-6 (24px) - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - "Shifts", - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - // Demo Buttons - Row( - children: [ - _buildDemoButton( - "Demo: Cancel <4hr", - const Color(0xFFEF4444), - () { - setState(() => _cancelledShiftDemo = 'lastMinute'); - _showCancelledModal('lastMinute'); - }, - ), - const SizedBox(width: 8), - _buildDemoButton( - "Demo: Cancel >4hr", - const Color(0xFFF59E0B), - () { - setState(() => _cancelledShiftDemo = 'advance'); - _showCancelledModal('advance'); - }, - ), - ], - ), - ], - ), - const SizedBox(height: 16), - - // Tabs - Row( - children: [ - _buildTab( - "myshifts", - "My Shifts", - LucideIcons.calendar, - _myShifts.length, - ), - const SizedBox(width: 8), - _buildTab( - "find", - "Find Shifts", - LucideIcons.search, - filteredJobs.length, - ), - const SizedBox(width: 8), - _buildTab( - "history", - "History", - LucideIcons.clock, - _historyShifts.length, - ), - ], - ), - ], - ), - ), - - // Calendar Selector (Only for My Shifts) - if (_activeTab == 'myshifts') - Container( - color: Colors.white, - padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 20), - child: Column( - children: [ - // Month/Year Header - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - onTap: () => setState(() => _weekOffset--), - borderRadius: BorderRadius.circular(20), - child: const Padding( - padding: EdgeInsets.all(8.0), - child: Icon( - LucideIcons.chevronLeft, - size: 20, - color: AppColors.krowCharcoal, - ), - ), - ), - Text( - DateFormat('MMMM yyyy').format(weekStartDate), - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ), - InkWell( - onTap: () => setState(() => _weekOffset++), - borderRadius: BorderRadius.circular(20), - child: const Padding( - padding: EdgeInsets.all(8.0), - child: Icon( - LucideIcons.chevronRight, - size: 20, - color: AppColors.krowCharcoal, - ), - ), - ), - ], - ), - ), - // Days Grid - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: calendarDays.map((date) { - final isSelected = _isSameDay(date, _selectedDate); - final dateStr = DateFormat('yyyy-MM-dd').format(date); - final hasShifts = _myShifts.any((s) => s.date == dateStr); - - return GestureDetector( - onTap: () => setState(() => _selectedDate = date), - child: Container( - width: 44, // roughly grid cols 7 - padding: const EdgeInsets.symmetric(vertical: 12), - decoration: BoxDecoration( - color: isSelected - ? AppColors.krowBlue - : Colors.white, - borderRadius: BorderRadius.circular( - 999, - ), // full rounded - border: Border.all( - color: isSelected - ? AppColors.krowBlue - : AppColors.krowBorder, - width: 1, - ), - ), - child: Column( - children: [ - Text( - date.day.toString().padLeft(2, '0'), - style: TextStyle( - fontSize: 20, // text-xl - fontWeight: FontWeight.bold, - color: isSelected - ? Colors.white - : AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 2), - Text( - DateFormat('E').format(date), // short weekday - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w500, - color: isSelected - ? Colors.white.withOpacity(0.8) - : AppColors.krowMuted, - ), - ), - if (hasShifts) - Container( - margin: const EdgeInsets.only(top: 4), - width: 6, - height: 6, - decoration: BoxDecoration( - color: isSelected - ? Colors.white - : AppColors.krowBlue, - shape: BoxShape.circle, - ), - ), - ], - ), - ), - ); - }).toList(), - ), - ], - ), - ), - - if (_activeTab == 'myshifts') - const Divider(height: 1, color: AppColors.krowBorder), - - // Body - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - // Search Bar & Job Type Filter (Find Work Only) - if (_activeTab == 'find') ...[ - // Search Bar - Padding( - padding: const EdgeInsets.only(bottom: 12), - child: Container( - height: 48, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: TextField( - onChanged: (val) => - setState(() => _searchQuery = val), - decoration: const InputDecoration( - prefixIcon: Icon( - LucideIcons.search, - size: 20, - color: AppColors.krowMuted, - ), - border: InputBorder.none, - hintText: "Search jobs...", - hintStyle: TextStyle( - color: AppColors.krowMuted, - fontSize: 14, - ), - contentPadding: EdgeInsets.symmetric(vertical: 12), - ), - ), - ), - ), - - // Job Type Filter Tabs (React-style equal width) - Container( - margin: const EdgeInsets.only(bottom: 16), - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - color: const Color(0xFFF1F3F5), - borderRadius: BorderRadius.circular(999), - ), - child: Row( - children: [ - _buildFilterTab('all', 'All Jobs'), - _buildFilterTab('one-day', 'One Day'), - _buildFilterTab('multi-day', 'Multi-Day'), - _buildFilterTab('long-term', 'Long Term'), - ], - ), - ), - ], - // Content Stacks - if (_activeTab == 'myshifts') ...[ - // Pending Assignments - if (_pendingAssignments.isNotEmpty) ...[ - Align( - alignment: Alignment.centerLeft, - child: Padding( - padding: const EdgeInsets.only(bottom: 12), - child: Row( - children: [ - Container( - width: 8, - height: 8, - decoration: const BoxDecoration( - color: Color(0xFFF59E0B), // amber-500 - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 8), - const Text( - "Awaiting Confirmation", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFFD97706), // amber-600 - ), - ), - ], - ), - ), - ), - ..._pendingAssignments.map( - (shift) => Padding( - padding: const EdgeInsets.only(bottom: 16), - child: ShiftAssignmentCard( - shift: shift, - onConfirm: () => _confirmShift(shift.id), - onDecline: () => _declineShift(shift.id), - ), - ), - ), - ], - - // Cancelled Shift Demo (Static List as per React) - Align( - alignment: Alignment.centerLeft, - child: Padding( - padding: const EdgeInsets.only(bottom: 12), - child: const Text( - "Cancelled Shifts", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: AppColors.krowMuted, - ), - ), - ), - ), - // Card 1: Cancelled <4hr - _buildCancelledCard( - title: "Annual Tech Conference", - client: "TechCorp Inc.", - pay: "\$200", - rate: "\$25/hr · 8h", - date: "Today", - time: "10:00 AM - 6:00 PM", - address: "123 Convention Center Dr, San Jose, CA", - isLastMinute: true, - onTap: () => - setState(() => _cancelledShiftDemo = 'lastMinute'), - ), - const SizedBox(height: 12), - // Card 2: Cancelled >4hr - _buildCancelledCard( - title: "Morning Catering Setup", - client: "EventPro Services", - pay: "\$120", - rate: "\$20/hr · 6h", - date: "Tomorrow", - time: "8:00 AM - 2:00 PM", - address: "456 Grand Ballroom Ave, San Francisco, CA", - isLastMinute: false, - onTap: () => - setState(() => _cancelledShiftDemo = 'advance'), - ), - const SizedBox(height: 24), - - // Confirmed Shifts - if (visibleMyShifts.isEmpty && - _pendingAssignments.isEmpty) ...[ - // Empty State - _buildEmptyState( - LucideIcons.calendar, - "No upcoming shifts", - "Find work to get started", - "Find Work", - () => setState(() => _activeTab = 'find'), - ), - ] else if (visibleMyShifts.isNotEmpty) ...[ - // Header only if other sections exist - if (_pendingAssignments.isNotEmpty) - Align( - alignment: Alignment.centerLeft, - child: Padding( - padding: const EdgeInsets.only(bottom: 12), - child: const Text( - "Confirmed Shifts", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: AppColors.krowMuted, - ), - ), - ), - ), - ...visibleMyShifts.map( - (shift) => MyShiftCard( - shift: shift, - onDecline: () {}, - onRequestSwap: () {}, - ), - ), - ], - ], - - if (_activeTab == 'find') ...[ - if (filteredJobs.isEmpty) - _buildEmptyState( - LucideIcons.search, - "No jobs available", - "Check back later", - null, - null, - ) - else - ...filteredJobs.map( - (shift) => MyShiftCard( - shift: shift, - onAccept: () {}, - onDecline: () {}, - ), - ), - ], - - if (_activeTab == 'history') ...[ - if (_historyShifts.isEmpty) - _buildEmptyState( - LucideIcons.clock, - "No shift history", - "Completed shifts appear here", - null, - null, - ) - else - ..._historyShifts.map( - (shift) => MyShiftCard(shift: shift, historyMode: true), - ), - ], - ], - ), - ), - ), - ], - ), - ); - } - - Widget _buildFilterTab(String id, String label) { - final isSelected = _jobType == id; - return Expanded( - child: GestureDetector( - onTap: () => setState(() => _jobType = id), - child: Container( - padding: const EdgeInsets.symmetric(vertical: 8), - decoration: BoxDecoration( - color: isSelected ? AppColors.krowBlue : Colors.transparent, - borderRadius: BorderRadius.circular(999), - boxShadow: isSelected - ? [ - BoxShadow( - color: AppColors.krowBlue.withOpacity(0.2), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ] - : null, - ), - child: Text( - label, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.w600, - color: isSelected ? Colors.white : AppColors.krowMuted, - ), - ), - ), - ), - ); - } - - Widget _buildTab(String id, String label, IconData icon, int count) { - final isActive = _activeTab == id; - return Expanded( - child: GestureDetector( - onTap: () => setState(() => _activeTab = id), - child: Container( - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 8), - decoration: BoxDecoration( - color: isActive - ? Colors.white - : Colors.white.withAlpha((0.2 * 255).round()), - borderRadius: BorderRadius.circular(8), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - icon, - size: 14, - color: isActive ? AppColors.krowBlue : Colors.white, - ), - const SizedBox(width: 6), - Flexible( - child: Text( - label, - style: TextStyle( - fontSize: 13, - fontWeight: FontWeight.w500, - color: isActive ? AppColors.krowBlue : Colors.white, - ), - overflow: TextOverflow.ellipsis, - ), - ), - const SizedBox(width: 4), - Container( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - constraints: const BoxConstraints(minWidth: 18), - decoration: BoxDecoration( - color: isActive - ? AppColors.krowBlue.withAlpha((0.1 * 255).round()) - : Colors.white.withAlpha((0.2 * 255).round()), - borderRadius: BorderRadius.circular(999), - ), - child: Center( - child: Text( - "$count", - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: isActive ? AppColors.krowBlue : Colors.white, - ), - ), - ), - ), - ], - ), - ), - ), - ); - } - - Widget _buildDemoButton(String label, Color color, VoidCallback onTap) { - return GestureDetector( - onTap: onTap, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: color, - borderRadius: BorderRadius.circular(4), - ), - child: Text( - label, - style: const TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ), - ); - } - - Widget _buildEmptyState( - IconData icon, - String title, - String subtitle, - String? actionLabel, - VoidCallback? onAction, - ) { - return Center( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 64), - child: Column( - children: [ - Container( - width: 64, - height: 64, - decoration: BoxDecoration( - color: const Color(0xFFF1F3F5), - borderRadius: BorderRadius.circular(12), - ), - child: Icon(icon, size: 32, color: AppColors.krowMuted), - ), - const SizedBox(height: 16), - Text( - title, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 4), - Text( - subtitle, - style: const TextStyle(fontSize: 14, color: AppColors.krowMuted), - ), - if (actionLabel != null && onAction != null) ...[ - const SizedBox(height: 16), - ElevatedButton( - onPressed: onAction, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - child: Text(actionLabel), - ), - ], - ], - ), - ), - ); - } - - Widget _buildCancelledCard({ - required String title, - required String client, - required String pay, - required String rate, - required String date, - required String time, - required String address, - required bool isLastMinute, - required VoidCallback onTap, - }) { - return GestureDetector( - onTap: onTap, - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Container( - width: 6, - height: 6, - decoration: const BoxDecoration( - color: Color(0xFFEF4444), - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 6), - const Text( - "CANCELLED", - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: Color(0xFFEF4444), - ), - ), - if (isLastMinute) ...[ - const SizedBox(width: 4), - const Text( - "• 4hr compensation", - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w500, - color: Color(0xFF10B981), - ), - ), - ], - ], - ), - const SizedBox(height: 12), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 44, - height: 44, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - AppColors.krowBlue.withAlpha((0.15 * 255).round()), - AppColors.krowBlue.withAlpha((0.08 * 255).round()), - ], - ), - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: AppColors.krowBlue.withAlpha((0.15 * 255).round()), - ), - ), - child: const Center( - child: Icon( - LucideIcons.briefcase, - color: AppColors.krowBlue, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ), - Text( - client, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - pay, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Text( - rate, - style: const TextStyle( - fontSize: 10, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - ), - const SizedBox(height: 8), - Row( - children: [ - const Icon( - LucideIcons.calendar, - size: 12, - color: AppColors.krowMuted, - ), - const SizedBox(width: 4), - Text( - date, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - const SizedBox(width: 12), - const Icon( - LucideIcons.clock, - size: 12, - color: AppColors.krowMuted, - ), - const SizedBox(width: 4), - Text( - time, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - const SizedBox(height: 4), - Row( - children: [ - const Icon( - LucideIcons.mapPin, - size: 12, - color: AppColors.krowMuted, - ), - const SizedBox(width: 4), - Expanded( - child: Text( - address, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ], - ), - ), - ], - ), - ], - ), - ), - ); - } - - void _showCancelledModal(String type) { - final isLastMinute = type == 'lastMinute'; - showDialog( - context: context, - builder: (context) => AlertDialog( - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), - title: Row( - children: [ - const Icon(LucideIcons.xCircle, color: Color(0xFFEF4444)), - const SizedBox(width: 8), - const Text("Shift Cancelled"), - ], - ), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "We're sorry, but the following shift has been cancelled by the client:", - style: TextStyle(fontSize: 14), - ), - const SizedBox(height: 12), - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.grey.shade50, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: Colors.grey.shade200), - ), - child: const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Annual Tech Conference", - style: TextStyle(fontWeight: FontWeight.bold), - ), - Text("Today, 10:00 AM - 6:00 PM"), - ], - ), - ), - const SizedBox(height: 16), - if (isLastMinute) - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFFECFDF5), - borderRadius: BorderRadius.circular(8), - border: Border.all(color: const Color(0xFF10B981)), - ), - child: const Row( - children: [ - Icon( - LucideIcons.checkCircle, - color: Color(0xFF10B981), - size: 16, - ), - SizedBox(width: 8), - Expanded( - child: Text( - "You are eligible for 4hr cancellation compensation.", - style: TextStyle( - fontSize: 12, - color: Color(0xFF065F46), - fontWeight: FontWeight.w500, - ), - ), - ), - ], - ), - ) - else - const Text( - "Reduced schedule at the venue. No compensation is due as this was cancelled more than 4 hours in advance.", - style: TextStyle(fontSize: 12, color: AppColors.krowMuted), - ), - ], - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text("Close"), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_home_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_home_screen.dart deleted file mode 100644 index c9c30170..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_home_screen.dart +++ /dev/null @@ -1,825 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import '../../theme.dart'; -import '../../widgets/shift_card.dart'; -import '../../widgets/worker/auto_match_toggle.dart'; -import '../../widgets/worker/benefits_widget.dart'; -import '../../widgets/worker/improve_yourself_widget.dart'; -import '../../widgets/worker/more_ways_widget.dart'; -import '../../services/mock_service.dart'; -import '../../models/shift.dart'; - -class WorkerHomeScreen extends ConsumerStatefulWidget { - const WorkerHomeScreen({super.key}); - - @override - ConsumerState createState() => _WorkerHomeScreenState(); -} - -class _WorkerHomeScreenState extends ConsumerState { - late Future> _todayShiftsFuture; - late Future> _tomorrowShiftsFuture; - late Future> _recommendedShiftsFuture; - bool _autoMatchEnabled = false; - bool _isProfileComplete = false; // Added for mock profile completion - - @override - void initState() { - super.initState(); - _todayShiftsFuture = mockService.getTodayShifts(); - _tomorrowShiftsFuture = mockService.getTomorrowShifts(); - _recommendedShiftsFuture = mockService.getRecommendedShifts(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: SafeArea( - child: SingleChildScrollView( - padding: const EdgeInsets.only(bottom: 100), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildHeader(), - - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - children: [ - if (!_isProfileComplete) - _buildPlaceholderBanner( - "Complete Your Profile", - "Get verified to see more shifts", - Colors.blue[50]!, - Colors.blue, - onTap: () { - context.push('/worker-profile'); - }, - ), - const SizedBox(height: 20), - _buildPlaceholderBanner( - "Availability", - "Update your availability for next week", - Colors.orange[50]!, - Colors.orange, - onTap: () => context.push('/availability'), - ), - const SizedBox(height: 20), - - // Auto Match Toggle - AutoMatchToggle( - enabled: _autoMatchEnabled, - onToggle: (val) => - setState(() => _autoMatchEnabled = val), - ), - const SizedBox(height: 20), - - // Quick Actions - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: _buildQuickAction( - context, - LucideIcons.search, - "Find Shifts", - () => context.go('/shifts'), - ), - ), - Expanded( - child: _buildQuickAction( - context, - LucideIcons.calendar, - "Availability", - () => context.push('/availability'), - ), - ), - Expanded( - child: _buildQuickAction( - context, - LucideIcons.messageSquare, - "Messages", - () => context.push('/messages'), - ), - ), - Expanded( - child: _buildQuickAction( - context, - LucideIcons.dollarSign, - "Earnings", - () => context.go('/payments'), - ), - ), - ], - ), - const SizedBox(height: 24), - - // Today's Shifts - FutureBuilder>( - future: _todayShiftsFuture, - builder: (context, snapshot) { - final shifts = snapshot.data ?? []; - return Column( - children: [ - _buildSectionHeader( - "Today's Shift", - shifts.isNotEmpty - ? "${shifts.length} scheduled" - : null, - ), - if (shifts.isEmpty) - _buildEmptyState( - "No shifts scheduled for today", - "Find shifts →", - () => context.go('/shifts?tab=find'), - ) - else - Column( - children: shifts - .map( - (shift) => ShiftCard( - shift: shift, - compact: true, - ), - ) - .toList(), - ), - ], - ); - }, - ), - const SizedBox(height: 24), - - // Tomorrow's Shifts - FutureBuilder>( - future: _tomorrowShiftsFuture, - builder: (context, snapshot) { - final shifts = snapshot.data ?? []; - return Column( - children: [ - _buildSectionHeader("Tomorrow", null), - if (shifts.isEmpty) - _buildEmptyState("No shifts for tomorrow", null) - else - Column( - children: shifts - .map( - (shift) => ShiftCard( - shift: shift, - compact: true, - ), - ) - .toList(), - ), - ], - ); - }, - ), - const SizedBox(height: 24), - - // Pending Payment Card - _buildPendingPaymentCard(), - const SizedBox(height: 24), - - // Recommended Shifts - _buildSectionHeader("Recommended for You", "View all"), - FutureBuilder>( - future: _recommendedShiftsFuture, - builder: (context, snapshot) { - if (!snapshot.hasData || snapshot.data!.isEmpty) { - return _buildEmptyState( - "No recommended shifts", - null, - ); - } - return SizedBox( - height: 160, // Adjusted height for horizontal list - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: snapshot.data!.length, - clipBehavior: Clip.none, // Allow shadows to paint - itemBuilder: (context, index) { - return Padding( - padding: const EdgeInsets.only(right: 12), - child: _buildRecommendedCard( - snapshot.data![index], - ), - ); - }, - ), - ); - }, - ), - const SizedBox(height: 24), - - // Benefits Widget - const BenefitsWidget(), - const SizedBox(height: 24), - - // Improve Yourself - const ImproveYourselfWidget(), - const SizedBox(height: 24), - - // More Ways To Use Krow - const MoreWaysToUseKrowWidget(), - ], - ), - ), - ], - ), - ), - ), - ); - } - - Widget _buildSectionHeader(String title, String? action) { - return Padding( - padding: const EdgeInsets.only(bottom: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - title, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, // semibold - color: AppColors.krowCharcoal, - ), - ), - if (action != null) - if (action == "View all") - GestureDetector( - onTap: () => context.go('/shifts?tab=find'), - child: const Row( - children: [ - Text( - "View all", - style: TextStyle( - color: AppColors.krowBlue, - fontSize: 14, - fontWeight: FontWeight.w500, - ), - ), - Icon( - LucideIcons.chevronRight, - size: 16, - color: AppColors.krowBlue, - ), - ], - ), - ) - else - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), - decoration: BoxDecoration( - color: AppColors.krowBlue.withValues(alpha: 0.08), - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: AppColors.krowBlue.withValues(alpha: 0.2), - ), - ), - child: Text( - action, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: AppColors.krowBlue, - ), - ), - ), - ], - ), - ); - } - - Widget _buildEmptyState( - String message, - String? actionLink, [ - VoidCallback? onAction, - ]) { - return Container( - width: double.infinity, - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFFF1F3F5), // secondary - borderRadius: BorderRadius.circular(8), // rounded-lg - ), - alignment: Alignment.center, - child: Column( - children: [ - Text( - message, - style: const TextStyle(color: AppColors.krowMuted, fontSize: 14), - ), - if (actionLink != null) - GestureDetector( - onTap: onAction, - child: Padding( - padding: const EdgeInsets.only(top: 4), - child: Text( - actionLink, - style: const TextStyle( - color: AppColors.krowBlue, - fontSize: 14, - fontWeight: FontWeight.w500, - ), - ), - ), - ), - ], - ), - ); - } - - Widget _buildHeader() { - return Padding( - padding: const EdgeInsets.fromLTRB(20, 24, 20, 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - width: 48, - height: 48, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: AppColors.krowBlue.withValues(alpha: 0.2), - width: 2, - ), - ), - child: CircleAvatar( - backgroundColor: AppColors.krowBlue.withValues(alpha: 0.1), - child: const Text( - 'K', - style: TextStyle( - color: AppColors.krowBlue, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - const SizedBox(width: 12), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Welcome back', - style: TextStyle(color: AppColors.krowMuted, fontSize: 14), - ), - Text( - 'Krower', - style: TextStyle( - color: AppColors.krowCharcoal, - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ], - ), - Row( - children: [ - GestureDetector( - onTap: () => context.push('/messages'), - child: Stack( - children: [ - _buildHeaderIcon(LucideIcons.bell), - const Positioned( - top: -2, - right: -2, - child: CircleAvatar( - radius: 8, - backgroundColor: Color(0xFFF04444), - child: Text( - '2', - style: TextStyle( - color: Colors.white, - fontSize: 10, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ), - ), - const SizedBox(width: 8), - GestureDetector( - onTap: () => context.go('/worker-profile'), - child: _buildHeaderIcon(LucideIcons.settings), - ), - ], - ), - ], - ), - ); - } - - Widget _buildHeaderIcon(IconData icon) { - return Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - boxShadow: [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Icon(icon, color: AppColors.krowMuted, size: 20), - ); - } - - Widget _buildPlaceholderBanner( - String title, - String subtitle, - Color bg, - Color accent, { - VoidCallback? onTap, - }) { - return GestureDetector( - onTap: onTap, - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: bg, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: accent.withValues(alpha: 0.3)), - ), - child: Row( - children: [ - Container( - padding: const EdgeInsets.all(8), - decoration: const BoxDecoration( - color: Colors.white, - shape: BoxShape.circle, - ), - child: Icon(LucideIcons.star, color: accent, size: 20), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Text( - subtitle, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - Icon(LucideIcons.chevronRight, color: accent), - ], - ), - ), - ); - } - - Widget _buildQuickAction( - BuildContext context, - IconData icon, - String label, - VoidCallback onTap, - ) { - return GestureDetector( - onTap: onTap, - child: Column( - children: [ - Container( - width: 50, - height: 50, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: const Color(0xFFF1F5F9)), - boxShadow: [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.05), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Icon(icon, color: AppColors.krowBlue, size: 24), - ), - const SizedBox(height: 8), - Text( - label, - style: const TextStyle( - fontSize: 10, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - ); - } - - Widget _buildPendingPaymentCard() { - return GestureDetector( - onTap: () => context.go('/payments'), - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [Colors.blue[50]!.withValues(alpha: 0.5), Colors.blue[50]!], - begin: Alignment.centerLeft, - end: Alignment.centerRight, - ), - borderRadius: BorderRadius.circular(16), - border: Border.all(color: Colors.blue[100]!.withValues(alpha: 0.5)), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Row( - children: [ - Container( - width: 40, - height: 40, - decoration: const BoxDecoration( - color: Color(0xFFE8F0FF), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.dollarSign, - color: Color(0xFF0047FF), - size: 20, - ), - ), - const SizedBox(width: 12), - const Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Pending Payment", - style: TextStyle( - fontWeight: FontWeight.w500, - fontSize: 14, - color: AppColors.krowCharcoal, - ), - overflow: TextOverflow.ellipsis, - ), - Text( - "Payment processing", - style: TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - overflow: TextOverflow.ellipsis, - ), - ], - ), - ), - ], - ), - ), - const Row( - children: [ - Text( - "\$285.00", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Color(0xFF0047FF), - ), - ), - SizedBox(width: 8), - Icon( - LucideIcons.chevronRight, - color: Color(0xFF94A3B8), - size: 20, - ), - ], - ), - ], - ), - ), - ); - } - - Widget _buildRecommendedCard(Shift shift) { - // Basic calculation for total pay - final duration = 8; // Simplified duration - final totalPay = duration * shift.hourlyRate; - - return GestureDetector( - onTap: () { - // Apply for the shift (matching React's applyMutation logic) - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Applied for ${shift.title}'), - backgroundColor: Colors.green, - duration: const Duration(seconds: 2), - ), - ); - }, - child: Container( - width: 300, - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: AppColors.krowBorder), - boxShadow: [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.02), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - // Badges - Row( - children: [ - const Text( - "• ACT NOW", - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: Color(0xFFDC2626), // red-600 - ), - ), - const SizedBox(width: 8), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 2, - ), - decoration: BoxDecoration( - color: const Color(0xFFE8F0FF), - borderRadius: BorderRadius.circular(999), - ), - child: const Text( - "One Day", - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w500, - color: Color(0xFF0047FF), - ), - ), - ), - ], - ), - const SizedBox(height: 12), - // Content - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 44, - height: 44, - decoration: BoxDecoration( - color: const Color(0xFFE8F0FF), - borderRadius: BorderRadius.circular(12), - ), - child: const Icon( - LucideIcons.calendar, - color: Color(0xFF0047FF), - size: 20, - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - shift.title, - style: const TextStyle( - fontWeight: FontWeight.w600, - fontSize: 16, - color: AppColors.krowCharcoal, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - Text( - "\$${totalPay.round()}", - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - const SizedBox(height: 2), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - shift.clientName, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - Text( - "\$${shift.hourlyRate.toStringAsFixed(0)}/hr • ${duration}h", - style: const TextStyle( - fontSize: 10, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - ), - ), - ], - ), - const SizedBox(height: 12), - // Footer Info - Row( - children: [ - const Icon( - LucideIcons.calendar, - size: 14, - color: AppColors.krowMuted, - ), - const SizedBox(width: 4), - Text( - "Today", // Mock - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - const SizedBox(width: 12), - const Icon( - LucideIcons.clock, - size: 14, - color: AppColors.krowMuted, - ), - const SizedBox(width: 4), - Text( - "${shift.startTime} - ${shift.endTime}", - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - const SizedBox(height: 4), - Row( - children: [ - const Icon( - LucideIcons.mapPin, - size: 14, - color: AppColors.krowMuted, - ), - const SizedBox(width: 4), - Expanded( - child: Text( - shift.locationAddress ?? shift.location, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ], - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/certificates_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/certificates_screen.dart deleted file mode 100644 index 6350b7bd..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/certificates_screen.dart +++ /dev/null @@ -1,908 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import 'package:intl/intl.dart'; -import '../../../../theme.dart'; - -class CertificatesScreen extends ConsumerStatefulWidget { - const CertificatesScreen({super.key}); - - @override - ConsumerState createState() => _CertificatesScreenState(); -} - -class _CertificatesScreenState extends ConsumerState { - // Mock Data - final List> _certificates = [ - { - 'id': 'background', - 'name': 'Background Check', - 'icon': LucideIcons.fileCheck, - 'color': const Color(0xFF0A39DF), - 'description': 'Required for all shifts', - 'status': 'COMPLETED', - 'expiry': DateTime.now().add(const Duration(days: 365)).toIso8601String(), - }, - { - 'id': 'food_handler', - 'name': 'Food Handler', - 'icon': LucideIcons.utensils, - 'color': const Color(0xFF0A39DF), - 'description': 'Required for food service', - 'status': 'EXPIRING', // within 30 days - 'expiry': DateTime.now().add(const Duration(days: 15)).toIso8601String(), - }, - { - 'id': 'rbs', - 'name': 'RBS Alcohol', - 'icon': LucideIcons.wine, - 'color': const Color(0xFF121826), - 'description': 'Required for bar shifts', - 'status': 'NOT_STARTED', - 'expiry': null, - }, - ]; - - @override - Widget build(BuildContext context) { - final int completedCount = _certificates - .where((c) => c['status'] == 'COMPLETED') - .length; - final int totalCount = _certificates.length; - final int progress = (completedCount / totalCount * 100).round(); - - return Scaffold( - backgroundColor: const Color(0xFFF8FAFC), - body: SingleChildScrollView( - child: Column( - children: [ - _buildHeader(progress, completedCount, totalCount), - Transform.translate( - offset: const Offset(0, -48), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - children: [ - ..._certificates.map(_buildCertificateCard), - const SizedBox(height: 16), - _buildAddMoreCard(), - const SizedBox(height: 32), - ], - ), - ), - ), - ], - ), - ), - ); - } - - Widget _buildHeader(int progress, int completedCount, int totalCount) { - return Container( - padding: const EdgeInsets.fromLTRB(20, 60, 20, 80), - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [Color(0xFF0A39DF), Color(0xFF1E40AF)], - ), - ), - child: Column( - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.1), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.chevronLeft, - color: Colors.white, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - const Text( - 'Certificates', - style: TextStyle( - color: Colors.white, - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 32), - Row( - children: [ - SizedBox( - width: 96, - height: 96, - child: Stack( - fit: StackFit.expand, - children: [ - CircularProgressIndicator( - value: progress / 100, - strokeWidth: 8, - backgroundColor: Colors.white.withOpacity(0.2), - valueColor: const AlwaysStoppedAnimation( - Color(0xFFF9E547), - ), - ), - Center( - child: Text( - '$progress%', - style: const TextStyle( - color: Colors.white, - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - ), - const SizedBox(width: 24), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Your Progress', - style: TextStyle( - color: Colors.white, - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 4), - Text( - '$completedCount of $totalCount verified', - style: TextStyle( - color: Colors.white.withOpacity(0.7), - fontSize: 14, - ), - ), - const SizedBox(height: 8), - const Row( - children: [ - Icon( - LucideIcons.shield, - color: Color(0xFFF9E547), - size: 16, - ), - SizedBox(width: 8), - Text( - 'Compliance Active', - style: TextStyle( - color: Color(0xFFF9E547), - fontSize: 14, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ], - ), - ], - ), - ], - ), - ); - } - - Widget _buildCertificateCard(Map cert) { - final String status = cert['status']; - final bool isExpiring = status == 'EXPIRING'; - final bool isComplete = status == 'COMPLETED'; - final bool isPending = status == 'PENDING'; - final bool isNotStarted = status == 'NOT_STARTED'; - - DateTime? expiryDate; - if (cert['expiry'] != null) { - expiryDate = DateTime.parse(cert['expiry']); - } - - int daysUntilExpiry = 0; - if (expiryDate != null) { - daysUntilExpiry = expiryDate.difference(DateTime.now()).inDays; - } - - return Container( - margin: const EdgeInsets.only(bottom: 16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - clipBehavior: Clip.hardEdge, - child: Column( - children: [ - if (isExpiring) - Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - decoration: BoxDecoration( - color: const Color(0xFFF9E547).withOpacity(0.2), - border: const Border( - bottom: BorderSide(color: Color(0x66F9E547)), - ), - ), - child: Row( - children: [ - const Icon( - LucideIcons.alertTriangle, - size: 16, - color: Color(0xFF121826), - ), - const SizedBox(width: 8), - Text( - daysUntilExpiry > 0 - ? 'Expires in $daysUntilExpiry days - Renew now' - : 'Expired - Renew now', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - ), - ], - ), - ), - - Padding( - padding: const EdgeInsets.all(20), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Stack( - clipBehavior: Clip.none, - children: [ - Container( - width: 64, - height: 64, - decoration: BoxDecoration( - color: cert['color'].withOpacity(0.1), - borderRadius: BorderRadius.circular(16), - ), - child: Center( - child: Icon( - cert['icon'], - color: cert['color'], - size: 28, - ), - ), - ), - if (isComplete) - const Positioned( - bottom: -4, - right: -4, - child: CircleAvatar( - radius: 12, - backgroundColor: Color(0xFF0A39DF), - child: Icon( - LucideIcons.checkCircle, - color: Colors.white, - size: 16, - ), - ), - ), - if (isPending) - const Positioned( - bottom: -4, - right: -4, - child: CircleAvatar( - radius: 12, - backgroundColor: Color(0xFF121826), - child: Icon( - LucideIcons.clock, - color: Colors.white, - size: 16, - ), - ), - ), - ], - ), - const SizedBox(width: 16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - cert['name'], - style: const TextStyle( - fontWeight: FontWeight.w600, - fontSize: 16, - color: Color(0xFF121826), - ), - ), - const SizedBox(height: 2), - Text( - cert['description'], - style: const TextStyle( - fontSize: 12, - color: Color(0xFF6A7382), - ), - ), - ], - ), - const Icon( - LucideIcons.chevronRight, - color: Color(0xFF6A7382), - size: 20, - ), - ], - ), - const SizedBox(height: 16), - - if (isComplete) _buildCompleteStatus(expiryDate), - - if (isExpiring) _buildExpiringStatus(expiryDate), - - if (isNotStarted) - SizedBox( - width: double.infinity, - child: ElevatedButton( - onPressed: () => _showUploadModal(context, cert), - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0A39DF), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - padding: const EdgeInsets.symmetric(vertical: 12), - elevation: 0, - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - LucideIcons.upload, - size: 16, - color: Colors.white, - ), - SizedBox(width: 8), - Text( - 'Upload Certificate', - style: TextStyle( - fontWeight: FontWeight.w500, - color: Colors.white, - ), - ), - ], - ), - ), - ), - - // Edit and Remove buttons for completed/expiring certificates - if (isComplete || isExpiring) ...[ - const SizedBox(height: 12), - SizedBox( - width: double.infinity, - child: OutlinedButton.icon( - onPressed: () => _showEditExpiryDialog(cert), - icon: const Icon(LucideIcons.pencil, size: 16), - label: const Text('Edit Expiration Date'), - style: OutlinedButton.styleFrom( - foregroundColor: const Color(0xFF121826), - side: const BorderSide(color: Color(0xFFE3E6E9)), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - padding: const EdgeInsets.symmetric(vertical: 12), - ), - ), - ), - const SizedBox(height: 8), - SizedBox( - width: double.infinity, - child: TextButton.icon( - onPressed: () => _showRemoveConfirmation(cert), - icon: const Icon(LucideIcons.trash2, size: 16), - label: const Text('Remove Certificate'), - style: TextButton.styleFrom( - foregroundColor: Colors.red, - padding: const EdgeInsets.symmetric(vertical: 12), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - ), - ), - ], - ], - ), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildCompleteStatus(DateTime? expiryDate) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - width: 8, - height: 8, - decoration: const BoxDecoration( - color: Color(0xFF0A39DF), - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 8), - const Text( - 'Verified', - style: TextStyle( - fontWeight: FontWeight.w500, - color: Color(0xFF0A39DF), - fontSize: 14, - ), - ), - ], - ), - if (expiryDate != null) - Text( - 'Exp: ${DateFormat('MMM d, yyyy').format(expiryDate)}', - style: const TextStyle(fontSize: 12, color: Color(0xFF6A7382)), - ), - ], - ); - } - - Widget _buildExpiringStatus(DateTime? expiryDate) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Container( - width: 8, - height: 8, - decoration: const BoxDecoration( - color: Color(0xFF0A39DF), - shape: BoxShape.circle, - ), - ), // Assuming blinking not essential for MVP Flutter - const SizedBox(width: 8), - const Text( - 'Expiring Soon', - style: TextStyle( - fontWeight: FontWeight.w500, - color: Color(0xFF0A39DF), - fontSize: 14, - ), - ), - ], - ), - if (expiryDate != null) - Padding( - padding: const EdgeInsets.only(top: 4), - child: Text( - 'Exp: ${DateFormat('MMM d, yyyy').format(expiryDate)}', - style: const TextStyle( - fontSize: 12, - color: Color(0xFF6A7382), - ), - ), - ), - ], - ), - Row( - children: [ - _buildIconButton(LucideIcons.eye, () { - // Show snackbar indicating certificate opened - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Certificate opened in new tab'), - duration: Duration(seconds: 2), - ), - ); - }), - const SizedBox(width: 8), - _buildSmallOutlineButton( - 'Renew', - () => _showUploadModal(context, null), - ), // Passing null just to open generic upload for now or handle logic - ], - ), - ], - ); - } - - Widget _buildIconButton(IconData icon, VoidCallback onTap) { - return InkWell( - onTap: onTap, - borderRadius: BorderRadius.circular(16), - child: Container( - width: 32, - height: 32, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.transparent, - border: Border.all( - color: Colors.transparent, - ), // Placeholder for consistent sizing - ), - child: const Center( - child: Icon(LucideIcons.eye, size: 16, color: Color(0xFF6A7382)), - ), - ), - ); - } - - Widget _buildSmallOutlineButton(String label, VoidCallback onTap) { - return OutlinedButton( - onPressed: onTap, - style: OutlinedButton.styleFrom( - side: const BorderSide(color: Color(0x660A39DF)), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 0), - minimumSize: const Size(0, 32), - ), - child: Text( - label, - style: const TextStyle(fontSize: 12, color: Color(0xFF0A39DF)), - ), - ); - } - - Widget _buildAddMoreCard() { - return GestureDetector( - onTap: () => _showUploadModal(context, null), - child: Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [Colors.grey[50]!, Colors.grey[100]!], - ), - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: Colors.grey[300]!, - style: BorderStyle.solid, - ), // Dashed border needs custom painter, solid fine for MVP - ), - child: const Row( - children: [ - Icon(LucideIcons.plus, color: Color(0xFF0A39DF), size: 24), - SizedBox(width: 16), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Add Another Certificate', - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 16, - color: Color(0xFF121826), - ), - ), - SizedBox(height: 2), - Text( - 'Boost your profile with more credentials', - style: TextStyle(fontSize: 12, color: Color(0xFF6A7382)), - ), - ], - ), - ], - ), - ), - ); - } - - void _showUploadModal(BuildContext context, Map? cert) { - showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) => Container( - height: MediaQuery.of(context).size.height * 0.85, - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.vertical(top: Radius.circular(32)), - ), - child: Column( - children: [ - // Header - Container( - height: 128, - width: double.infinity, - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [Color(0xFF0A39DF), Color(0xFF1E40AF)], - ), - borderRadius: BorderRadius.vertical(top: Radius.circular(32)), - ), - child: Stack( - alignment: Alignment.center, - clipBehavior: Clip.none, - children: [ - Positioned( - top: 16, - right: 16, - child: IconButton( - icon: const Icon(LucideIcons.x, color: Colors.white), - onPressed: () => context.pop(), - ), - ), - Positioned( - bottom: -32, - child: Container( - width: 80, - height: 80, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 10, - ), - ], - ), - child: Center( - child: Icon( - cert != null ? cert['icon'] : LucideIcons.fileCheck, - size: 40, - color: const Color(0xFF0A39DF), - ), - ), - ), - ), - ], - ), - ), - const SizedBox(height: 48), - Text( - cert != null ? cert['name'] : 'New Certificate', - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF121826), - ), - ), - const SizedBox(height: 24), - // Upload Options - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Row( - children: [ - Expanded( - child: _buildUploadOption(LucideIcons.camera, 'Take Photo'), - ), - const SizedBox(width: 16), - Expanded( - child: _buildUploadOption( - LucideIcons.upload, - 'Upload File', - ), - ), - ], - ), - ), - const SizedBox(height: 16), - const Text( - 'Supported formats: PDF, JPG, PNG (max 10MB)', - style: TextStyle(fontSize: 12, color: Color(0xFF6A7382)), - ), - ], - ), - ), - ); - } - - Widget _buildUploadOption(IconData icon, String label) { - return Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: const Color(0xFFF8FAFC), - borderRadius: BorderRadius.circular(16), - ), - child: Column( - children: [ - Container( - width: 56, - height: 56, - decoration: const BoxDecoration( - color: Colors.white, - shape: BoxShape.circle, - ), - child: Center(child: Icon(icon, color: const Color(0xFF0A39DF))), - ), - const SizedBox(height: 12), - Text( - label, - style: const TextStyle( - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - ), - ], - ), - ); - } - - // Edit Expiry Date Dialog - Future _showEditExpiryDialog(Map cert) async { - DateTime? currentExpiry; - if (cert['expiry'] != null) { - currentExpiry = DateTime.parse(cert['expiry']); - } - - DateTime selectedDate = currentExpiry ?? DateTime.now(); - - await showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Row( - children: [ - Icon(LucideIcons.calendar, size: 20, color: AppColors.krowBlue), - const SizedBox(width: 8), - const Text( - 'Update Expiration Date', - style: TextStyle(fontSize: 18), - ), - ], - ), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Expiration Date', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - ), - const SizedBox(height: 12), - InkWell( - onTap: () async { - final DateTime? picked = await showDatePicker( - context: context, - initialDate: selectedDate, - firstDate: DateTime.now(), - lastDate: DateTime.now().add(const Duration(days: 3650)), - ); - if (picked != null) { - selectedDate = picked; - } - }, - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - border: Border.all(color: const Color(0xFFE3E6E9)), - borderRadius: BorderRadius.circular(12), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - DateFormat('MMM d, yyyy').format(selectedDate), - style: const TextStyle(fontSize: 16), - ), - const Icon(LucideIcons.calendar, size: 20), - ], - ), - ), - ), - ], - ), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: const Text('Cancel'), - ), - ElevatedButton( - onPressed: () { - // Update the certificate expiry date - setState(() { - final index = _certificates.indexWhere( - (c) => c['id'] == cert['id'], - ); - if (index != -1) { - _certificates[index]['expiry'] = selectedDate - .toIso8601String(); - // Update status based on new expiry - final daysUntilExpiry = selectedDate - .difference(DateTime.now()) - .inDays; - if (daysUntilExpiry <= 30) { - _certificates[index]['status'] = 'EXPIRING'; - } else { - _certificates[index]['status'] = 'COMPLETED'; - } - } - }); - Navigator.of(context).pop(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Expiration date updated successfully'), - backgroundColor: Colors.green, - ), - ); - }, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - ), - child: const Text('Save'), - ), - ], - ); - }, - ); - } - - // Remove Certificate Confirmation Dialog - Future _showRemoveConfirmation(Map cert) async { - final bool? confirmed = await showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('Remove Certificate'), - content: Text( - 'Are you sure you want to remove "${cert['name']}"? This action cannot be undone.', - ), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(false), - child: const Text('Cancel'), - ), - ElevatedButton( - onPressed: () => Navigator.of(context).pop(true), - style: ElevatedButton.styleFrom( - backgroundColor: Colors.red, - foregroundColor: Colors.white, - ), - child: const Text('Remove'), - ), - ], - ); - }, - ); - - if (confirmed == true) { - setState(() { - _certificates.removeWhere((c) => c['id'] == cert['id']); - }); - if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('${cert['name']} removed successfully'), - backgroundColor: Colors.red, - ), - ); - } - } - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/documents_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/documents_screen.dart deleted file mode 100644 index 7f31eeb2..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/documents_screen.dart +++ /dev/null @@ -1,296 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import '../../../../theme.dart'; - -class DocumentsScreen extends ConsumerStatefulWidget { - const DocumentsScreen({super.key}); - - @override - ConsumerState createState() => _DocumentsScreenState(); -} - -class _DocumentsScreenState extends ConsumerState { - // Mock Data - final List> _requiredDocs = [ - { - 'userId': 'id', - 'name': 'Government ID', - 'description': 'Passport, Driver\'s License, or State ID', - 'status': 'VERIFIED', - }, - { - 'userId': 'ssn', - 'name': 'Social Security Card', - 'description': 'Or W-9 Form', - 'status': 'PENDING', - }, - { - 'userId': 'work_auth', - 'name': 'Work Authorization', - 'description': 'I-9 or Work Permit', - 'status': 'VERIFIED', - }, - { - 'userId': 'address', - 'name': 'Proof of Address', - 'description': 'Utility bill or bank statement', - 'status': 'MISSING', - }, - ]; - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFFAFBFC), - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.chevronLeft, color: Color(0xFF6A7382)), - onPressed: () => context.pop(), - ), - title: const Text( - 'Documents', - style: TextStyle( - color: Color(0xFF121826), - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1.0), - child: Container(color: const Color(0xFFE3E6E9), height: 1.0), - ), - ), - body: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 24), - child: Column( - children: [ - _buildProgressCard(), - const SizedBox(height: 16), - _buildDocumentsList(), - ], - ), - ), - ); - } - - Widget _buildProgressCard() { - final completedCount = _requiredDocs - .where((d) => d['status'] == 'VERIFIED') - .length; - final totalCount = _requiredDocs.length; - final progress = totalCount > 0 ? completedCount / totalCount : 0.0; - - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Document Verification', - style: TextStyle( - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - ), - Text( - '$completedCount/$totalCount Complete', - style: const TextStyle(fontSize: 14, color: Color(0xFF0A39DF)), - ), - ], - ), - const SizedBox(height: 8), - ClipRRect( - borderRadius: BorderRadius.circular(4), - child: LinearProgressIndicator( - value: progress, - minHeight: 8, - backgroundColor: const Color(0xFFE3E6E9), - valueColor: const AlwaysStoppedAnimation( - Color(0xFF0A39DF), - ), - ), - ), - ], - ), - ); - } - - Widget _buildDocumentsList() { - return Column( - children: _requiredDocs.map((doc) => _buildDocumentCard(doc)).toList(), - ); - } - - Widget _buildDocumentCard(Map doc) { - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: const Color(0xFF0A39DF).withOpacity(0.1), - borderRadius: BorderRadius.circular(8), - ), - child: const Center( - child: Icon( - LucideIcons.fileText, - color: Color(0xFF0A39DF), - size: 20, - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - doc['name'], - style: const TextStyle( - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - ), - _getStatusIcon(doc['status']), - ], - ), - const SizedBox(height: 2), - Text( - doc['description'], - style: const TextStyle( - fontSize: 14, - color: Color(0xFF6A7382), - ), - ), - const SizedBox(height: 12), - Row( - children: [ - _buildStatusBadge(doc['status']), - const SizedBox(width: 8), - _buildActionButton(doc['status']), - ], - ), - ], - ), - ), - ], - ), - ); - } - - Widget _getStatusIcon(String status) { - switch (status) { - case 'VERIFIED': - return const Icon( - LucideIcons.checkCircle, - color: Color(0xFF22C55E), - size: 20, - ); - case 'PENDING': - return const Icon( - LucideIcons.clock, - color: Color(0xFFF59E0B), - size: 20, - ); - default: - return const Icon( - LucideIcons.alertCircle, - color: Color(0xFFEF4444), - size: 20, - ); - } - } - - Widget _buildStatusBadge(String status) { - Color bg; - Color text; - String label = status; - - switch (status) { - case 'verified': - bg = const Color(0xFF10B981).withOpacity(0.2); - text = const Color(0xFF10B981); - break; - case 'PENDING': - bg = const Color(0xFFF59200).withOpacity(0.2); - text = const Color(0xFFF59200); - break; - case 'MISSING': - default: - bg = const Color(0xFFEF4444).withOpacity(0.2); - text = const Color(0xFFEF4444); - break; - } - - // Capitalize label - label = label[0].toUpperCase() + label.substring(1); - - return Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), - decoration: BoxDecoration( - color: bg, - borderRadius: BorderRadius.circular(12), - ), - child: Text( - label, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: text, - ), - ), - ); - } - - Widget _buildActionButton(String status) { - final bool isVerified = status == 'VERIFIED'; - return InkWell( - onTap: () {}, - borderRadius: BorderRadius.circular(4), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - child: Row( - children: [ - Icon( - isVerified ? LucideIcons.eye : LucideIcons.upload, - size: 16, - color: const Color(0xFF0A39DF), - ), - const SizedBox(width: 4), - Text( - isVerified ? 'View' : 'Upload', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF0A39DF), - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/tax_forms_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/tax_forms_screen.dart deleted file mode 100644 index c1560544..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/tax_forms_screen.dart +++ /dev/null @@ -1,327 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import '../../../../theme.dart'; -import 'taxforms/form_i9_screen.dart'; -import 'taxforms/form_w4_screen.dart'; - -class TaxFormsScreen extends ConsumerStatefulWidget { - const TaxFormsScreen({super.key}); - - @override - ConsumerState createState() => _TaxFormsScreenState(); -} - -class _TaxFormsScreenState extends ConsumerState { - // Mock Data - final List> _taxForm = [ - { - 'formType': 'I9', - 'title': 'Form I-9', - 'subtitle': 'Employment Eligibility Verification', - 'description': 'Required to verify your identity and work authorization', - 'status': 'SUBMITTED', - 'icon': - '🛂', // Using text emoji as placeholder for custom icon or just use Lucide icon - }, - { - 'formType': 'W4', - 'title': 'Form W-4', - 'subtitle': 'Employee\'s Withholding Certificate', - 'description': 'Set up your federal tax withholding', - 'status': 'NOT_STARTED', - 'icon': '📋', - }, - ]; - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFFAFBFC), - appBar: AppBar( - backgroundColor: const Color(0xFF0A39DF), - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.arrowLeft, color: Colors.white), - onPressed: () => context.pop(), - ), - title: const Text( - 'Tax Documents', - style: TextStyle( - color: Colors.white, - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - bottom: const PreferredSize( - preferredSize: Size.fromHeight(24), - child: Padding( - padding: EdgeInsets.only(left: 20, right: 20, bottom: 20), - child: Row( - children: [ - Expanded( - child: Text( - 'Complete required forms to start working', - style: TextStyle( - color: Color(0xCCFFFFFF), // white with opacity - fontSize: 14, - ), - ), - ), - ], - ), - ), - ), - ), - body: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 24), - child: Column( - children: [ - _buildProgressOverview(), - const SizedBox(height: 24), - ..._taxForm.map(_buildFormCard), - const SizedBox(height: 24), - _buildInfoCard(), - ], - ), - ), - ); - } - - Widget _buildProgressOverview() { - final completedCount = _taxForm - .where((f) => f['status'] == 'SUBMITTED' || f['status'] == 'APPROVED') - .length; - final totalCount = _taxForm.length; - final progress = totalCount > 0 ? completedCount / totalCount : 0.0; - - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Document Progress', - style: TextStyle( - fontWeight: FontWeight.w500, - fontSize: 14, - color: Color(0xFF121826), - ), - ), - Text( - '$completedCount/$totalCount', - style: const TextStyle(fontSize: 14, color: Color(0xFF6A7382)), - ), - ], - ), - const SizedBox(height: 12), - ClipRRect( - borderRadius: BorderRadius.circular(4), - child: LinearProgressIndicator( - value: progress, - minHeight: 8, - backgroundColor: const Color(0xFFF3F4F6), - valueColor: const AlwaysStoppedAnimation( - Color(0xFF0A39DF), - ), - ), - ), - ], - ), - ); - } - - Widget _buildFormCard(Map form) { - return GestureDetector( - onTap: () { - if (form['formType'] == 'I9') { - context.push('/taxforms/i9'); - } else if (form['formType'] == 'W4') { - context.push('/taxforms/w4'); - } - }, - child: Container( - margin: const EdgeInsets.only(bottom: 16), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 48, - height: 48, - decoration: BoxDecoration( - color: const Color(0xFF0A39DF).withOpacity(0.1), - borderRadius: BorderRadius.circular(12), - ), - child: Center( - child: Text(form['icon'], style: const TextStyle(fontSize: 24)), - ), - ), - const SizedBox(width: 16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - form['title'], - style: const TextStyle( - fontWeight: FontWeight.w600, - fontSize: 16, - color: Color(0xFF121826), - ), - ), - _buildStatusBadge(form['status']), - ], - ), - const SizedBox(height: 4), - Text( - form['subtitle'], - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF6A7382), - ), - ), - const SizedBox(height: 4), - Text( - form['description'], - style: const TextStyle( - fontSize: 12, - color: Color(0xFF6A7382), - ), - ), - ], - ), - ), - const SizedBox(width: 8), - const Icon( - LucideIcons.chevronRight, - color: Color(0xFF6A7382), - size: 20, - ), - ], - ), - ), - ); - } - - Widget _buildStatusBadge(String status) { - switch (status) { - case 'SUBMITTED': - case 'APPROVED': - return Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: const Color(0xFFF0FDF4), - borderRadius: BorderRadius.circular(12), - ), - child: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(LucideIcons.checkCircle, size: 12, color: Color(0xFF16A34A)), - SizedBox(width: 4), - Text( - 'Completed', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF16A34A), - ), - ), - ], - ), - ); - case 'DRAFT': - return Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: const Color(0xFFFFFBEB), - borderRadius: BorderRadius.circular(12), - ), - child: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(LucideIcons.clock, size: 12, color: Color(0xFFD97706)), - SizedBox(width: 4), - Text( - 'In Progress', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFFD97706), - ), - ), - ], - ), - ); - default: - return Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: const Color(0xFFF3F4F6), - borderRadius: BorderRadius.circular(12), - ), - child: const Text( - 'Not Started', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF6B7280), - ), - ), - ); - } - } - - Widget _buildInfoCard() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFFEFF6FF), - borderRadius: BorderRadius.circular(16), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Icon(LucideIcons.fileText, color: Color(0xFF2563EB), size: 20), - const SizedBox(width: 12), - const Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Why are these needed?', - style: TextStyle( - fontWeight: FontWeight.w500, - color: Color(0xFF1E3A8A), - ), - ), - SizedBox(height: 4), - Text( - 'I-9 and W-4 forms are required by federal law to verify your employment eligibility and set up correct tax withholding.', - style: TextStyle(fontSize: 14, color: Color(0xFF1D4ED8)), - ), - ], - ), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/taxforms/form_i9_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/taxforms/form_i9_screen.dart deleted file mode 100644 index d1a6dac8..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/taxforms/form_i9_screen.dart +++ /dev/null @@ -1,905 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../../../../theme.dart'; - -class FormI9Screen extends StatefulWidget { - const FormI9Screen({super.key}); - - @override - State createState() => _FormI9ScreenState(); -} - -class _FormI9ScreenState extends State { - int _currentStep = 0; - bool _isSubmitting = false; - bool _isSuccess = false; - - final Map _formData = { - 'lastName': '', - 'firstName': '', - 'middleInitial': '', - 'otherLastNames': '', - 'address': '', - 'aptNumber': '', - 'city': '', - 'state': null, - 'zipCode': '', - 'dateOfBirth': '', - 'ssn': '', - 'email': '', - 'phone': '', - 'citizenshipStatus': '', - 'uscisNumber': '', - 'i94Number': '', - 'foreignPassportNumber': '', - 'countryOfIssuance': '', - 'expirationDate': '', - }; - - String _signature = ''; - - final List _usStates = [ - 'AL', - 'AK', - 'AZ', - 'AR', - 'CA', - 'CO', - 'CT', - 'DE', - 'FL', - 'GA', - 'HI', - 'ID', - 'IL', - 'IN', - 'IA', - 'KS', - 'KY', - 'LA', - 'ME', - 'MD', - 'MA', - 'MI', - 'MN', - 'MS', - 'MO', - 'MT', - 'NE', - 'NV', - 'NH', - 'NJ', - 'NM', - 'NY', - 'NC', - 'ND', - 'OH', - 'OK', - 'OR', - 'PA', - 'RI', - 'SC', - 'SD', - 'TN', - 'TX', - 'UT', - 'VT', - 'VA', - 'WA', - 'WV', - 'WI', - 'WY', - ]; - - final List> _steps = [ - {'title': 'Personal Information', 'subtitle': 'Name and contact details'}, - {'title': 'Address', 'subtitle': 'Your current address'}, - { - 'title': 'Citizenship Status', - 'subtitle': 'Work authorization verification', - }, - {'title': 'Review & Sign', 'subtitle': 'Confirm your information'}, - ]; - - void _updateField(String key, dynamic value) { - setState(() { - _formData[key] = value; - }); - } - - bool _canProceed() { - switch (_currentStep) { - case 0: - return _formData['lastName'].trim().isNotEmpty && - _formData['firstName'].trim().isNotEmpty && - _formData['dateOfBirth'].isNotEmpty && - _formData['ssn'].replaceAll(RegExp(r'\D'), '').length >= 4; - case 1: - return _formData['address'].trim().isNotEmpty && - _formData['city'].trim().isNotEmpty && - _formData['state'] != null && - _formData['zipCode'].length >= 5; - case 2: - return _formData['citizenshipStatus'].isNotEmpty; - case 3: - return _signature.trim().isNotEmpty; - default: - return true; - } - } - - void _handleNext() { - if (_currentStep < _steps.length - 1) { - setState(() => _currentStep++); - } else { - _submitForm(); - } - } - - void _handleBack() { - if (_currentStep > 0) { - setState(() => _currentStep--); - } - } - - Future _submitForm() async { - setState(() => _isSubmitting = true); - // Mock API call - await Future.delayed(const Duration(seconds: 2)); - if (mounted) { - setState(() { - _isSubmitting = false; - _isSuccess = true; - }); - } - } - - @override - Widget build(BuildContext context) { - if (_isSuccess) return _buildSuccessView(); - - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: Column( - children: [ - _buildHeader(), - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 24), - child: _buildCurrentStep(), - ), - ), - _buildFooter(), - ], - ), - ); - } - - Widget _buildSuccessView() { - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: Center( - child: Padding( - padding: const EdgeInsets.all(24.0), - child: Container( - padding: const EdgeInsets.all(32), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(24), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 64, - height: 64, - decoration: BoxDecoration( - color: const Color(0xFFDCFCE7), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.check, - color: Color(0xFF16A34A), - size: 32, - ), - ), - const SizedBox(height: 16), - const Text( - 'Form I-9 Submitted!', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - const Text( - 'Your form has been successfully submitted. Your employer will complete Section 2.', - textAlign: TextAlign.center, - style: TextStyle(color: AppColors.krowMuted), - ), - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - child: ElevatedButton( - onPressed: () => context.pop(), - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - padding: const EdgeInsets.symmetric(vertical: 16), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: const Text('Back to Documents'), - ), - ), - ], - ), - ), - ), - ), - ); - } - - Widget _buildHeader() { - return Container( - color: AppColors.krowBlue, - padding: const EdgeInsets.only(top: 60, bottom: 24, left: 20, right: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 24, - ), - ), - const SizedBox(width: 12), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Form I-9', - style: TextStyle( - color: Colors.white, - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - Text( - 'Employment Eligibility Verification', - style: TextStyle(color: Colors.white70, fontSize: 12), - ), - ], - ), - ], - ), - const SizedBox(height: 24), - Row( - children: _steps.asMap().entries.map((entry) { - final idx = entry.key; - final isLast = idx == _steps.length - 1; - return Expanded( - child: Row( - children: [ - Expanded( - child: Container( - height: 4, - decoration: BoxDecoration( - color: idx <= _currentStep - ? Colors.white - : Colors.white.withOpacity(0.3), - borderRadius: BorderRadius.circular(2), - ), - ), - ), - if (!isLast) const SizedBox(width: 4), - ], - ), - ); - }).toList(), - ), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Step ${_currentStep + 1} of ${_steps.length}', - style: const TextStyle(color: Colors.white70, fontSize: 12), - ), - Text( - _steps[_currentStep]['title']!, - style: const TextStyle( - color: Colors.white, - fontSize: 12, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ], - ), - ); - } - - Widget _buildCurrentStep() { - switch (_currentStep) { - case 0: - return _buildStep1(); - case 1: - return _buildStep2(); - case 2: - return _buildStep3(); - case 3: - return _buildStep4(); - default: - return Container(); - } - } - - Widget _buildTextField( - String label, - String key, { - TextInputType? keyboardType, - String? placeholder, - Function(String)? onChanged, - int? maxLength, - }) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - label, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - fontWeight: FontWeight.w500, - ), - ), - const SizedBox(height: 6), - TextField( - controller: TextEditingController(text: _formData[key]) - ..selection = TextSelection.fromPosition( - TextPosition(offset: (_formData[key] as String).length), - ), - onChanged: onChanged ?? (val) => _updateField(key, val), - keyboardType: keyboardType, - maxLength: maxLength, - decoration: InputDecoration( - hintText: placeholder, - hintStyle: TextStyle(color: Colors.grey[400]), - filled: true, - fillColor: Colors.white, - counterText: "", - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBorder), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBorder), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBlue), - ), - ), - ), - ], - ); - } - - Widget _buildDropdown(String label, String key, List items) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - label, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - fontWeight: FontWeight.w500, - ), - ), - const SizedBox(height: 6), - Container( - padding: const EdgeInsets.symmetric(horizontal: 16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: DropdownButtonHideUnderline( - child: DropdownButton( - value: _formData[key], - isExpanded: true, - hint: const Text('Select', style: TextStyle(color: Colors.grey)), - icon: const Icon( - LucideIcons.chevronDown, - size: 16, - color: AppColors.krowMuted, - ), - onChanged: (val) => _updateField(key, val), - items: items - .map( - (item) => DropdownMenuItem(value: item, child: Text(item)), - ) - .toList(), - ), - ), - ), - ], - ); - } - - Widget _buildStep1() { - return Column( - children: [ - Row( - children: [ - Expanded( - child: _buildTextField( - 'Last Name *', - 'lastName', - placeholder: 'Smith', - ), - ), - const SizedBox(width: 12), - Expanded( - child: _buildTextField( - 'First Name *', - 'firstName', - placeholder: 'John', - ), - ), - ], - ), - const SizedBox(height: 16), - Row( - children: [ - Expanded( - child: _buildTextField( - 'Middle Initial', - 'middleInitial', - placeholder: 'A', - maxLength: 1, - ), - ), - const SizedBox(width: 12), - Expanded( - child: _buildTextField( - 'Other Last Names', - 'otherLastNames', - placeholder: 'If any', - ), - ), - ], - ), - const SizedBox(height: 16), - _buildTextField( - 'Date of Birth *', - 'dateOfBirth', - placeholder: 'YYYY-MM-DD', - keyboardType: TextInputType.datetime, - ), // Ideally use date picker - const SizedBox(height: 16), - _buildTextField( - 'Social Security Number *', - 'ssn', - placeholder: 'XXX-XX-XXXX', - keyboardType: TextInputType.number, - onChanged: (val) { - // Simple masking logic - String text = val.replaceAll(RegExp(r'\D'), ''); - if (text.length > 9) text = text.substring(0, 9); - // Add formatting if needed - _updateField('ssn', text); - }, - ), - const SizedBox(height: 16), - _buildTextField( - 'Email Address', - 'email', - placeholder: 'john@example.com', - keyboardType: TextInputType.emailAddress, - ), - const SizedBox(height: 16), - _buildTextField( - 'Phone Number', - 'phone', - placeholder: '(555) 123-4567', - keyboardType: TextInputType.phone, - ), - ], - ); - } - - Widget _buildStep2() { - return Column( - children: [ - _buildTextField( - 'Street Address *', - 'address', - placeholder: '123 Main Street', - ), - const SizedBox(height: 16), - _buildTextField('Apt. Number', 'aptNumber', placeholder: 'If any'), - const SizedBox(height: 16), - _buildTextField('City *', 'city', placeholder: 'San Francisco'), - const SizedBox(height: 16), - Row( - children: [ - Expanded(child: _buildDropdown('State *', 'state', _usStates)), - const SizedBox(width: 12), - Expanded( - child: _buildTextField( - 'ZIP Code *', - 'zipCode', - placeholder: '94102', - keyboardType: TextInputType.number, - maxLength: 5, - ), - ), - ], - ), - ], - ); - } - - Widget _buildStep3() { - return Column( - children: [ - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.blue[50], - borderRadius: BorderRadius.circular(12), - ), - child: Row( - children: [ - const Icon(LucideIcons.info, color: Color(0xFF2563EB), size: 20), - const SizedBox(width: 12), - const Expanded( - child: Text( - 'Select the option that describes your citizenship or immigration status.', - style: TextStyle(fontSize: 14, color: Color(0xFF1D4ED8)), - ), - ), - ], - ), - ), - const SizedBox(height: 24), - _buildRadioOption('citizen', 'A citizen of the United States'), - const SizedBox(height: 12), - _buildRadioOption( - 'noncitizen_national', - 'A noncitizen national of the United States', - ), - const SizedBox(height: 12), - _buildRadioOption('permanent_resident', 'A lawful permanent resident'), - const SizedBox(height: 12), - _buildRadioOption('authorized_alien', 'An alien authorized to work'), - - if (_formData['citizenshipStatus'] == 'permanent_resident' || - _formData['citizenshipStatus'] == 'authorized_alien') - Padding( - padding: const EdgeInsets.only(top: 24), - child: Column( - children: [ - _buildTextField( - 'USCIS/A-Number', - 'uscisNumber', - placeholder: 'A-123456789', - ), - if (_formData['citizenshipStatus'] == 'authorized_alien') ...[ - const SizedBox(height: 16), - _buildTextField( - 'Expiration Date', - 'expirationDate', - placeholder: 'YYYY-MM-DD', - ), - ], - ], - ), - ), - ], - ); - } - - Widget _buildRadioOption(String value, String label) { - final isSelected = _formData['citizenshipStatus'] == value; - return GestureDetector( - onTap: () => _updateField('citizenshipStatus', value), - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: isSelected ? AppColors.krowBlue : AppColors.krowBorder, - width: isSelected ? 2 : 1, - ), - ), - child: Row( - children: [ - Container( - width: 20, - height: 20, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: isSelected ? AppColors.krowBlue : Colors.grey, - width: isSelected ? 6 : 2, - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: Text( - label, - style: const TextStyle( - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - ), - ], - ), - ), - ); - } - - Widget _buildStep4() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Information Summary', - style: TextStyle(fontWeight: FontWeight.w600, fontSize: 14), - ), - const SizedBox(height: 12), - _buildSummaryRow( - 'Name', - '${_formData['firstName']} ${_formData['lastName']}', - ), - _buildSummaryRow( - 'SSN', - '***-**-${_formData['ssn'].length >= 4 ? _formData['ssn'].substring(_formData['ssn'].length - 4) : '****'}', - ), - _buildSummaryRow( - 'Address', - '${_formData['city']}, ${_formData['state']}', - ), - _buildSummaryRow( - 'Status', - _getStatusLabel(_formData['citizenshipStatus']), - ), - ], - ), - ), - const SizedBox(height: 24), - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFFFFFBEB), - borderRadius: BorderRadius.circular(12), - ), - child: const Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon(LucideIcons.alertCircle, color: Color(0xFFD97706), size: 20), - SizedBox(width: 12), - Expanded( - child: Text( - 'I am aware that federal law provides for imprisonment and/or fines for false statements or the use of false documents in connection with the completion of this form.', - style: TextStyle(fontSize: 12, color: Color(0xFFB45309)), - ), - ), - ], - ), - ), - const SizedBox(height: 24), - const Text( - 'Signature (type your full name) *', - style: TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - fontWeight: FontWeight.w500, - ), - ), - const SizedBox(height: 6), - TextField( - onChanged: (val) => setState(() => _signature = val), - decoration: InputDecoration( - hintText: 'Type your full name', - filled: true, - fillColor: Colors.white, - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBorder), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBorder), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBlue), - ), - ), - style: const TextStyle( - fontFamily: 'Cursive', - fontSize: 18, - ), // Fallback font if Cursive not available - ), - const SizedBox(height: 16), - const Text( - 'Today\'s Date', - style: TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - fontWeight: FontWeight.w500, - ), - ), - const SizedBox(height: 6), - Container( - width: double.infinity, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), - decoration: BoxDecoration( - color: const Color(0xFFF3F4F6), - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: Text( - DateTime.now().toString().split(' ')[0], - style: const TextStyle(color: AppColors.krowCharcoal), - ), - ), - ], - ); - } - - Widget _buildSummaryRow(String label, String value) { - return Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - label, - style: const TextStyle(color: AppColors.krowMuted, fontSize: 14), - ), - Text( - value, - style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 14), - ), - ], - ), - ); - } - - String _getStatusLabel(String status) { - switch (status) { - case 'citizen': - return 'U.S. Citizen'; - case 'noncitizen_national': - return 'Noncitizen National'; - case 'permanent_resident': - return 'Permanent Resident'; - case 'authorized_alien': - return 'Authorized to Work'; - default: - return status; - } - } - - Widget _buildFooter() { - return Container( - padding: const EdgeInsets.all(16), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: AppColors.krowBorder)), - ), - child: SafeArea( - child: Row( - children: [ - if (_currentStep > 0) - Expanded( - child: Padding( - padding: const EdgeInsets.only(right: 12), - child: OutlinedButton( - onPressed: _handleBack, - style: OutlinedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 16), - side: const BorderSide(color: AppColors.krowBorder), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(LucideIcons.arrowLeft, size: 16), - SizedBox(width: 8), - Text( - 'Back', - style: TextStyle(color: AppColors.krowCharcoal), - ), - ], - ), - ), - ), - ), - Expanded( - flex: 2, - child: ElevatedButton( - onPressed: (_canProceed() && !_isSubmitting) - ? _handleNext - : null, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - disabledBackgroundColor: Colors.grey[300], - foregroundColor: Colors.white, - padding: const EdgeInsets.symmetric(vertical: 16), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: _isSubmitting - ? const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - color: Colors.white, - strokeWidth: 2, - ), - ) - : Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - _currentStep == _steps.length - 1 - ? 'Submit Form' - : 'Continue', - ), - if (_currentStep < _steps.length - 1) ...[ - const SizedBox(width: 8), - const Icon(LucideIcons.arrowRight, size: 16), - ], - ], - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/taxforms/form_w4_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/taxforms/form_w4_screen.dart deleted file mode 100644 index 3fdcc57b..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/compliance/taxforms/form_w4_screen.dart +++ /dev/null @@ -1,1056 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../../../../theme.dart'; - -class FormW4Screen extends StatefulWidget { - const FormW4Screen({super.key}); - - @override - State createState() => _FormW4ScreenState(); -} - -class _FormW4ScreenState extends State { - int _currentStep = 0; - bool _isSubmitting = false; - bool _isSuccess = false; - - final Map _formData = { - 'firstName': '', - 'lastName': '', - 'address': '', - 'cityStateZip': '', - 'ssn': '', - 'filingStatus': '', - 'multipleJobs': false, - 'qualifyingChildren': 0, - 'otherDependents': 0, - 'otherIncome': '', - 'deductions': '', - 'extraWithholding': '', - }; - - String _signature = ''; - - final List> _steps = [ - {'title': 'Personal Information', 'subtitle': 'Step 1'}, - {'title': 'Filing Status', 'subtitle': 'Step 1c'}, - {'title': 'Multiple Jobs', 'subtitle': 'Step 2 (optional)'}, - {'title': 'Dependents', 'subtitle': 'Step 3'}, - {'title': 'Other Adjustments', 'subtitle': 'Step 4 (optional)'}, - {'title': 'Review & Sign', 'subtitle': 'Step 5'}, - ]; - - void _updateField(String key, dynamic value) { - setState(() { - _formData[key] = value; - }); - } - - bool _canProceed() { - switch (_currentStep) { - case 0: - return _formData['firstName'].trim().isNotEmpty && - _formData['lastName'].trim().isNotEmpty && - _formData['ssn'].replaceAll(RegExp(r'\D'), '').length >= 4 && - _formData['address'].trim().isNotEmpty; - case 1: - return _formData['filingStatus'].isNotEmpty; - case 5: - return _signature.trim().isNotEmpty; - default: - return true; - } - } - - void _handleNext() { - if (_currentStep < _steps.length - 1) { - setState(() => _currentStep++); - } else { - _submitForm(); - } - } - - void _handleBack() { - if (_currentStep > 0) { - setState(() => _currentStep--); - } - } - - Future _submitForm() async { - setState(() => _isSubmitting = true); - // Mock API call - await Future.delayed(const Duration(seconds: 2)); - if (mounted) { - setState(() { - _isSubmitting = false; - _isSuccess = true; - }); - } - } - - int get _totalCredits { - return (_formData['qualifyingChildren'] as int) * 2000 + - (_formData['otherDependents'] as int) * 500; - } - - @override - Widget build(BuildContext context) { - if (_isSuccess) return _buildSuccessView(); - - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: Column( - children: [ - _buildHeader(), - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 24), - child: _buildCurrentStep(), - ), - ), - _buildFooter(), - ], - ), - ); - } - - Widget _buildSuccessView() { - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: Center( - child: Padding( - padding: const EdgeInsets.all(24.0), - child: Container( - padding: const EdgeInsets.all(32), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(24), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 64, - height: 64, - decoration: BoxDecoration( - color: const Color(0xFFDCFCE7), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.check, - color: Color(0xFF16A34A), - size: 32, - ), - ), - const SizedBox(height: 16), - const Text( - 'Form W-4 Submitted!', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - const Text( - 'Your withholding certificate has been submitted to your employer.', - textAlign: TextAlign.center, - style: TextStyle(color: AppColors.krowMuted), - ), - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - child: ElevatedButton( - onPressed: () => context.pop(), - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - padding: const EdgeInsets.symmetric(vertical: 16), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: const Text('Back to Documents'), - ), - ), - ], - ), - ), - ), - ), - ); - } - - Widget _buildHeader() { - return Container( - color: AppColors.krowBlue, - padding: const EdgeInsets.only(top: 60, bottom: 24, left: 20, right: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 24, - ), - ), - const SizedBox(width: 12), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Form W-4', - style: TextStyle( - color: Colors.white, - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - Text( - 'Employee\'s Withholding Certificate', - style: TextStyle(color: Colors.white70, fontSize: 12), - ), - ], - ), - ], - ), - const SizedBox(height: 24), - Row( - children: _steps.asMap().entries.map((entry) { - final idx = entry.key; - final isLast = idx == _steps.length - 1; - return Expanded( - child: Row( - children: [ - Expanded( - child: Container( - height: 4, - decoration: BoxDecoration( - color: idx <= _currentStep - ? Colors.white - : Colors.white.withOpacity(0.3), - borderRadius: BorderRadius.circular(2), - ), - ), - ), - if (!isLast) const SizedBox(width: 4), - ], - ), - ); - }).toList(), - ), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Step ${_currentStep + 1} of ${_steps.length}', - style: const TextStyle(color: Colors.white70, fontSize: 12), - ), - Text( - _steps[_currentStep]['title']!, - style: const TextStyle( - color: Colors.white, - fontSize: 12, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ], - ), - ); - } - - Widget _buildCurrentStep() { - switch (_currentStep) { - case 0: - return _buildStep1(); - case 1: - return _buildStep2(); - case 2: - return _buildStep3(); - case 3: - return _buildStep4(); - case 4: - return _buildStep5(); - case 5: - return _buildStep6(); - default: - return Container(); - } - } - - Widget _buildTextField( - String label, - String key, { - TextInputType? keyboardType, - String? placeholder, - Function(String)? onChanged, - }) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - label, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - fontWeight: FontWeight.w500, - ), - ), - const SizedBox(height: 6), - TextField( - controller: TextEditingController(text: _formData[key].toString()) - ..selection = TextSelection.fromPosition( - TextPosition(offset: (_formData[key].toString()).length), - ), - onChanged: onChanged ?? (val) => _updateField(key, val), - keyboardType: keyboardType, - decoration: InputDecoration( - hintText: placeholder, - hintStyle: TextStyle(color: Colors.grey[400]), - filled: true, - fillColor: Colors.white, - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBorder), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBorder), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBlue), - ), - ), - ), - ], - ); - } - - Widget _buildStep1() { - return Column( - children: [ - Row( - children: [ - Expanded( - child: _buildTextField( - 'First Name *', - 'firstName', - placeholder: 'John', - ), - ), - const SizedBox(width: 12), - Expanded( - child: _buildTextField( - 'Last Name *', - 'lastName', - placeholder: 'Smith', - ), - ), - ], - ), - const SizedBox(height: 16), - _buildTextField( - 'Social Security Number *', - 'ssn', - placeholder: 'XXX-XX-XXXX', - keyboardType: TextInputType.number, - onChanged: (val) { - String text = val.replaceAll(RegExp(r'\D'), ''); - if (text.length > 9) text = text.substring(0, 9); - _updateField('ssn', text); - }, - ), - const SizedBox(height: 16), - _buildTextField('Address *', 'address', placeholder: '123 Main Street'), - const SizedBox(height: 16), - _buildTextField( - 'City, State, ZIP', - 'cityStateZip', - placeholder: 'San Francisco, CA 94102', - ), - ], - ); - } - - Widget _buildStep2() { - return Column( - children: [ - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.blue[50], - borderRadius: BorderRadius.circular(12), - ), - child: Row( - children: [ - const Icon(LucideIcons.info, color: Color(0xFF2563EB), size: 20), - const SizedBox(width: 12), - const Expanded( - child: Text( - 'Your filing status determines your standard deduction and tax rates.', - style: TextStyle(fontSize: 14, color: Color(0xFF1D4ED8)), - ), - ), - ], - ), - ), - const SizedBox(height: 24), - _buildRadioOption( - 'single', - 'Single or Married filing separately', - null, - ), - const SizedBox(height: 12), - _buildRadioOption( - 'married', - 'Married filing jointly or Qualifying surviving spouse', - null, - ), - const SizedBox(height: 12), - _buildRadioOption( - 'head_of_household', - 'Head of household', - 'Check only if you\'re unmarried and pay more than half the costs of keeping up a home', - ), - ], - ); - } - - Widget _buildRadioOption(String value, String label, String? subLabel) { - final isSelected = _formData['filingStatus'] == value; - return GestureDetector( - onTap: () => _updateField('filingStatus', value), - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: isSelected ? AppColors.krowBlue : AppColors.krowBorder, - width: isSelected ? 2 : 1, - ), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - margin: const EdgeInsets.only(top: 2), - width: 20, - height: 20, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: isSelected ? AppColors.krowBlue : Colors.grey, - width: isSelected ? 6 : 2, - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - label, - style: const TextStyle( - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - if (subLabel != null) ...[ - const SizedBox(height: 4), - Text( - subLabel, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ], - ), - ), - ], - ), - ), - ); - } - - Widget _buildStep3() { - return Column( - children: [ - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.amber[50], - borderRadius: BorderRadius.circular(12), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Icon( - LucideIcons.helpCircle, - color: Color(0xFFD97706), - size: 20, - ), - const SizedBox(width: 12), - const Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'When to complete this step?', - style: TextStyle( - fontWeight: FontWeight.w600, - color: Color(0xFF92400E), - fontSize: 14, - ), - ), - SizedBox(height: 4), - Text( - 'Complete this step only if you hold more than one job at a time, or are married filing jointly and your spouse also works.', - style: TextStyle(fontSize: 12, color: Color(0xFFB45309)), - ), - ], - ), - ), - ], - ), - ), - const SizedBox(height: 24), - GestureDetector( - onTap: () => _updateField('multipleJobs', !_formData['multipleJobs']), - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: _formData['multipleJobs'] - ? AppColors.krowBlue - : AppColors.krowBorder, - ), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 24, - height: 24, - decoration: BoxDecoration( - color: _formData['multipleJobs'] - ? AppColors.krowBlue - : Colors.white, - borderRadius: BorderRadius.circular(6), - border: Border.all( - color: _formData['multipleJobs'] - ? AppColors.krowBlue - : Colors.grey, - ), - ), - child: _formData['multipleJobs'] - ? const Icon( - LucideIcons.check, - color: Colors.white, - size: 16, - ) - : null, - ), - const SizedBox(width: 12), - const Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'I have multiple jobs or my spouse works', - style: TextStyle( - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - SizedBox(height: 4), - Text( - 'Check this box if there are only two jobs total', - style: TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - ], - ), - ), - ), - const SizedBox(height: 16), - const Text( - 'If this does not apply, you can continue to the next step', - textAlign: TextAlign.center, - style: TextStyle(fontSize: 12, color: AppColors.krowMuted), - ), - ], - ); - } - - Widget _buildStep4() { - return Column( - children: [ - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.blue[50], - borderRadius: BorderRadius.circular(12), - ), - child: Row( - children: [ - const Icon(LucideIcons.info, color: Color(0xFF2563EB), size: 20), - const SizedBox(width: 12), - const Expanded( - child: Text( - 'If your total income will be \$200,000 or less (\$400,000 if married filing jointly), you may claim credits for dependents.', - style: TextStyle(fontSize: 14, color: Color(0xFF1D4ED8)), - ), - ), - ], - ), - ), - const SizedBox(height: 24), - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - children: [ - _buildCounter( - 'Qualifying children under age 17', - '\$2,000 each', - 'qualifyingChildren', - ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 16), - child: Divider(height: 1, color: AppColors.krowBorder), - ), - _buildCounter( - 'Other dependents', - '\$500 each', - 'otherDependents', - ), - ], - ), - ), - if (_totalCredits > 0) ...[ - const SizedBox(height: 16), - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFFDCFCE7), - borderRadius: BorderRadius.circular(12), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Total credits (Step 3)', - style: TextStyle( - fontWeight: FontWeight.w500, - color: Color(0xFF166534), - ), - ), - Text( - ' rastructure${_totalCredits}', - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Color(0xFF15803D), - ), - ), - ], - ), - ), - ], - ], - ); - } - - Widget _buildCounter(String label, String badge, String key) { - int value = _formData[key] as int; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - label, - style: const TextStyle(fontWeight: FontWeight.w500), - ), - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: const Color(0xFFDCFCE7), - borderRadius: BorderRadius.circular(12), - ), - child: Text( - badge, - style: const TextStyle( - fontSize: 10, - color: Color(0xFF15803D), - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - const SizedBox(height: 12), - Row( - children: [ - _buildCircleBtn( - LucideIcons.minus, - () => _updateField(key, value > 0 ? value - 1 : 0), - ), - SizedBox( - width: 48, - child: Text( - value.toString(), - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - _buildCircleBtn( - LucideIcons.plus, - () => _updateField(key, value + 1), - ), - ], - ), - ], - ); - } - - Widget _buildCircleBtn(IconData icon, VoidCallback onTap) { - return GestureDetector( - onTap: onTap, - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all(color: AppColors.krowBorder), - color: Colors.white, - ), - child: Icon(icon, size: 20, color: AppColors.krowCharcoal), - ), - ); - } - - Widget _buildStep5() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'These adjustments are optional. You can skip them if they don\'t apply.', - style: TextStyle(color: AppColors.krowMuted, fontSize: 14), - ), - const SizedBox(height: 24), - _buildTextField( - '4(a) Other income (not from jobs)', - 'otherIncome', - placeholder: '\$0', - keyboardType: TextInputType.number, - ), - const Padding( - padding: EdgeInsets.only(top: 4, bottom: 16), - child: Text( - 'Include interest, dividends, retirement income', - style: TextStyle(fontSize: 12, color: AppColors.krowMuted), - ), - ), - - _buildTextField( - '4(b) Deductions', - 'deductions', - placeholder: '\$0', - keyboardType: TextInputType.number, - ), - const Padding( - padding: EdgeInsets.only(top: 4, bottom: 16), - child: Text( - 'If you expect to claim deductions other than the standard deduction', - style: TextStyle(fontSize: 12, color: AppColors.krowMuted), - ), - ), - - _buildTextField( - '4(c) Extra withholding', - 'extraWithholding', - placeholder: '\$0', - keyboardType: TextInputType.number, - ), - const Padding( - padding: EdgeInsets.only(top: 4, bottom: 16), - child: Text( - 'Additional tax to withhold each pay period', - style: TextStyle(fontSize: 12, color: AppColors.krowMuted), - ), - ), - ], - ); - } - - Widget _buildStep6() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Your W-4 Summary', - style: TextStyle(fontWeight: FontWeight.w600, fontSize: 14), - ), - const SizedBox(height: 12), - _buildSummaryRow( - 'Name', - '${_formData['firstName']} ${_formData['lastName']}', - ), - _buildSummaryRow( - 'SSN', - '***-**-${_formData['ssn'].length >= 4 ? _formData['ssn'].substring(_formData['ssn'].length - 4) : '****'}', - ), - _buildSummaryRow( - 'Filing Status', - _getFilingStatusLabel(_formData['filingStatus']), - ), - if (_totalCredits > 0) - _buildSummaryRow( - 'Credits', - '\$${_totalCredits}', - valueColor: Colors.green[700], - ), - ], - ), - ), - const SizedBox(height: 24), - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.amber[50], - borderRadius: BorderRadius.circular(12), - ), - child: const Text( - 'Under penalties of perjury, I declare that this certificate, to the best of my knowledge and belief, is true, correct, and complete.', - style: TextStyle(fontSize: 12, color: Color(0xFFB45309)), - ), - ), - const SizedBox(height: 24), - const Text( - 'Signature (type your full name) *', - style: TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - fontWeight: FontWeight.w500, - ), - ), - const SizedBox(height: 6), - TextField( - onChanged: (val) => setState(() => _signature = val), - decoration: InputDecoration( - hintText: 'Type your full name', - filled: true, - fillColor: Colors.white, - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBorder), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBorder), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBlue), - ), - ), - style: const TextStyle(fontFamily: 'Cursive', fontSize: 18), - ), - const SizedBox(height: 16), - const Text( - 'Date', - style: TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - fontWeight: FontWeight.w500, - ), - ), - const SizedBox(height: 6), - Container( - width: double.infinity, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), - decoration: BoxDecoration( - color: const Color(0xFFF3F4F6), - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: Text( - DateTime.now().toString().split(' ')[0], - style: const TextStyle(color: AppColors.krowCharcoal), - ), - ), - ], - ); - } - - Widget _buildSummaryRow(String label, String value, {Color? valueColor}) { - return Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - label, - style: const TextStyle(color: AppColors.krowMuted, fontSize: 14), - ), - Text( - value, - style: TextStyle( - fontWeight: FontWeight.w500, - fontSize: 14, - color: valueColor ?? AppColors.krowCharcoal, - ), - ), - ], - ), - ); - } - - String _getFilingStatusLabel(String status) { - switch (status) { - case 'single': - return 'Single'; - case 'married': - return 'Married'; - case 'head_of_household': - return 'Head of Household'; - default: - return status; - } - } - - Widget _buildFooter() { - return Container( - padding: const EdgeInsets.all(16), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: AppColors.krowBorder)), - ), - child: SafeArea( - child: Row( - children: [ - if (_currentStep > 0) - Expanded( - child: Padding( - padding: const EdgeInsets.only(right: 12), - child: OutlinedButton( - onPressed: _handleBack, - style: OutlinedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 16), - side: const BorderSide(color: AppColors.krowBorder), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(LucideIcons.arrowLeft, size: 16), - SizedBox(width: 8), - Text( - 'Back', - style: TextStyle(color: AppColors.krowCharcoal), - ), - ], - ), - ), - ), - ), - Expanded( - flex: 2, - child: ElevatedButton( - onPressed: (_canProceed() && !_isSubmitting) - ? _handleNext - : null, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - disabledBackgroundColor: Colors.grey[300], - foregroundColor: Colors.white, - padding: const EdgeInsets.symmetric(vertical: 16), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: _isSubmitting - ? const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - color: Colors.white, - strokeWidth: 2, - ), - ) - : Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - _currentStep == _steps.length - 1 - ? 'Submit Form' - : 'Continue', - ), - if (_currentStep < _steps.length - 1) ...[ - const SizedBox(width: 8), - const Icon(LucideIcons.arrowRight, size: 16), - ], - ], - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/finances/bank_account_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/finances/bank_account_screen.dart deleted file mode 100644 index 9465ae2f..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/finances/bank_account_screen.dart +++ /dev/null @@ -1,435 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import '../../../../theme.dart'; - -class BankAccountScreen extends ConsumerStatefulWidget { - const BankAccountScreen({super.key}); - - @override - ConsumerState createState() => _BankAccountScreenState(); -} - -class _BankAccountScreenState extends ConsumerState { - bool _showForm = false; - - // Mock Data - final List> _accounts = [ - { - 'id': 1, - 'bank': 'Chase Bank', - 'type': 'CHECKING', - 'last4': '4523', - 'isPrimary': true, - }, - ]; - - // Form Controllers - final _routingController = TextEditingController(); - final _accountController = TextEditingController(); - String _selectedType = 'CHECKING'; - - @override - void dispose() { - _routingController.dispose(); - _accountController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFFAFBFC), - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.chevronLeft, color: Color(0xFF6A7382)), - onPressed: () => context.pop(), - ), - title: const Text( - 'Bank Account', - style: TextStyle( - color: Color(0xFF121826), - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1.0), - child: Container(color: const Color(0xFFE3E6E9), height: 1.0), - ), - ), - body: Column( - children: [ - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildSecurityNotice(), - const SizedBox(height: 24), - const Text( - 'Linked Accounts', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF121826), - ), - ), - const SizedBox(height: 12), - ..._accounts.map(_buildAccountCard), - - if (_showForm) ...[ - const SizedBox(height: 24), - _buildAddAccountForm(), - ], - // Add extra padding at bottom to avoid FAB overlap if needed - const SizedBox(height: 80), - ], - ), - ), - ), - if (!_showForm) - Container( - padding: const EdgeInsets.all(20), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: Color(0xFFE3E6E9))), - ), - child: SafeArea( - child: SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: () => setState(() => _showForm = true), - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0A39DF), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - elevation: 0, - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(LucideIcons.plus, color: Colors.white, size: 20), - SizedBox(width: 8), - Text( - 'Add Bank Account', - style: TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - ], - ), - ), - ), - ), - ), - ], - ), - ); - } - - Widget _buildSecurityNotice() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFF0A39DF).withOpacity(0.08), - borderRadius: BorderRadius.circular(8), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Icon(LucideIcons.shield, color: Color(0xFF0A39DF), size: 20), - const SizedBox(width: 12), - const Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Secure & Encrypted', - style: TextStyle( - fontWeight: FontWeight.w500, - fontSize: 14, - color: Color(0xFF121826), - ), - ), - SizedBox(height: 2), - Text( - 'Your banking information is encrypted and securely stored. We never share your details.', - style: TextStyle(fontSize: 12, color: Color(0xFF6A7382)), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildAccountCard(Map account) { - final bool isPrimary = account['isPrimary'] ?? false; - final Color primaryColor = const Color(0xFF0A39DF); - - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: isPrimary ? primaryColor : const Color(0xFFE3E6E9), - width: isPrimary ? 2 : 1, - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - width: 48, - height: 48, - decoration: BoxDecoration( - color: primaryColor.withOpacity(0.1), - borderRadius: BorderRadius.circular(8), - ), - child: Center( - child: Icon( - LucideIcons.building2, - color: primaryColor, - size: 24, - ), - ), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - account['bank'], - style: const TextStyle( - fontWeight: FontWeight.w500, - fontSize: 14, - color: Color(0xFF121826), - ), - ), - Text( - '${account['type']} •••• ${account['last4']}', - style: const TextStyle( - fontSize: 14, - color: Color(0xFF6A7382), - ), - ), - ], - ), - ], - ), - if (isPrimary) - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: primaryColor.withOpacity(0.15), - borderRadius: BorderRadius.circular(20), // Badge style - ), - child: Row( - children: [ - Icon(LucideIcons.check, size: 12, color: primaryColor), - const SizedBox(width: 4), - Text( - 'Primary', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: primaryColor, - ), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildAddAccountForm() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Add New Account', - style: TextStyle( - fontWeight: FontWeight.w500, - fontSize: 16, - color: Color(0xFF121826), - ), - ), - const SizedBox(height: 16), - _buildInputLabel('Routing Number'), - TextField( - controller: _routingController, - decoration: _inputDecoration('9 digits'), - keyboardType: TextInputType.number, - ), - const SizedBox(height: 16), - _buildInputLabel('Account Number'), - TextField( - controller: _accountController, - decoration: _inputDecoration('Enter account number'), - keyboardType: TextInputType.number, - ), - const SizedBox(height: 16), - _buildInputLabel('Account Type'), - Row( - children: [ - Expanded(child: _buildTypeButton('CHECKING')), - const SizedBox(width: 8), - Expanded(child: _buildTypeButton('SAVINGS')), - ], - ), - const SizedBox(height: 16), - Row( - children: [ - Expanded( - child: OutlinedButton( - onPressed: () => setState(() => _showForm = false), - style: OutlinedButton.styleFrom( - side: const BorderSide(color: Color(0xFFE3E6E9)), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - padding: const EdgeInsets.symmetric(vertical: 12), - ), - child: const Text( - 'Cancel', - style: TextStyle(color: Color(0xFF121826)), - ), - ), - ), - const SizedBox(width: 8), - Expanded( - child: ElevatedButton( - onPressed: () { - // Mock add account - setState(() { - _accounts.add({ - 'id': DateTime.now().millisecondsSinceEpoch, - 'bank': 'New Bank', - 'type': _selectedType, - 'last4': _accountController.text.length > 4 - ? _accountController.text.substring( - _accountController.text.length - 4, - ) - : '0000', - 'isPrimary': false, - }); - _showForm = false; - _accountController.clear(); - _routingController.clear(); - }); - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0A39DF), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - padding: const EdgeInsets.symmetric(vertical: 12), - elevation: 0, - ), - child: const Text( - 'Link Account', - style: TextStyle(color: Colors.white), - ), - ), - ), - ], - ), - ], - ), - ); - } - - Widget _buildInputLabel(String label) { - return Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Text( - label, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - ), - ); - } - - InputDecoration _inputDecoration(String hint) { - return InputDecoration( - hintText: hint, - hintStyle: const TextStyle(color: Color(0xFF9CA3AF)), - contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(6), - borderSide: const BorderSide(color: Color(0xFFE3E6E9)), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(6), - borderSide: const BorderSide(color: Color(0xFFE3E6E9)), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(6), - borderSide: const BorderSide(color: Color(0xFF0A39DF)), - ), - ); - } - - Widget _buildTypeButton(String type) { - final bool isSelected = _selectedType == type; - return GestureDetector( - onTap: () => setState(() => _selectedType = type), - child: Container( - padding: const EdgeInsets.symmetric(vertical: 10), - alignment: Alignment.center, - decoration: BoxDecoration( - color: isSelected - ? const Color(0xFFF1F5F9) - : Colors - .white, // Slight gray if selected? Or use OutlineButton style - // React uses Button variant="outline", which usually has gray border and white bg. - // There's no distinct active state style in the React code provided for the buttons other than they exist. - // Wait, the React code doesn't show active state styling for these buttons, just renders them. - // I will make them selectable visually. - borderRadius: BorderRadius.circular(6), - border: Border.all( - color: isSelected - ? const Color(0xFF0A39DF) - : const Color(0xFFE3E6E9), - ), - ), - child: Text( - type, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: isSelected - ? const Color(0xFF0A39DF) - : const Color(0xFF121826), - ), - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/finances/time_card_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/finances/time_card_screen.dart deleted file mode 100644 index 1722f610..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/finances/time_card_screen.dart +++ /dev/null @@ -1,415 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import 'package:intl/intl.dart'; -import '../../../../theme.dart'; - -class TimeCardScreen extends ConsumerStatefulWidget { - const TimeCardScreen({super.key}); - - @override - ConsumerState createState() => _TimeCardScreenState(); -} - -class _TimeCardScreenState extends ConsumerState { - DateTime _selectedDate = DateTime.now(); - - // Mock Data - final List> _timesheets = [ - { - 'id': '1', - 'shiftId': '101', - 'date': DateTime.now() - .subtract(const Duration(days: 1)) - .toIso8601String(), - 'startTime': '09:00', - 'endTime': '17:00', - 'totalHours': 8.0, - 'hourlyRate': 20.0, - 'totalPay': 160.0, - 'status': 'PENDING', - 'shiftTitle': 'Line Cook', - 'clientName': 'Burger King', - 'location': 'Downtown', - }, - { - 'id': '2', - 'shiftId': '102', - 'date': DateTime.now() - .subtract(const Duration(days: 3)) - .toIso8601String(), - 'startTime': '10:00', - 'endTime': '16:00', - 'totalHours': 6.0, - 'hourlyRate': 18.0, - 'totalPay': 108.0, - 'status': 'APPROVED', - 'shiftTitle': 'Dishwasher', - 'clientName': 'The Pierre', - 'location': 'Upper East Side', - }, - { - 'id': '3', - 'shiftId': '103', - 'date': DateTime.now() - .subtract(const Duration(days: 10)) - .toIso8601String(), - 'startTime': '18:00', - 'endTime': '23:00', - 'totalHours': 5.0, - 'hourlyRate': 22.0, - 'totalPay': 110.0, - 'status': 'PAID', - 'shiftTitle': 'Bartender', - 'clientName': 'Rooftop Bar', - 'location': 'Midtown', - }, - ]; - - @override - Widget build(BuildContext context) { - // Filter timesheets by selected month/year - final filteredTimesheets = _timesheets.where((t) { - final date = DateTime.parse(t['date']); - return date.month == _selectedDate.month && - date.year == _selectedDate.year; - }).toList(); - - final totalHours = filteredTimesheets.fold( - 0.0, - (sum, t) => sum + (t['totalHours'] as double), - ); - final totalEarnings = filteredTimesheets.fold( - 0.0, - (sum, t) => sum + (t['totalPay'] as double), - ); - - return Scaffold( - backgroundColor: const Color(0xFFFAFBFC), - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.chevronLeft, color: Color(0xFF6A7382)), - onPressed: () => context.pop(), - ), - title: const Text( - 'Timecard', - style: TextStyle( - color: Color(0xFF121826), - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1.0), - child: Container(color: const Color(0xFFE3E6E9), height: 1.0), - ), - ), - body: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 24), - child: Column( - children: [ - _buildMonthSelector(), - const SizedBox(height: 24), - _buildSummary(totalHours, totalEarnings), - const SizedBox(height: 24), - _buildShiftHistory(filteredTimesheets), - ], - ), - ), - ); - } - - Widget _buildMonthSelector() { - return Container( - padding: const EdgeInsets.all( - 4, - ), // React uses p-3, but row layout needs space - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - IconButton( - icon: const Icon(LucideIcons.chevronLeft, color: Color(0xFF6A7382)), - onPressed: () { - setState(() { - _selectedDate = DateTime( - _selectedDate.year, - _selectedDate.month - 1, - ); - }); - }, - ), - Text( - DateFormat('MMM yyyy').format(_selectedDate), - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF121826), - ), - ), - IconButton( - icon: const Icon( - LucideIcons.chevronRight, - color: Color(0xFF6A7382), - ), - onPressed: () { - setState(() { - _selectedDate = DateTime( - _selectedDate.year, - _selectedDate.month + 1, - ); - }); - }, - ), - ], - ), - ); - } - - Widget _buildSummary(double totalHours, double totalEarnings) { - return Row( - children: [ - Expanded( - child: _buildSummaryCard( - LucideIcons.clock, - 'Hours Worked', - totalHours.toStringAsFixed(1), - ), - ), - const SizedBox(width: 12), - Expanded( - child: _buildSummaryCard( - LucideIcons.dollarSign, - 'Total Earnings', - '\$${totalEarnings.toStringAsFixed(2)}', - ), - ), - ], - ); - } - - Widget _buildSummaryCard(IconData icon, String label, String value) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon(icon, size: 16, color: const Color(0xFF0A39DF)), - const SizedBox(width: 8), - Text( - label, - style: const TextStyle(fontSize: 12, color: Color(0xFF6A7382)), - ), - ], - ), - const SizedBox(height: 8), - Text( - value, - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Color(0xFF121826), - ), - ), - ], - ), - ); - } - - Widget _buildShiftHistory(List> timesheets) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Shift History', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF121826), - ), - ), - const SizedBox(height: 12), - if (timesheets.isEmpty) - const Center( - child: Padding( - padding: EdgeInsets.symmetric(vertical: 48), - child: Column( - children: [ - Icon(LucideIcons.clock, size: 48, color: Color(0xFF6A7382)), - SizedBox(height: 12), - Text( - 'No shifts for this month', - style: TextStyle(color: Color(0xFF6A7382)), - ), - ], - ), - ), - ) - else - ...timesheets.map(_buildTimesheetCard), - ], - ); - } - - Widget _buildTimesheetCard(Map timesheet) { - final status = timesheet['status']; - Color statusBg; - Color statusColor; - - switch (status) { - case 'APPROVED': - statusBg = const Color(0xFF10B981).withOpacity(0.12); - statusColor = const Color(0xFF10B981); // Green - break; - case 'DISPUTED': - statusBg = const Color(0xFFEF4444).withOpacity(0.12); - statusColor = const Color(0xFFEF4444); // Red - break; - case 'PAID': - statusBg = const Color(0xFF0A39DF).withOpacity(0.12); - statusColor = const Color(0xFF0A39DF); // Blue - break; - case 'PENDING': - default: - statusBg = const Color(0xFFF59200).withOpacity(0.12); - statusColor = const Color(0xFFF59200); // Orange - break; - } - - final date = DateTime.parse(timesheet['date']); - final dateStr = DateFormat('EEE, MMM d').format(date); - - // Format times: 09:00 -> 9:00 AM - String formatTime(String t) { - if (t.isEmpty) return '--:--'; - final parts = t.split(':'); - final dt = DateTime(2000, 1, 1, int.parse(parts[0]), int.parse(parts[1])); - return DateFormat('h:mm a').format(dt); - } - - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - timesheet['shiftTitle'], - style: const TextStyle( - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - ), - Text( - timesheet['clientName'], - style: const TextStyle( - fontSize: 12, - color: Color(0xFF6A7382), - ), - ), - ], - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: statusBg, - borderRadius: BorderRadius.circular(20), - ), - child: Text( - status.toString().replaceFirst( - status[0], - status[0].toUpperCase(), - ), - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: statusColor, - ), - ), - ), - ], - ), - const SizedBox(height: 12), - Wrap( - spacing: 12, - runSpacing: 4, - children: [ - _buildIconText(LucideIcons.calendar, dateStr), - _buildIconText( - LucideIcons.clock, - '${formatTime(timesheet['startTime'])} - ${formatTime(timesheet['endTime'])}', - ), - if (timesheet['location'] != null) - _buildIconText(LucideIcons.mapPin, timesheet['location']), - ], - ), - const SizedBox(height: 12), - Container( - padding: const EdgeInsets.only(top: 12), - decoration: const BoxDecoration( - border: Border(top: BorderSide(color: Color(0xFFE3E6E9))), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - '${timesheet['totalHours'].toStringAsFixed(1)} hours @ \$${timesheet['hourlyRate']}/hr', - style: const TextStyle( - fontSize: 12, - color: Color(0xFF6A7382), - ), - ), - Text( - '\$${timesheet['totalPay'].toStringAsFixed(2)}', - style: const TextStyle( - fontWeight: FontWeight.w600, - color: Color(0xFF0A39DF), - ), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildIconText(IconData icon, String text) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(icon, size: 14, color: const Color(0xFF6A7382)), - const SizedBox(width: 4), - Text( - text, - style: const TextStyle(fontSize: 12, color: Color(0xFF6A7382)), - ), - ], - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/level_up/krow_university_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/level_up/krow_university_screen.dart deleted file mode 100644 index 7782292d..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/level_up/krow_university_screen.dart +++ /dev/null @@ -1,820 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import '../../../../theme.dart'; - -class KrowUniversityScreen extends ConsumerStatefulWidget { - const KrowUniversityScreen({super.key}); - - @override - ConsumerState createState() => - _KrowUniversityScreenState(); -} - -class _KrowUniversityScreenState extends ConsumerState { - String _activeCategory = 'all'; - - // Mock Data - final Map _staff = { - 'level': 'Krower I', - 'xp': 1250, - 'badges': [], - }; - - final List> _levels = [ - { - 'name': 'Krower I', - 'xpRequired': 0, - 'icon': LucideIcons.award, - 'colors': [Color(0xFF333F48), Color(0xFF4A5A64)], - }, - { - 'name': 'Krower II', - 'xpRequired': 500, - 'icon': LucideIcons.star, - 'colors': [Color(0xFF0032A0), Color(0xFF0047CC)], - }, - { - 'name': 'Krower III', - 'xpRequired': 1500, - 'icon': LucideIcons.sparkles, - 'colors': [Color(0xFF0032A0), Color(0xFF333F48)], - }, - { - 'name': 'Krower Elite', - 'xpRequired': 3500, - 'icon': LucideIcons.crown, - 'colors': [Color(0xFFF7E600), Color(0xFFF8E08E)], - }, - ]; - - final List> _categories = [ - {'categoryId': 'all', 'label': 'All', 'icon': LucideIcons.graduationCap}, - {'categoryId': 'food_safety', 'label': 'Food Safety', 'icon': LucideIcons.award}, - {'categoryId': 'hospitality', 'label': 'Hospitality', 'icon': LucideIcons.star}, - {'categoryId': 'warehouse', 'label': 'Warehouse', 'icon': LucideIcons.award}, - {'categoryId': 'leadership', 'label': 'Leadership', 'icon': LucideIcons.award}, - ]; - - final List> _courses = [ - { - 'id': '1', - 'title': 'Introduction to Food Safety', - 'description': 'Learn the basics of food handling and safety protocols.', - 'category': 'food_safety', - 'durationMinutes': 30, - 'xpReward': 100, - 'levelRequired': 'Krower I', - 'isCertification': true, - 'progressPercent': 100, - 'completed': true, - }, - { - 'id': '2', - 'title': 'Advanced Customer Service', - 'description': 'Master the art of hospitality and guest satisfaction.', - 'category': 'hospitality', - 'durationMinutes': 45, - 'xpReward': 150, - 'levelRequired': 'Krower I', - 'isCertification': false, - 'progressPercent': 45, - 'completed': false, - }, - { - 'id': '3', - 'title': 'Warehouse Operations 101', - 'description': - 'Essential safety and operational guidelines for warehouse work.', - 'category': 'warehouse', - 'durationMinutes': 60, - 'xpReward': 200, - 'levelRequired': 'Krower II', - 'isCertification': true, - 'progressPercent': 0, - 'completed': false, - }, - { - 'id': '4', - 'title': 'Team Leadership Fundamentals', - 'description': 'Developing core leadership skills for shift supervisors.', - 'category': 'leadership', - 'durationMinutes': 90, - 'xpReward': 300, - 'levelRequired': 'Krower III', - 'isCertification': true, - 'progressPercent': 0, - 'completed': false, - }, - ]; - - final List _certifications = [ - 'Food Handler', - 'Alcohol Safety', - 'First Aid', - 'OSHA', - ]; - - @override - Widget build(BuildContext context) { - final filteredCourses = _activeCategory == 'all' - ? _courses - : _courses.where((c) => c['category'] == _activeCategory).toList(); - - final completedCount = _courses.where((c) => c['completed'] == true).length; - final totalXpEarned = _staff['xp']; - - return Scaffold( - backgroundColor: const Color(0xFFF8F9FA), - body: SingleChildScrollView( - padding: const EdgeInsets.only(bottom: 100), - child: Column( - children: [ - _buildHeader(completedCount, totalXpEarned), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 20), - _buildLevelProgress(), - const SizedBox(height: 24), - _buildCategories(), - const SizedBox(height: 24), - _buildSectionHeader( - _activeCategory == 'all' - ? 'All Courses' - : _categories.firstWhere( - (c) => c['categoryId'] == _activeCategory, - )['label'], - null, - ), - _buildCoursesList(filteredCourses), - _buildSectionHeader('Certifications', null), - _buildCertificationsGrid(), - ], - ), - ), - ], - ), - ), - ); - } - - Widget _buildHeader(int completedCount, int totalXp) { - return Container( - width: double.infinity, - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [Color(0xFF7C3AED), Color(0xFF6D28D9)], - ), - ), - padding: const EdgeInsets.fromLTRB(20, 60, 20, 32), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - const Text( - 'KROW University', - style: TextStyle( - color: Colors.white, - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 24), - Row( - children: [ - Expanded( - child: _buildStatCard(_courses.length.toString(), 'Courses'), - ), - const SizedBox(width: 12), - Expanded( - child: _buildStatCard(completedCount.toString(), 'Completed'), - ), - const SizedBox(width: 12), - Expanded(child: _buildStatCard(totalXp.toString(), 'XP')), - ], - ), - ], - ), - ); - } - - Widget _buildStatCard(String value, String label) { - return Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(12), - ), - child: Column( - children: [ - Text( - value, - style: const TextStyle( - color: Colors.white, - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - Text( - label, - style: const TextStyle(color: Color(0xFFDDD6FE), fontSize: 12), - ), - ], - ), - ); - } - - Widget _buildLevelProgress() { - final String currentLevelName = _staff['level']; - final int xp = _staff['xp']; - final List badges = List.from(_staff['badges']); - - final currentLevelIndex = _levels.indexWhere( - (l) => l['name'] == currentLevelName, - ); - final currentLevel = currentLevelIndex != -1 - ? _levels[currentLevelIndex] - : _levels[0]; - final nextLevel = currentLevelIndex + 1 < _levels.length - ? _levels[currentLevelIndex + 1] - : null; - - final double progressToNext = nextLevel != null - ? ((xp - currentLevel['xpRequired']) / - (nextLevel['xpRequired'] - currentLevel['xpRequired'])) - .clamp(0.0, 1.0) - : 1.0; - - return Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(20), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - border: Border.all(color: const Color(0xFFF1F5F9)), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Your Level', - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), - ), - const Icon( - LucideIcons.chevronRight, - size: 20, - color: Color(0xFF94A3B8), - ), - ], - ), - const SizedBox(height: 20), - Row( - children: [ - Container( - width: 64, - height: 64, - decoration: BoxDecoration( - gradient: LinearGradient( - colors: currentLevel['colors'], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: (currentLevel['colors'][0] as Color).withOpacity( - 0.3, - ), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: Icon( - currentLevel['icon'], - color: Colors.white, - size: 32, - ), - ), - const SizedBox(width: 16), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - currentLevel['name'], - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - Text( - '$xp XP earned', - style: const TextStyle( - fontSize: 14, - color: Color(0xFF64748B), - ), - ), - ], - ), - ], - ), - if (nextLevel != null) ...[ - const SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Progress to ${nextLevel['name']}', - style: const TextStyle( - fontSize: 14, - color: Color(0xFF64748B), - ), - ), - Text( - '${(progressToNext * 100).toInt()}%', - style: const TextStyle(fontWeight: FontWeight.bold), - ), - ], - ), - const SizedBox(height: 8), - ClipRRect( - borderRadius: BorderRadius.circular(6), - child: LinearProgressIndicator( - value: progressToNext, - minHeight: 12, - backgroundColor: const Color(0xFFF1F5F9), - valueColor: AlwaysStoppedAnimation( - nextLevel['colors'][1], - ), - ), - ), - const SizedBox(height: 8), - Text( - '${nextLevel['xpRequired'] - xp} XP to go', - style: const TextStyle(fontSize: 12, color: Color(0xFF94A3B8)), - ), - ], - const SizedBox(height: 20), - Text( - 'Badges Earned (${badges.length})', - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF334155), - ), - ), - const SizedBox(height: 8), - if (badges.isEmpty) - const Text( - 'Complete courses to earn badges!', - style: TextStyle(fontSize: 14, color: Color(0xFF94A3B8)), - ) - else - Wrap( - spacing: 8, - children: badges.map((b) => _buildBadgeChip(b)).toList(), - ), - const SizedBox(height: 16), - // Level Benefits - if (nextLevel != null) - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - const Color(0xFFF8E08E).withOpacity(0.3), - const Color(0xFFF7E600).withOpacity(0.2), - ], - ), - borderRadius: BorderRadius.circular(12), - ), - child: Text( - '🎯 Reach ${nextLevel['name']} to unlock premium shifts & +\$2/hr bonus!', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF333F48), - ), - ), - ), - ], - ), - ); - } - - Widget _buildBadgeChip(String label) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - const Color(0xFF0032A0).withOpacity(0.05), - const Color(0xFF0032A0).withOpacity(0.1), - ], - ), - border: Border.all(color: const Color(0xFF0032A0).withOpacity(0.2)), - borderRadius: BorderRadius.circular(8), - ), - child: Text( - label, - style: const TextStyle(color: Color(0xFF0032A0), fontSize: 12), - ), - ); - } - - Widget _buildCategories() { - return SingleChildScrollView( - scrollDirection: Axis.horizontal, - clipBehavior: Clip.none, - child: Row( - children: _categories.map((cat) { - final bool isActive = _activeCategory == cat['categoryId']; - return Padding( - padding: const EdgeInsets.only(right: 8), - child: GestureDetector( - onTap: () => setState(() => _activeCategory = cat['categoryId']), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 10, - ), - decoration: BoxDecoration( - color: isActive ? const Color(0xFF7C3AED) : Colors.white, - borderRadius: BorderRadius.circular(24), - border: isActive - ? null - : Border.all(color: const Color(0xFFE2E8F0)), - boxShadow: isActive - ? [ - BoxShadow( - color: const Color(0xFF7C3AED).withOpacity(0.2), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ] - : null, - ), - child: Row( - children: [ - Icon( - cat['icon'], - size: 16, - color: isActive ? Colors.white : const Color(0xFF64748B), - ), - const SizedBox(width: 8), - Text( - cat['label'], - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: isActive - ? Colors.white - : const Color(0xFF64748B), - ), - ), - ], - ), - ), - ), - ); - }).toList(), - ), - ); - } - - Widget _buildSectionHeader(String title, String? action) { - return Text( - title, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ); - } - - Widget _buildCoursesList(List> courses) { - if (courses.isEmpty) { - return Center( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 40), - child: Column( - children: [ - const Icon( - LucideIcons.graduationCap, - size: 48, - color: Color(0xFFCBD5E1), - ), - const SizedBox(height: 12), - const Text( - 'No courses in this category yet', - style: TextStyle(color: Color(0xFF64748B)), - ), - ], - ), - ), - ); - } - return ListView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: courses.length, - itemBuilder: (context, index) { - final course = courses[index]; - final bool isCompleted = course['completed']; - final bool isLocked = - course['levelRequired'] != 'Krower I' && - _staff['level'] != course['levelRequired']; - final double progress = - (course['progressPercent'] as num).toDouble() / 100; - - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.04), - blurRadius: 5, - offset: const Offset(0, 2), - ), - ], - ), - child: Opacity( - opacity: isLocked ? 0.6 : 1.0, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Stack( - children: [ - Container( - width: 80, - height: 80, - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFFF5F3FF), Color(0xFFEDE9FE)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - borderRadius: BorderRadius.circular(12), - ), - child: Center( - child: isLocked - ? const Icon( - LucideIcons.lock, - color: Color(0xFF94A3B8), - ) - : isCompleted - ? const Icon( - LucideIcons.checkCircle, - color: Color(0xFF10B981), - size: 32, - ) - : const Icon( - LucideIcons.play, - color: Color(0xFF7C3AED), - size: 24, - ), - ), - ), - if (course['isCertification']) - Positioned( - top: -4, - right: -4, - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - color: Color(0xFFF59E0B), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.award, - color: Colors.white, - size: 10, - ), - ), - ), - ], - ), - const SizedBox(width: 16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - course['title'], - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - const Icon( - LucideIcons.chevronRight, - size: 20, - color: Color(0xFF94A3B8), - ), - ], - ), - const SizedBox(height: 4), - Text( - course['description'], - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), - ), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - const SizedBox(height: 12), - Row( - children: [ - _buildBadge( - LucideIcons.clock, - '${course['durationMinutes']} min', - ), - const SizedBox(width: 8), - _buildXpBadge('+${course['xpReward']} XP'), - ], - ), - if (progress > 0 && !isCompleted) ...[ - const SizedBox(height: 12), - ClipRRect( - borderRadius: BorderRadius.circular(2), - child: LinearProgressIndicator( - value: progress, - minHeight: 4, - backgroundColor: const Color(0xFFF1F5F9), - valueColor: const AlwaysStoppedAnimation( - Color(0xFF7C3AED), - ), - ), - ), - const SizedBox(height: 4), - Text( - '${(progress * 100).toInt()}% complete', - style: const TextStyle( - fontSize: 10, - color: Color(0xFF94A3B8), - ), - ), - ], - if (isLocked) ...[ - const SizedBox(height: 8), - Text( - '🔒 Requires ${course['levelRequired']}', - style: const TextStyle( - fontSize: 12, - color: Color(0xFFD97706), - fontWeight: FontWeight.w500, - ), - ), - ], - ], - ), - ), - ], - ), - ), - ); - }, - ); - } - - Widget _buildBadge(IconData icon, String text) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(4), - border: Border.all(color: const Color(0xFFE2E8F0)), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(icon, size: 12, color: const Color(0xFF64748B)), - const SizedBox(width: 4), - Text( - text, - style: const TextStyle(fontSize: 10, color: Color(0xFF64748B)), - ), - ], - ), - ); - } - - Widget _buildXpBadge(String text) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: const Color(0xFFF5F3FF), - borderRadius: BorderRadius.circular(4), - border: Border.all(color: const Color(0xFFDDD6FE)), - ), - child: Text( - text, - style: const TextStyle( - fontSize: 10, - fontWeight: FontWeight.w600, - color: Color(0xFF7C3AED), - ), - ), - ); - } - - Widget _buildCertificationsGrid() { - return GridView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - mainAxisSpacing: 12, - crossAxisSpacing: 12, - childAspectRatio: 1.5, - ), - itemCount: _certifications.length, - itemBuilder: (context, index) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: const LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [Color(0xFFFFFBEB), Color(0xFFFEF3C7)], - ), - borderRadius: BorderRadius.circular(16), - border: Border.all(color: const Color(0xFFFEF3C7)), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Icon(LucideIcons.award, color: Color(0xFFD97706), size: 32), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - _certifications[index], - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const Text( - 'Certification', - style: TextStyle(fontSize: 11, color: Color(0xFF64748B)), - ), - ], - ), - ], - ), - ); - }, - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/level_up/leaderboard_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/level_up/leaderboard_screen.dart deleted file mode 100644 index 98d389bf..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/level_up/leaderboard_screen.dart +++ /dev/null @@ -1,450 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; - -class LeaderboardScreen extends ConsumerStatefulWidget { - const LeaderboardScreen({super.key}); - - @override - ConsumerState createState() => _LeaderboardScreenState(); -} - -class _LeaderboardScreenState extends ConsumerState { - String _activeTab = 'weekly'; - - // Mock Data - final List> _profiles = [ - { - 'id': '1', - 'fullName': 'Sarah Jenkins', - 'photoUrl': null, - 'xp': 2500, - 'level': 'Krower III', - 'userId': 'sarah@example.com', - }, - { - 'id': '2', - 'fullName': 'Mike Ross', - 'photoUrl': null, - 'xp': 2350, - 'level': 'Krower II', - 'userId': 'mike@example.com', - }, - { - 'id': '3', - 'fullName': 'Jessica Lee', - 'photoUrl': null, - 'xp': 2100, - 'level': 'Krower II', - 'userId': 'jessica@example.com', - }, - { - 'id': '4', - 'fullName': 'Krower (You)', - 'photoUrl': null, - 'xp': 1250, - 'level': 'Krower I', - 'userId': 'me@krow.com', // Current user - }, - { - 'id': '5', - 'fullName': 'David Chen', - 'photoUrl': null, - 'xp': 900, - 'level': 'Krower I', - 'userId': 'david@example.com', - }, - { - 'id': '6', - 'fullName': 'Emily Clark', - 'photoUrl': null, - 'xp': 850, - 'level': 'Krower I', - 'userId': 'emily@example.com', - }, - ]; - - @override - Widget build(BuildContext context) { - // Sort profiles by XP desc - final sortedProfiles = List>.from(_profiles); - sortedProfiles.sort((a, b) => (b['xp'] as int).compareTo(a['xp'] as int)); - - final topThree = sortedProfiles.take(3).toList(); - final rest = sortedProfiles.skip(3).toList(); - - // Find my rank - final myIndex = sortedProfiles.indexWhere( - (p) => p['userId'] == 'me@krow.com', - ); - final myRank = myIndex + 1; - - return Scaffold( - backgroundColor: const Color(0xFFFAFBFC), - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.chevronLeft, color: Color(0xFF6A7382)), - onPressed: () => context.pop(), - ), - title: const Text( - 'Leaderboard', - style: TextStyle( - color: Color(0xFF121826), - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1.0), - child: Container(color: const Color(0xFFE3E6E9), height: 1.0), - ), - ), - body: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 24), - child: Column( - children: [ - _buildTabs(), - const SizedBox(height: 24), - _buildPodium(topThree), - const SizedBox(height: 24), - if (myRank > 0) ...[ - _buildMyRank(myRank), - const SizedBox(height: 16), - ], - _buildRestList(rest, 4), // Starting rank 4 - ], - ), - ), - ); - } - - Widget _buildTabs() { - final tabs = ['weekly', 'monthly', 'all-time']; - return Container( - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - color: const Color(0xFFE3E6E9), - borderRadius: BorderRadius.circular(8), - ), - child: Row( - children: tabs.map((tab) { - final isActive = _activeTab == tab; - return Expanded( - child: GestureDetector( - onTap: () => setState(() => _activeTab = tab), - child: Container( - padding: const EdgeInsets.symmetric(vertical: 8), - alignment: Alignment.center, - decoration: BoxDecoration( - color: isActive ? Colors.white : Colors.transparent, - borderRadius: BorderRadius.circular(6), - ), - child: Text( - tab[0].toUpperCase() + tab.substring(1), - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: isActive - ? const Color(0xFF121826) - : const Color(0xFF6A7382), - ), - ), - ), - ), - ); - }).toList(), - ), - ); - } - - Widget _buildPodium(List> topThree) { - if (topThree.isEmpty) return const SizedBox.shrink(); - - return SizedBox( - height: 300, // Increased height to prevent overflow - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // 2nd Place (Left) - if (topThree.length > 1) - Expanded( - child: _buildPodiumItem( - topThree[1], - 2, - const Color(0xFFC0C0C0), - 160, - ), - ), - - // 1st Place (Center - Taller) - Expanded( - child: _buildPodiumItem( - topThree[0], - 1, - const Color(0xFFF9E547), - 200, - ), - ), // Yellow/Gold - // 3rd Place (Right) - if (topThree.length > 2) - Expanded( - child: _buildPodiumItem( - topThree[2], - 3, - const Color(0xFFCD7F32), - 140, - ), - ), // Bronze - ], - ), - ); - } - - Widget _buildPodiumItem( - Map profile, - int rank, - Color color, - double height, - ) { - // Height determines the stand height + avatar space. - // The visual in React has a stand. - - // React styles: - // 2nd: Avatar border #C0C0C0, bg #C0C0C020, stand #C0C0C030 - // 1st: Avatar border accent (#F9E547), stand accent30 - // 3rd: Avatar border #CD7F32, stand #CD7F3220 - - final Color standColor = color.withOpacity(0.2); // approx - final String firstName = profile['fullName'].split(' ')[0]; - - return Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - if (rank == 1) - Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Icon(LucideIcons.trophy, color: color, size: 32), - ) - else - Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Icon(LucideIcons.medal, color: color, size: 24), - ), - - Container( - width: rank == 1 ? 80 : 64, - height: rank == 1 ? 80 : 64, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all(color: color, width: 3), - image: profile['photoUrl'] != null - ? DecorationImage( - image: NetworkImage(profile['photoUrl']), - fit: BoxFit.cover, - ) - : null, - color: standColor, - ), - child: profile['photoUrl'] == null - ? Center( - child: Text( - firstName[0], - style: TextStyle( - fontSize: rank == 1 ? 32 : 24, - fontWeight: FontWeight.bold, - color: const Color(0xFF6A7382), // Muted text for fallback - ), - ), - ) - : null, - ), - const SizedBox(height: 8), - Text( - firstName, - style: const TextStyle( - fontWeight: FontWeight.w600, - fontSize: 14, - color: Color(0xFF121826), - ), - ), - Text( - '${profile['xp']} XP', - style: const TextStyle(fontSize: 12, color: Color(0xFF6A7382)), - ), - const SizedBox(height: 8), - Container( - width: 64, - height: rank == 1 ? 96 : (rank == 2 ? 64 : 48), // stand height - decoration: BoxDecoration( - color: standColor, - borderRadius: const BorderRadius.vertical(top: Radius.circular(8)), - ), - ), - ], - ); - } - - Widget _buildMyRank(int rank) { - // React style: bg primary10 (#0A39DF1A), border primary30 - const primary = Color(0xFF0A39DF); - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(12), - border: Border.all(color: primary.withOpacity(0.3)), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text( - '#$rank', - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: primary, - ), - ), - const SizedBox(width: 12), - const Text( - 'Your Rank', - style: TextStyle( - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - ), - ], - ), - const Row( - children: [ - Icon(LucideIcons.trendingUp, size: 16, color: primary), - SizedBox(width: 4), - Text( - '+5', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: primary, - ), - ), - ], - ), - ], - ), - ); - } - - Widget _buildRestList(List> rest, int startRank) { - return Column( - children: rest.asMap().entries.map((entry) { - final index = entry.key; - final profile = entry.value; - final rank = startRank + index; - - return Container( - margin: const EdgeInsets.only(bottom: 8), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: Row( - children: [ - SizedBox( - width: 32, - child: Text( - '#$rank', - textAlign: TextAlign.center, - style: const TextStyle( - fontWeight: FontWeight.w600, - color: Color(0xFF6A7382), - ), - ), - ), - const SizedBox(width: 12), - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: const Color(0xFF0A39DF).withOpacity(0.1), - image: profile['photoUrl'] != null - ? DecorationImage( - image: NetworkImage(profile['photoUrl']), - fit: BoxFit.cover, - ) - : null, - ), - child: profile['photoUrl'] == null - ? Center( - child: Text( - profile['fullName'][0], - style: const TextStyle( - fontWeight: FontWeight.bold, - color: Color(0xFF0A39DF), - ), - ), - ) - : null, - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - profile['fullName'], - style: const TextStyle( - fontWeight: FontWeight.w500, - fontSize: 14, - color: Color(0xFF121826), - ), - ), - Text( - profile['level'], - style: const TextStyle( - fontSize: 12, - color: Color(0xFF6A7382), - ), - ), - ], - ), - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(4), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: Row( - children: [ - const Icon( - LucideIcons.star, - size: 12, - color: Color(0xFFEAB308), - ), // Amber for star - const SizedBox(width: 4), - Text( - '${profile['xp']} XP', - style: const TextStyle( - fontSize: 12, - color: Color(0xFF121826), - ), - ), - ], - ), - ), - ], - ), - ); - }).toList(), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/level_up/trainings_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/level_up/trainings_screen.dart deleted file mode 100644 index cb3423c6..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/level_up/trainings_screen.dart +++ /dev/null @@ -1,329 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import '../../../../theme.dart'; - -class TrainingsScreen extends ConsumerStatefulWidget { - const TrainingsScreen({super.key}); - - @override - ConsumerState createState() => _TrainingsScreenState(); -} - -class _TrainingsScreenState extends ConsumerState { - // Mock Data - final List> _courses = [ - { - 'id': '1', - 'title': 'Introduction to Food Safety', - 'description': 'Learn the basics of food handling and safety protocols.', - 'durationMinutes': 30, - 'xpReward': 100, - 'thumbnailUrl': null, // Use default icon - 'progressPercent': 100, - 'completed': true, - }, - { - 'id': '2', - 'title': 'Advanced Customer Service', - 'description': 'Master the art of hospitality and guest satisfaction.', - 'durationMinutes': 45, - 'xpReward': 150, - 'thumbnailUrl': null, - 'progressPercent': 45, - 'completed': false, - }, - { - 'id': '3', - 'title': 'Warehouse Safety Standards', - 'description': 'Comprehensive guide to warehouse safety.', - 'durationMinutes': 60, - 'xpReward': 200, - 'thumbnailUrl': null, - 'progressPercent': 0, - 'completed': false, - }, - ]; - - @override - Widget build(BuildContext context) { - // Calculate stats - final int completedCount = _courses.where((c) => c['completed']).length; - final int inProgressCount = _courses - .where((c) => !c['completed'] && (c['progressPercent'] as int) > 0) - .length; - final int totalXp = _courses - .where((c) => c['completed']) - .fold(0, (sum, c) => sum + (c['xpReward'] as int)); - - return Scaffold( - backgroundColor: const Color(0xFFFAFBFC), - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.chevronLeft, color: Color(0xFF6A7382)), - onPressed: () => context.pop(), - ), - title: const Text( - 'Trainings', - style: TextStyle( - color: Color(0xFF121826), - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1.0), - child: Container(color: const Color(0xFFE3E6E9), height: 1.0), - ), - ), - body: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 24), - child: Column( - children: [ - _buildStatsRow(completedCount, inProgressCount, totalXp), - const SizedBox(height: 24), - _buildCourseList(), - ], - ), - ), - ); - } - - Widget _buildStatsRow(int completed, int inProgress, int xp) { - return Row( - children: [ - Expanded( - child: _buildStatCard( - completed.toString(), - 'Completed', - const Color(0xFF0A39DF), - ), - ), - const SizedBox(width: 12), - Expanded( - child: _buildStatCard( - inProgress.toString(), - 'In Progress', - const Color(0xFF121826), - ), - ), - const SizedBox(width: 12), - Expanded( - child: _buildStatCard( - xp.toString(), - 'XP Earned', - const Color(0xFFF9E547), - ), - ), // Note: yellow text might be hard to read on white? React uses this color for text. - ], - ); - } - - Widget _buildStatCard(String value, String label, Color valueColor) { - // In React: F9E547 is yellow. On white bg it is low contrast. - // However, the prompt asks to match React UI. - // The React code uses `colors.accent` for XP value which is #F9E547. - // I will stick to it, maybe add a slight shadow or darker shade if it's invisible. - // Actually, for better visibility, I might use a slightly darker yellow/gold for text if needed, - // but the prompt says "Match every visible component exactly". I'll use the hex provided. - - // React code: - //
- - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: Column( - children: [ - Text( - value, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: valueColor == const Color(0xFFF9E547) - ? const Color(0xFFEAB308) - : valueColor, // Adjusted yellow to readable gold - ), - ), - const SizedBox(height: 4), - Text( - label, - style: const TextStyle(fontSize: 12, color: Color(0xFF6A7382)), - ), - ], - ), - ); - } - - Widget _buildCourseList() { - if (_courses.isEmpty) { - return const Center( - child: Padding( - padding: EdgeInsets.symmetric(vertical: 48), - child: Column( - children: [ - Icon(LucideIcons.award, size: 48, color: Color(0xFF6A7382)), - SizedBox(height: 12), - Text( - 'No trainings available yet', - style: TextStyle(color: Color(0xFF6A7382)), - ), - ], - ), - ), - ); - } - - return Column( - children: _courses.map((course) { - final bool isCompleted = course['completed']; - final int progressPercent = course['progressPercent']; - - return Container( - margin: const EdgeInsets.only(bottom: 12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - clipBehavior: Clip.hardEdge, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, // Align to top - children: [ - // Thumbnail area - Container( - width: 96, - height: - 120, // height needs to be sufficient to cover the card content or fixed - // React uses flex with h-24 w-24 (96px). - // But the card might be taller if description is long. - // I'll make it fixed width, and height matching parent via IntrinsicHeight if needed, - // or just fixed height since content is short. - // Let's use a fixed height for consistency or aspect ratio. - color: const Color( - 0xFF0A39DF, - ).withOpacity(0.06), // primary + alpha - child: Center( - child: course['thumbnailUrl'] != null - ? Image.network( - course['thumbnailUrl'], - fit: BoxFit.cover, - ) - : const Icon( - LucideIcons.play, - size: 32, - color: Color(0xFF0A39DF), - ), - ), - ), - - // Content - Expanded( - child: Padding( - padding: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - course['title'], - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - if (isCompleted) - const Icon( - LucideIcons.checkCircle, - size: 20, - color: Color(0xFF22C55E), - ), // Green-500 - ], - ), - const SizedBox(height: 4), - Text( - course['description'], - style: const TextStyle( - fontSize: 12, - color: Color(0xFF6A7382), - ), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - const SizedBox(height: 8), - Row( - children: [ - const Icon( - LucideIcons.clock, - size: 12, - color: Color(0xFF6A7382), - ), - const SizedBox(width: 4), - Text( - '${course['durationMinutes']} min', - style: const TextStyle( - fontSize: 12, - color: Color(0xFF6A7382), - ), - ), - const SizedBox(width: 8), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 4, - vertical: 0, - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(4), - border: Border.all( - color: const Color(0xFFF9E547), - ), - ), - child: Text( - '+${course['xpReward']} XP', - style: const TextStyle( - fontSize: 10, - color: Color(0xFF121826), - ), - ), - ), - ], - ), - if (progressPercent > 0 && !isCompleted) ...[ - const SizedBox(height: 8), - ClipRRect( - borderRadius: BorderRadius.circular(2), - child: LinearProgressIndicator( - value: progressPercent / 100, - minHeight: 4, - backgroundColor: const Color(0xFFE3E6E9), - valueColor: const AlwaysStoppedAnimation( - Color(0xFF0A39DF), - ), - ), - ), - ], - ], - ), - ), - ), - ], - ), - ); - }).toList(), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/attire_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/attire_screen.dart deleted file mode 100644 index 9f218dc5..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/attire_screen.dart +++ /dev/null @@ -1,567 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import '../../../../theme.dart'; - -class AttireScreen extends ConsumerStatefulWidget { - const AttireScreen({super.key}); - - @override - ConsumerState createState() => _AttireScreenState(); -} - -class _AttireScreenState extends ConsumerState { - // Mock Data matching React - final List> _attireOptions = [ - { - 'id': 'non_slip_shoes', - 'label': 'Non Slip Shoes', - 'icon': LucideIcons.footprints, - 'imageUrl': 'https://i.ebayimg.com/images/g/8N8AAOSwmkhgalWb/s-l1200.jpg', - }, - { - 'id': 'blue_jeans', - 'label': 'Blue Jeans', - 'icon': LucideIcons.scissors, - 'imageUrl': - 'https://www.gerberchildrenswear.com/cdn/shop/files/Gerber_1-pack-baby-neutral-blue-straight-fit-jeans-evyr-d_image_1.jpg?v=1721762942&width=1920', - }, - { - 'id': 'black_pants', - 'label': 'Black Pants', - 'icon': LucideIcons.user, - 'imageUrl': - 'https://media.gq.com/photos/5d1a2c8185896900081d0462/3:4/w_748%2Cc_limit/GQ-black-pants-stella-3x2.jpg', - }, - { - 'id': 'white_polo', - 'label': 'White Polo', - 'icon': LucideIcons.shirt, - 'imageUrl': - 'https://images.unsplash.com/photo-1581655353564-df123a1eb820?q=80&w=300&auto=format&fit=crop', - }, - { - 'id': 'black_socks', - 'label': 'Black Socks', - 'icon': LucideIcons.footprints, - 'imageUrl': - 'https://cdn.shopify.com/s/files/1/0472/6493/products/Everyday-Sock-Black-IMG_0408_fb623806-8c31-4627-8816-840fec9c1bde.jpg?v=1681767074&width=1500', - }, - { - 'id': 'catering_shirt', - 'label': 'Catering Shirt', - 'icon': LucideIcons.shirt, - 'imageUrl': - 'https://images.unsplash.com/photo-1618354691373-d851c5c3a990?q=80&w=300&auto=format&fit=crop', - }, - { - 'id': 'banquette', - 'label': 'Banquette', - 'icon': LucideIcons.shirt, - 'imageUrl': - 'https://images.unsplash.com/photo-1594938298603-c8148c4dae35?q=80&w=300&auto=format&fit=crop', - }, - { - 'id': 'black_cap', - 'label': 'Black Cap', - 'icon': LucideIcons.hardHat, - 'imageUrl': - 'https://www.stormtech.ca/cdn/shop/products/FPX-2-04000000-FRONT.jpg?v=1736187261&width=2400', - }, - { - 'id': 'chef_coat', - 'label': 'Chef Coat', - 'icon': LucideIcons.chefHat, - 'imageUrl': 'https://cdn.4imprint.ca/prod/extras/144601/515360/700/1.jpg', - }, - { - 'id': 'black_button_up', - 'label': 'Black Button Up', - 'icon': LucideIcons.shirt, - 'imageUrl': - 'https://cdn-images.farfetch-contents.com/17/05/87/96/17058796_34657384_600.jpg', - }, - { - 'id': 'black_polo', - 'label': 'Black Polo', - 'icon': LucideIcons.shirt, - 'imageUrl': - 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTD_67YJX5fnZB5Qy1mATbHhQUVo96CryuMwA&s', - }, - { - 'id': 'all_black_bistro', - 'label': 'All Black Bistro', - 'icon': LucideIcons.shirt, - 'imageUrl': - 'https://cdnimg.webstaurantstore.com/images/products/large/740190/2526926.jpg', - }, - { - 'id': 'white_button_up', - 'label': 'White Button Up', - 'icon': LucideIcons.shirt, - 'imageUrl': - 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTP_Vlx2e44njSqec58u0Qn3qDnWxRK6fYQvg&s', - }, - { - 'id': 'white_black_bistro', - 'label': 'White and Black Bistro', - 'icon': LucideIcons.shirt, - 'imageUrl': - 'https://cdnimg.webstaurantstore.com/images/products/large/740190/2526926.jpg', - }, - ]; - - // Mock mandatory items (e.g. for Server) - final List _mandatoryItems = [ - 'non_slip_shoes', - 'black_pants', - 'white_button_up', - 'black_socks', - ]; - - final List _selectedAttire = []; - final Map _attirePhotos = {}; // id -> url - final Map _uploading = {}; - bool _attestationChecked = false; - - @override - void initState() { - super.initState(); - // Pre-select mandatory - _selectedAttire.addAll(_mandatoryItems); - } - - void _toggleAttire(String id) { - if (_mandatoryItems.contains(id)) return; - setState(() { - if (_selectedAttire.contains(id)) { - _selectedAttire.remove(id); - } else { - _selectedAttire.add(id); - } - }); - } - - void _handlePhotoUpload(String id) async { - setState(() => _uploading[id] = true); - // Simulate upload - await Future.delayed(const Duration(seconds: 1)); - if (mounted) { - setState(() { - _uploading[id] = false; - _attirePhotos[id] = 'mock_url'; // Mocked - if (!_selectedAttire.contains(id)) { - _selectedAttire.add(id); - } - }); - } - } - - @override - Widget build(BuildContext context) { - final allMandatorySelected = _mandatoryItems.every( - (id) => _selectedAttire.contains(id), - ); - final allMandatoryHavePhotos = _mandatoryItems.every( - (id) => _attirePhotos.containsKey(id), - ); - final canSave = - allMandatorySelected && allMandatoryHavePhotos && _attestationChecked; - - return Scaffold( - backgroundColor: const Color(0xFFFAFBFC), - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.chevronLeft, color: Color(0xFF6A7382)), - onPressed: () => context.pop(), - ), - title: const Text( - 'Attire', - style: TextStyle( - color: Color(0xFF121826), - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1.0), - child: Container(color: const Color(0xFFE3E6E9), height: 1.0), - ), - ), - body: Column( - children: [ - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - _buildInfoCard(), - const SizedBox(height: 24), - _buildAttireGrid(), - const SizedBox(height: 24), - _buildAttestation(), - const SizedBox(height: 80), - ], - ), - ), - ), - _buildBottomBar( - canSave, - allMandatorySelected, - allMandatoryHavePhotos, - ), - ], - ), - ); - } - - Widget _buildInfoCard() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: AppColors.krowBlue.withOpacity(0.08), - borderRadius: BorderRadius.circular(8), - ), - child: const Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon(LucideIcons.shirt, color: AppColors.krowBlue, size: 24), - SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Your Wardrobe', - style: TextStyle( - fontWeight: FontWeight.w500, - fontSize: 14, - color: Color(0xFF121826), - ), - ), - SizedBox(height: 2), - Text( - 'Select the attire items you own. This helps us match you with shifts that fit your wardrobe.', - style: TextStyle(fontSize: 14, color: Color(0xFF6A7382)), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildAttireGrid() { - return GridView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 12, - mainAxisSpacing: 12, - childAspectRatio: 0.8, // Taller for photo upload button - ), - itemCount: _attireOptions.length, - itemBuilder: (context, index) { - final item = _attireOptions[index]; - final id = item['id'] as String; - final isSelected = _selectedAttire.contains(id); - final isMandatory = _mandatoryItems.contains(id); - final hasPhoto = _attirePhotos.containsKey(id); - final isUploading = _uploading[id] ?? false; - - return Container( - decoration: BoxDecoration( - color: isSelected - ? AppColors.krowBlue.withOpacity(0.1) - : Colors.transparent, - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: isSelected ? AppColors.krowBlue : const Color(0xFFE3E6E9), - width: 2, - ), - ), - child: Stack( - children: [ - if (isMandatory) - Positioned( - top: 8, - left: 8, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 6, - vertical: 2, - ), - decoration: BoxDecoration( - color: Colors.red, - borderRadius: BorderRadius.circular(4), - ), - child: const Text( - 'REQUIRED', - style: TextStyle( - color: Colors.white, - fontSize: 9, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - if (hasPhoto) - Positioned( - top: 8, - right: 8, - child: Container( - width: 20, - height: 20, - decoration: const BoxDecoration( - color: AppColors.krowBlue, - shape: BoxShape.circle, - ), - child: const Center( - child: Icon( - LucideIcons.check, - color: Colors.white, - size: 12, - ), - ), - ), - ), - - Padding( - padding: const EdgeInsets.all(12), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - GestureDetector( - onTap: () => _toggleAttire(id), - child: Column( - children: [ - item['imageUrl'] != null - ? Container( - height: 80, - width: 80, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - image: DecorationImage( - image: NetworkImage( - item['imageUrl'] as String, - ), - fit: BoxFit.cover, - ), - ), - ) - : Icon( - item['icon'] as IconData, - size: 48, - color: AppColors.krowCharcoal, - ), - const SizedBox(height: 8), - Text( - item['label'] as String, - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - ), - ], - ), - ), - const SizedBox(height: 12), - - // Upload Button - InkWell( - onTap: () => _handlePhotoUpload(id), - borderRadius: BorderRadius.circular(8), - child: Container( - padding: const EdgeInsets.symmetric( - vertical: 8, - horizontal: 12, - ), - decoration: BoxDecoration( - color: hasPhoto - ? AppColors.krowBlue.withOpacity(0.05) - : Colors.white, - border: Border.all( - color: hasPhoto - ? AppColors.krowBlue - : AppColors.krowBorder, - ), - borderRadius: BorderRadius.circular(8), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (isUploading) - const SizedBox( - width: 12, - height: 12, - child: CircularProgressIndicator( - strokeWidth: 2, - ), - ) - else if (hasPhoto) - const Icon( - LucideIcons.check, - size: 12, - color: AppColors.krowBlue, - ) - else - const Icon( - LucideIcons.camera, - size: 12, - color: AppColors.krowMuted, - ), - const SizedBox(width: 6), - Text( - isUploading - ? '...' - : hasPhoto - ? 'Added' - : 'Add Photo', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: hasPhoto - ? AppColors.krowBlue - : AppColors.krowMuted, - ), - ), - ], - ), - ), - ), - - if (hasPhoto) - const Padding( - padding: EdgeInsets.only(top: 4), - child: Text( - '⏳ Pending verification', - style: TextStyle( - fontSize: 10, - color: AppColors.krowMuted, - ), - ), - ), - ], - ), - ), - ], - ), - ); - }, - ); - } - - Widget _buildAttestation() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 24, - height: 24, - child: Checkbox( - value: _attestationChecked, - onChanged: (val) => setState(() => _attestationChecked = val!), - activeColor: AppColors.krowBlue, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4), - ), - ), - ), - const SizedBox(width: 12), - const Expanded( - child: Text( - 'I certify that I own these items and will wear them to my shifts. I understand that items are pending manager verification at my first shift.', - style: TextStyle(fontSize: 14, color: AppColors.krowCharcoal), - ), - ), - ], - ), - ); - } - - Widget _buildBottomBar( - bool canSave, - bool allMandatorySelected, - bool allMandatoryHavePhotos, - ) { - return Container( - padding: const EdgeInsets.all(20), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: Color(0xFFE3E6E9))), - ), - child: SafeArea( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - if (!canSave) - Padding( - padding: const EdgeInsets.only(bottom: 12), - child: Column( - children: [ - if (!allMandatorySelected) - const Text( - '✓ Select all required items', - style: TextStyle(fontSize: 12, color: Colors.red), - ), - if (!allMandatoryHavePhotos) - const Text( - '✓ Upload photos of required items', - style: TextStyle(fontSize: 12, color: Colors.red), - ), - if (!_attestationChecked) - const Text( - '✓ Accept attestation', - style: TextStyle(fontSize: 12, color: Colors.red), - ), - ], - ), - ), - SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: canSave - ? () { - // Save logic - context.pop(); - } - : null, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - disabledBackgroundColor: AppColors.krowMuted, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - elevation: 0, - ), - child: const Text( - 'Save Attire', - style: TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/emergency_contact_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/emergency_contact_screen.dart deleted file mode 100644 index efe9b11a..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/emergency_contact_screen.dart +++ /dev/null @@ -1,318 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import '../../../../theme.dart'; - -class EmergencyContactScreen extends ConsumerStatefulWidget { - const EmergencyContactScreen({super.key}); - - @override - ConsumerState createState() => - _EmergencyContactScreenState(); -} - -class _EmergencyContactScreenState - extends ConsumerState { - final List> _contacts = [ - {'name': '', 'phone': '', 'relationship': 'family'}, - ]; - - void _addContact() { - setState(() { - _contacts.add({'name': '', 'phone': '', 'relationship': 'family'}); - }); - } - - void _removeContact(int index) { - if (_contacts.length > 1) { - setState(() { - _contacts.removeAt(index); - }); - } - } - - void _updateContact(int index, String field, dynamic value) { - setState(() { - _contacts[index][field] = value; - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFFAFBFC), - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.chevronLeft, color: Color(0xFF6A7382)), - onPressed: () => context.pop(), - ), - title: const Text( - 'Emergency Contact', - style: TextStyle( - color: Color(0xFF121826), - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1.0), - child: Container(color: const Color(0xFFE3E6E9), height: 1.0), - ), - ), - body: Column( - children: [ - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - _buildInfoBanner(), - const SizedBox(height: 24), - ..._contacts.asMap().entries.map( - (entry) => _buildContactForm(entry.key, entry.value), - ), - _buildAddButton(), - const SizedBox(height: 80), - ], - ), - ), - ), - _buildSaveButton(), - ], - ), - ); - } - - Widget _buildInfoBanner() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFFF9E547).withOpacity(0.2), - borderRadius: BorderRadius.circular(8), - ), - child: const Text( - 'Please provide at least one emergency contact. This information will only be used in case of an emergency during your shifts.', - style: TextStyle(fontSize: 14, color: Color(0xFF121826)), - ), - ); - } - - Widget _buildContactForm(int index, Map contact) { - return Container( - margin: const EdgeInsets.only(bottom: 16), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Contact ${index + 1}', - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - ), - if (_contacts.length > 1) - IconButton( - icon: const Icon( - LucideIcons.trash2, - color: Colors.red, - size: 20, - ), - onPressed: () => _removeContact(index), - ), - ], - ), - const SizedBox(height: 16), - _buildLabel('Full Name'), - _buildTextField( - value: contact['name'], - hint: 'Contact name', - icon: LucideIcons.user, - onChanged: (val) => _updateContact(index, 'name', val), - ), - const SizedBox(height: 16), - _buildLabel('Phone Number'), - _buildTextField( - value: contact['phone'], - hint: '+1 (555) 000-0000', - icon: LucideIcons.phone, - onChanged: (val) => _updateContact(index, 'phone', val), - keyboardType: TextInputType.phone, - ), - const SizedBox(height: 16), - _buildLabel('Relationship'), - _buildDropdown( - value: contact['relationship'], - onChanged: (val) => _updateContact(index, 'relationship', val), - ), - ], - ), - ); - } - - Widget _buildLabel(String text) { - return Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Text( - text, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - ), - ); - } - - Widget _buildTextField({ - required String value, - required String hint, - required IconData icon, - required Function(String) onChanged, - TextInputType? keyboardType, - }) { - return TextField( - controller: TextEditingController(text: value) - ..selection = TextSelection.fromPosition( - TextPosition(offset: value.length), - ), - onChanged: onChanged, - keyboardType: keyboardType, - decoration: InputDecoration( - hintText: hint, - hintStyle: const TextStyle(color: Color(0xFF9CA3AF)), - prefixIcon: Icon(icon, color: const Color(0xFF6A7382), size: 20), - contentPadding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 12, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(6), - borderSide: const BorderSide(color: Color(0xFFE3E6E9)), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(6), - borderSide: const BorderSide(color: Color(0xFFE3E6E9)), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(6), - borderSide: const BorderSide(color: Color(0xFF0A39DF)), - ), - fillColor: Colors.white, - filled: true, - ), - ); - } - - Widget _buildDropdown({ - required String value, - required Function(String?) onChanged, - }) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(6), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: DropdownButtonHideUnderline( - child: DropdownButton( - value: value, - isExpanded: true, - items: const [ - DropdownMenuItem(value: 'family', child: Text('Family Member')), - DropdownMenuItem(value: 'spouse', child: Text('Spouse/Partner')), - DropdownMenuItem(value: 'friend', child: Text('Friend')), - DropdownMenuItem(value: 'other', child: Text('Other')), - ], - onChanged: onChanged, - ), - ), - ); - } - - Widget _buildAddButton() { - return SizedBox( - width: double.infinity, - height: 48, - child: OutlinedButton( - onPressed: _addContact, - style: OutlinedButton.styleFrom( - side: const BorderSide(color: Color(0xFF0A39DF)), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(LucideIcons.plus, color: Color(0xFF0A39DF), size: 20), - SizedBox(width: 8), - Text( - 'Add Another Contact', - style: TextStyle( - color: Color(0xFF0A39DF), - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - ], - ), - ), - ); - } - - Widget _buildSaveButton() { - return Container( - padding: const EdgeInsets.all(20), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: Color(0xFFE3E6E9))), - ), - child: SafeArea( - child: SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: () { - // Save logic - context.pop(); - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0A39DF), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - elevation: 0, - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(LucideIcons.save, color: Colors.white, size: 20), - SizedBox(width: 8), - Text( - 'Save Contacts', - style: TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/experience_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/experience_screen.dart deleted file mode 100644 index 23f8869c..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/experience_screen.dart +++ /dev/null @@ -1,371 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import '../../../../theme.dart'; - -class ExperienceScreen extends ConsumerStatefulWidget { - const ExperienceScreen({super.key}); - - @override - ConsumerState createState() => _ExperienceScreenState(); -} - -class _ExperienceScreenState extends ConsumerState { - // Mock Data - final List _industryOptions = [ - 'hospitality', - 'food_service', - 'warehouse', - 'events', - 'retail', - 'healthcare', - 'other', - ]; - - final List _skillOptions = [ - 'Food Service', - 'Bartending', - 'Event Setup', - 'Hospitality', - 'Warehouse', - 'Customer Service', - 'Cleaning', - 'Security', - 'Retail', - 'Cooking', - 'Cashier', - 'Server', - 'Barista', - 'Host/Hostess', - 'Busser', - ]; - - List _selectedIndustries = []; - List _selectedSkills = []; - final TextEditingController _customSkillController = TextEditingController(); - - void _toggleIndustry(String industry) { - setState(() { - if (_selectedIndustries.contains(industry)) { - _selectedIndustries.remove(industry); - } else { - _selectedIndustries.add(industry); - } - }); - } - - void _toggleSkill(String skill) { - setState(() { - if (_selectedSkills.contains(skill)) { - _selectedSkills.remove(skill); - } else { - _selectedSkills.add(skill); - } - }); - } - - void _addCustomSkill() { - final skill = _customSkillController.text.trim(); - if (skill.isNotEmpty && !_selectedSkills.contains(skill)) { - setState(() { - _selectedSkills.add(skill); - _customSkillController.clear(); - }); - } - } - - @override - void dispose() { - _customSkillController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFFAFBFC), - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.chevronLeft, color: Color(0xFF6A7382)), - onPressed: () => context.pop(), - ), - title: const Text( - 'Experience & Skills', - style: TextStyle( - color: Color(0xFF121826), - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1.0), - child: Container(color: const Color(0xFFE3E6E9), height: 1.0), - ), - ), - body: Column( - children: [ - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildSectionTitle('Industries'), - const Text( - 'Select the industries you have experience in', - style: TextStyle(fontSize: 14, color: Color(0xFF6A7382)), - ), - const SizedBox(height: 12), - Wrap( - spacing: 8, - runSpacing: 8, - children: _industryOptions - .map( - (i) => _buildBadge( - i, - _selectedIndustries.contains(i), - () => _toggleIndustry(i), - isIndustry: true, - ), - ) - .toList(), - ), - const SizedBox(height: 24), - _buildSectionTitle('Skills'), - const Text( - 'Select your skills or add custom ones', - style: TextStyle(fontSize: 14, color: Color(0xFF6A7382)), - ), - const SizedBox(height: 12), - Wrap( - spacing: 8, - runSpacing: 8, - children: _skillOptions - .map( - (s) => _buildBadge( - s, - _selectedSkills.contains(s), - () => _toggleSkill(s), - ), - ) - .toList(), - ), - const SizedBox(height: 16), - _buildCustomSkillInput(), - const SizedBox(height: 16), - if (_selectedSkills.any((s) => !_skillOptions.contains(s))) - _buildCustomSkillsList(), - const SizedBox(height: 80), - ], - ), - ), - ), - _buildSaveButton(), - ], - ), - ); - } - - Widget _buildSectionTitle(String title) { - return Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Text( - title, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF121826), - ), - ), - ); - } - - Widget _buildBadge( - String label, - bool isSelected, - VoidCallback onTap, { - bool isIndustry = false, - }) { - final displayLabel = isIndustry - ? label - .replaceAll('_', ' ') - .replaceFirst(label[0], label[0].toUpperCase()) - : label; // Simple capitalize for industry - - return GestureDetector( - onTap: onTap, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - decoration: BoxDecoration( - color: isSelected ? const Color(0xFF0A39DF) : Colors.transparent, - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: isSelected - ? const Color(0xFF0A39DF) - : const Color(0xFFE3E6E9), - ), - ), - child: Text( - isIndustry - ? (displayLabel[0].toUpperCase() + displayLabel.substring(1)) - : displayLabel, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: isSelected ? Colors.white : const Color(0xFF6A7382), - ), - ), - ), - ); - } - - Widget _buildCustomSkillInput() { - return Row( - children: [ - Expanded( - child: TextField( - controller: _customSkillController, - onSubmitted: (_) => _addCustomSkill(), - decoration: InputDecoration( - hintText: 'Add custom skill...', - hintStyle: const TextStyle(color: Color(0xFF9CA3AF)), - contentPadding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 12, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(6), - borderSide: const BorderSide(color: Color(0xFFE3E6E9)), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(6), - borderSide: const BorderSide(color: Color(0xFFE3E6E9)), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(6), - borderSide: const BorderSide(color: Color(0xFF0A39DF)), - ), - fillColor: Colors.white, - filled: true, - ), - ), - ), - const SizedBox(width: 8), - InkWell( - onTap: _addCustomSkill, - child: Container( - width: 48, - height: 48, - decoration: BoxDecoration( - color: const Color(0xFF0A39DF), - borderRadius: BorderRadius.circular(6), - ), - child: const Center( - child: Icon(LucideIcons.plus, color: Colors.white), - ), - ), - ), - ], - ); - } - - Widget _buildCustomSkillsList() { - final customSkills = _selectedSkills - .where((s) => !_skillOptions.contains(s)) - .toList(); - if (customSkills.isEmpty) return const SizedBox.shrink(); - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Custom Skills:', - style: TextStyle(fontSize: 14, color: Color(0xFF6A7382)), - ), - const SizedBox(height: 8), - Wrap( - spacing: 8, - runSpacing: 8, - children: customSkills.map((skill) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - decoration: BoxDecoration( - color: const Color(0xFFF9E547), - borderRadius: BorderRadius.circular(20), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - skill, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - ), - const SizedBox(width: 4), - GestureDetector( - onTap: () => _toggleSkill(skill), - child: const Icon( - LucideIcons.x, - size: 14, - color: Color(0xFF121826), - ), - ), - ], - ), - ); - }).toList(), - ), - ], - ); - } - - Widget _buildSaveButton() { - return Container( - padding: const EdgeInsets.all(20), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: Color(0xFFE3E6E9))), - ), - child: SafeArea( - child: SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: () { - // Save logic - context.pop(); - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0A39DF), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - elevation: 0, - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(LucideIcons.save, color: Colors.white, size: 20), - SizedBox(width: 8), - Text( - 'Save Experience', - style: TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/personal_info_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/personal_info_screen.dart deleted file mode 100644 index 499656d7..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/onboarding/personal_info_screen.dart +++ /dev/null @@ -1,334 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import '../../../../theme.dart'; - -class PersonalInfoScreen extends ConsumerStatefulWidget { - const PersonalInfoScreen({super.key}); - - @override - ConsumerState createState() => _PersonalInfoScreenState(); -} - -class _PersonalInfoScreenState extends ConsumerState { - // Mock User Data - final Map _user = { - 'id': 't8P3fYh4y1cPoZbbVPXUhfQCsDo3', - 'fullName': 'Krower', - 'email': 'worker@krow.com', - 'photoUrl': null, - 'userRole': 'staff', - }; - - final Map _staff= { - 'id': '93673c8f-91aa-405d-8647-f1aac29cc19b', - 'userId': 't8P3fYh4y1cPoZbbVPXUhfQCsDo3', - 'fullName': 'Krower', - 'level': 'Krower I', - 'totalShifts': 0, - 'averageRating': 5.0, - 'onTimeRate': 100, - 'noShowCount': 0, - 'cancellationCount': 0, - 'reliabilityScore': 100, - 'phone': '555-123-4567', // Mock for hasPersonalInfo - 'skills': [], // Mock for hasExperience - 'emergencyContacts': [], // Mock for hasEmergencyContact - 'bio': 'Experienced warehouse staff with a passion for hospitality and a keen eye for detail. Always ready for a new challenge!', - 'preferredLocations': ['Montreal', 'Quebec City'], - 'maxDistanceMiles': 25, - 'industries': [], - 'languages': ['English', 'Spanish'], - 'vendorId': '93678f7v-01aa-505d-9647-g1aac29cc123', - }; - - // Form State - late TextEditingController _phoneController; - late TextEditingController _bioController; - late TextEditingController _languagesController; - late TextEditingController _locationsController; - - @override - void initState() { - super.initState(); - _phoneController = TextEditingController(text: ''); - _bioController = TextEditingController(text: ''); - _languagesController = TextEditingController(text: ''); - _locationsController = TextEditingController(text: ''); - } - - @override - void dispose() { - _phoneController.dispose(); - _bioController.dispose(); - _languagesController.dispose(); - _locationsController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFFAFBFC), - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.chevronLeft, color: Color(0xFF6A7382)), - onPressed: () => context.pop(), - ), - title: const Text( - 'Personal Info', - style: TextStyle( - color: Color(0xFF121826), - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1.0), - child: Container(color: const Color(0xFFE3E6E9), height: 1.0), - ), - ), - body: Column( - children: [ - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - _buildProfilePhoto(), - const SizedBox(height: 24), - _buildFormFields(), - const SizedBox(height: 80), // Space for bottom button - ], - ), - ), - ), - _buildSaveButton(), - ], - ), - ); - } - - Widget _buildProfilePhoto() { - return Column( - children: [ - Stack( - children: [ - Container( - width: 96, - height: 96, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: const Color(0xFF0A39DF).withOpacity(0.1), - ), - child: _user['photoUrl'] != null - ? ClipOval( - child: Image.network( - _user['photoUrl'], - fit: BoxFit.cover, - ), - ) - : Center( - child: Text( - (_user['fullName'] as String)[0], - style: const TextStyle( - fontSize: 32, - fontWeight: FontWeight.bold, - color: Color(0xFF0A39DF), - ), - ), - ), - ), - Positioned( - bottom: 0, - right: 0, - child: Container( - width: 32, - height: 32, - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle, - border: Border.all(color: const Color(0xFFE3E6E9)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: const Center( - child: Icon( - LucideIcons.camera, - size: 16, - color: Color(0xFF0A39DF), - ), - ), - ), - ), - ], - ), - const SizedBox(height: 12), - const Text( - 'Tap to change photo', - style: TextStyle(fontSize: 14, color: Color(0xFF6A7382)), - ), - ], - ); - } - - Widget _buildFormFields() { - - _phoneController.text = (_staff['phone'] ?? '') as String; - _bioController.text = (_staff['bio'] ?? '') as String; - - final langs = _staff['languages']; - _languagesController.text =(langs is List) ? langs.join(', ') : (langs?.toString() ?? ''); - - final locs = _staff['preferredLocations']; - _locationsController.text = (locs is List) ? locs.join(', ') : (locs?.toString() ?? ''); - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildLabel('Full Name'), - _buildReadOnlyField(_user['fullName']), - const SizedBox(height: 16), - _buildLabel('Email'), - _buildReadOnlyField(_user['email']), - const SizedBox(height: 16), - _buildLabel('Phone Number'), - _buildTextField(_phoneController, '+1 (555) 000-0000'), - const SizedBox(height: 16), - _buildLabel('Bio'), - _buildTextField( - _bioController, - 'Tell clients about yourself...', - maxLines: 4, - ), - const SizedBox(height: 16), - _buildLabel('Languages'), - _buildTextField(_languagesController, 'English, Spanish, French...'), - const SizedBox(height: 16), - _buildLabel('Preferred Locations'), - _buildTextField(_locationsController, 'Downtown, Midtown, Brooklyn...'), - ], - ); - } - - Widget _buildLabel(String text) { - return Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Text( - text, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF121826), - ), - ), - ); - } - - Widget _buildReadOnlyField(String text) { - return Container( - width: double.infinity, - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), - decoration: BoxDecoration( - color: const Color(0xFFF9FAFB), - borderRadius: BorderRadius.circular(6), - border: Border.all(color: const Color(0xFFE3E6E9)), - ), - child: Text( - text, - style: const TextStyle(fontSize: 14, color: Color(0xFF121826)), - ), - ); - } - - Widget _buildTextField( - TextEditingController controller, - String hint, { - int maxLines = 1, - }) { - return TextField( - controller: controller, - maxLines: maxLines, - decoration: InputDecoration( - hintText: hint, - hintStyle: const TextStyle(color: Color(0xFF9CA3AF)), - contentPadding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 12, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(6), - borderSide: const BorderSide(color: Color(0xFFE3E6E9)), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(6), - borderSide: const BorderSide(color: Color(0xFFE3E6E9)), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(6), - borderSide: const BorderSide(color: Color(0xFF0A39DF)), - ), - fillColor: Colors.white, - filled: true, - ), - ); - } - - Widget _buildSaveButton() { - return Container( - padding: const EdgeInsets.all(20), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: Color(0xFFE3E6E9))), - ), - child: SafeArea( - child: SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: () { - // Save logic - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Personal info saved (Placeholder)'), - duration: Duration(seconds: 2), - ), - ); - context.pop(); - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0A39DF), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - elevation: 0, - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(LucideIcons.save, color: Colors.white, size: 20), - SizedBox(width: 8), - Text( - 'Save Changes', - style: TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/support/faqs_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/support/faqs_screen.dart deleted file mode 100644 index 46ef90cb..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/support/faqs_screen.dart +++ /dev/null @@ -1,319 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../../../theme.dart'; - -class FAQsScreen extends StatefulWidget { - const FAQsScreen({super.key}); - - @override - State createState() => _FAQsScreenState(); -} - -class _FAQsScreenState extends State { - final TextEditingController _searchController = TextEditingController(); - String _searchQuery = ''; - final Map _openItems = {}; - - final List> _faqData = [ - { - 'category': 'Getting Started', - 'questions': [ - { - 'q': 'How do I apply for shifts?', - 'a': - 'Browse available shifts on the Shifts tab and tap "Accept" on any shift that interests you. Once confirmed, you\'ll receive all the details you need.', - }, - { - 'q': 'How do I get paid?', - 'a': - 'Payments are processed weekly via direct deposit to your linked bank account. You can view your earnings in the Payments section.', - }, - { - 'q': 'What if I need to cancel a shift?', - 'a': - 'You can cancel a shift up to 24 hours before it starts without penalty. Late cancellations may affect your reliability score.', - }, - ], - }, - { - 'category': 'Shifts & Work', - 'questions': [ - { - 'q': 'How do I clock in?', - 'a': - 'Use the Clock In feature on the home screen when you arrive at your shift. Make sure location services are enabled for verification.', - }, - { - 'q': 'What should I wear?', - 'a': - 'Check the shift details for dress code requirements. You can manage your wardrobe in the Attire section of your profile.', - }, - { - 'q': 'Who do I contact if I\'m running late?', - 'a': - 'Use the "Running Late" feature in the app to notify the client. You can also message the shift manager directly.', - }, - ], - }, - { - 'category': 'Payments & Earnings', - 'questions': [ - { - 'q': 'When do I get paid?', - 'a': - 'Payments are processed every Friday for shifts completed the previous week. Funds typically arrive within 1-2 business days.', - }, - { - 'q': 'How do I update my bank account?', - 'a': - 'Go to Profile > Finance > Bank Account to add or update your banking information.', - }, - { - 'q': 'Where can I find my tax documents?', - 'a': - 'Tax documents (1099) are available in Profile > Compliance > Tax Documents by January 31st each year.', - }, - ], - }, - ]; - - @override - void dispose() { - _searchController.dispose(); - super.dispose(); - } - - void _toggleItem(String key) { - setState(() { - _openItems[key] = !(_openItems[key] ?? false); - }); - } - - @override - Widget build(BuildContext context) { - // Filter logic - final filteredFaqs = _faqData - .map((cat) { - final questions = (cat['questions'] as List).where((q) { - final question = (q['q'] as String).toLowerCase(); - final answer = (q['a'] as String).toLowerCase(); - final query = _searchQuery.toLowerCase(); - return question.contains(query) || answer.contains(query); - }).toList(); - return {'category': cat['category'], 'questions': questions}; - }) - .where((cat) => (cat['questions'] as List).isNotEmpty) - .toList(); - - return Scaffold( - backgroundColor: AppColors.krowBackground, - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: GestureDetector( - onTap: () => context.pop(), - child: const Icon( - LucideIcons.chevronLeft, - color: AppColors.krowMuted, - ), - ), - title: const Text( - "FAQs", - style: TextStyle( - color: AppColors.krowCharcoal, - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1), - child: Container(color: AppColors.krowBorder, height: 1), - ), - ), - body: Stack( - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 100), // Space for bottom bar - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - // Search - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - ), - child: TextField( - controller: _searchController, - onChanged: (val) => setState(() => _searchQuery = val), - decoration: const InputDecoration( - hintText: "Search questions...", - hintStyle: TextStyle(color: AppColors.krowMuted), - prefixIcon: Icon( - LucideIcons.search, - color: AppColors.krowMuted, - ), - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 12), - ), - ), - ), - const SizedBox(height: 24), - - // FAQ List - if (filteredFaqs.isEmpty) - const Padding( - padding: EdgeInsets.symmetric(vertical: 48), - child: Column( - children: [ - Icon( - LucideIcons.helpCircle, - size: 48, - color: AppColors.krowMuted, - ), - SizedBox(height: 12), - Text( - "No matching questions found", - style: TextStyle(color: AppColors.krowMuted), - ), - ], - ), - ) - else - ...filteredFaqs.asMap().entries.map((entry) { - final catIndex = entry.key; - final category = entry.value; - final questions = category['questions'] as List; - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - category['category'] as String, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 12), - ...questions.asMap().entries.map((qEntry) { - final qIndex = qEntry.key; - final item = qEntry.value; - final key = "$catIndex-$qIndex"; - final isOpen = _openItems[key] ?? false; - - return Container( - margin: const EdgeInsets.only(bottom: 8), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - children: [ - InkWell( - onTap: () => _toggleItem(key), - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Expanded( - child: Text( - item['q'], - style: const TextStyle( - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - ), - Icon( - isOpen - ? LucideIcons.chevronUp - : LucideIcons.chevronDown, - color: AppColors.krowMuted, - size: 20, - ), - ], - ), - ), - ), - if (isOpen) - Padding( - padding: const EdgeInsets.fromLTRB( - 16, - 0, - 16, - 16, - ), - child: Text( - item['a'], - style: const TextStyle( - color: AppColors.krowMuted, - fontSize: 14, - height: 1.5, - ), - ), - ), - ], - ), - ); - }).toList(), - const SizedBox(height: 12), - ], - ); - }).toList(), - ], - ), - ), - ), - Positioned( - left: 0, - right: 0, - bottom: 0, - child: Container( - padding: const EdgeInsets.all(20), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: AppColors.krowBorder)), - ), - child: SafeArea( - top: false, - child: SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: () => context.push('/messages'), - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - elevation: 0, - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(LucideIcons.messageCircle, size: 20), - SizedBox(width: 8), - Text( - "Contact Support", - style: TextStyle(fontWeight: FontWeight.w600), - ), - ], - ), - ), - ), - ), - ), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/support/messages_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/support/messages_screen.dart deleted file mode 100644 index 40b7d553..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/support/messages_screen.dart +++ /dev/null @@ -1,558 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../../../theme.dart'; - -class MessagesScreen extends StatefulWidget { - const MessagesScreen({super.key}); - - @override - State createState() => _MessagesScreenState(); -} - -class _MessagesScreenState extends State { - // Mock User - final String _userEmail = 'worker@krow.com'; - - // Mock Data - final List> _conversations = [ - { - 'senderId': 'manager@cafe.com', - 'senderName': 'Sarah Manager', - 'lastMessage': 'See you tomorrow!', - 'lastTime': DateTime.now().subtract(const Duration(hours: 2)), - 'unread': 2, - 'messages': [ - {'content': 'Hi there!', 'senderId': 'manager@cafe.com'}, - { - 'content': 'Are you available for a shift?', - 'senderId': 'manager@cafe.com', - }, - {'content': 'Yes, I am!', 'senderId': 'worker@krow.com'}, - {'content': 'See you tomorrow!', 'senderId': 'manager@cafe.com'}, - ], - }, - { - 'senderId': 'support@krow.com', - 'senderName': 'Krow Support', - 'lastMessage': 'Your payment has been processed.', - 'lastTime': DateTime.now().subtract(const Duration(days: 1)), - 'unread': 0, - 'messages': [ - {'content': 'Welcome to Krow!', 'senderId': 'support@krow.com'}, - { - 'content': 'Your payment has been processed.', - 'senderId': 'support@krow.com', - }, - ], - }, - ]; - - Map? _selectedChat; - final TextEditingController _messageController = TextEditingController(); - - @override - Widget build(BuildContext context) { - if (_selectedChat != null) { - return _buildChatView(); - } - return _buildConversationListView(); - } - - Widget _buildConversationListView() { - return Scaffold( - backgroundColor: Colors.white, - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: GestureDetector( - onTap: () => context.pop(), - child: Container( - margin: const EdgeInsets.all(8), - decoration: const BoxDecoration( - color: Color(0xFFF1F5F9), // slate-100 - shape: BoxShape.circle, - ), - alignment: Alignment.center, - child: const Icon( - LucideIcons.arrowLeft, - color: Color(0xFF475569), - size: 20, - ), // slate-600 - ), - ), - title: const Text( - "Messages", - style: TextStyle( - color: Color(0xFF0F172A), // slate-900 - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(60), - child: Padding( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 16), - child: Container( - height: 48, - decoration: BoxDecoration( - color: const Color(0xFFF8FAFC), // slate-50 - borderRadius: BorderRadius.circular(12), - ), - child: const TextField( - decoration: InputDecoration( - hintText: "Search conversations...", - hintStyle: TextStyle(color: Color(0xFF94A3B8)), // slate-400 - prefixIcon: Icon( - LucideIcons.search, - color: Color(0xFF94A3B8), - ), // slate-400 - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 12), - ), - ), - ), - ), - ), - ), - body: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Quick Actions - Row( - children: [ - _buildQuickAction( - LucideIcons.alertTriangle, - "Running Late", - const Color(0xFFFEE2E2), - const Color(0xFFDC2626), - ), - const SizedBox(width: 12), - _buildQuickAction( - LucideIcons.messageCircle, - "Chat Support", - const Color(0xFFE0E7FF), - const Color(0xFF0032A0), - ), - const SizedBox(width: 12), - _buildQuickAction( - LucideIcons.users, - "Group Chat", - const Color(0xFFFEF3C7), - const Color(0xFF333F48), - ), - ], - ), - const SizedBox(height: 24), - - // Recent Chats - const Text( - "Recent Chats", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - const SizedBox(height: 12), - - if (_conversations.isEmpty) - const Center( - child: Padding( - padding: EdgeInsets.symmetric(vertical: 48), - child: Column( - children: [ - Icon( - LucideIcons.messageCircle, - size: 48, - color: Color(0xFFCBD5E1), - ), // slate-300 - SizedBox(height: 12), - Text( - "No messages yet", - style: TextStyle(color: Color(0xFF64748B)), - ), // slate-500 - ], - ), - ), - ) - else - ..._conversations.map((conv) { - return GestureDetector( - onTap: () => setState(() => _selectedChat = conv), - child: Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: const Color(0xFFF1F5F9), - ), // slate-100 - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - ), - ], - ), - child: Row( - children: [ - CircleAvatar( - backgroundColor: const Color(0xFFE0E7FF), - radius: 24, - child: Text( - (conv['senderName'] as String)[0], - style: const TextStyle( - color: Color(0xFF0032A0), - fontWeight: FontWeight.bold, - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - conv['senderName'], - style: const TextStyle( - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - Text( - _formatDate(conv['lastTime'] as DateTime), - style: const TextStyle( - fontSize: 12, - color: Color(0xFF94A3B8), // slate-400 - ), - ), - ], - ), - const SizedBox(height: 4), - Row( - children: [ - Expanded( - child: Text( - conv['lastMessage'], - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontSize: 14, - color: Color(0xFF64748B), // slate-500 - ), - ), - ), - if ((conv['unread'] as int) > 0) - Container( - padding: const EdgeInsets.symmetric( - horizontal: 6, - vertical: 2, - ), - decoration: BoxDecoration( - color: const Color(0xFF0032A0), - borderRadius: BorderRadius.circular(10), - ), - child: Text( - "${conv['unread']}", - style: const TextStyle( - color: Colors.white, - fontSize: 10, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - ], - ), - ), - ], - ), - ), - ); - }).toList(), - - const SizedBox(height: 24), - // Krow Support Banner - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - const Color(0xFF0032A0).withOpacity(0.05), - const Color(0xFFF8E08E).withOpacity(0.2), - ], - ), - borderRadius: BorderRadius.circular(16), - ), - child: Row( - children: [ - Container( - width: 48, - height: 48, - decoration: BoxDecoration( - color: const Color(0xFF0032A0).withOpacity(0.1), - borderRadius: BorderRadius.circular(12), - ), - alignment: Alignment.center, - child: const Icon( - LucideIcons.headphones, - color: Color(0xFF0032A0), - ), - ), - const SizedBox(width: 12), - const Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Need Help?", - style: TextStyle( - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), - ), - ), - Text( - "Chat with KROW support 24/7", - style: TextStyle( - fontSize: 12, - color: Color(0xFF475569), - ), - ), - ], - ), - ), - const Icon( - LucideIcons.chevronRight, - color: Color(0xFF94A3B8), - ), - ], - ), - ), - ], - ), - ), - ); - } - - Widget _buildQuickAction( - IconData icon, - String label, - Color bgColor, - Color iconColor, - ) { - return Expanded( - child: Container( - height: 100, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: const Color(0xFFF1F5F9)), // slate-100 - boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 2), - ], - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration(color: bgColor, shape: BoxShape.circle), - alignment: Alignment.center, - child: Icon(icon, color: iconColor, size: 20), - ), - const SizedBox(height: 8), - Text( - label, - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 10, - fontWeight: FontWeight.w500, - color: Color(0xFF334155), // slate-700 - ), - ), - ], - ), - ), - ); - } - - Widget _buildChatView() { - final messages = _selectedChat!['messages'] as List; - - return Scaffold( - backgroundColor: Colors.white, - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.arrowLeft, color: Color(0xFF475569)), - onPressed: () => setState(() => _selectedChat = null), - ), - title: Row( - children: [ - CircleAvatar( - radius: 16, - backgroundColor: const Color(0xFFE0E7FF), - child: Text( - (_selectedChat!['senderName'] as String)[0], - style: const TextStyle( - fontSize: 12, - color: Color(0xFF0032A0), - fontWeight: FontWeight.bold, - ), - ), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - _selectedChat!['senderName'], - style: const TextStyle( - color: Color(0xFF0F172A), - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - const Text( - "Active now", - style: TextStyle(color: Color(0xFF64748B), fontSize: 12), - ), - ], - ), - ], - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1), - child: Container(color: const Color(0xFFF1F5F9), height: 1), - ), - ), - body: Column( - children: [ - Expanded( - child: ListView.builder( - padding: const EdgeInsets.all(20), - itemCount: messages.length, - itemBuilder: (context, index) { - final msg = messages[index]; - final isMe = msg['senderId'] == _userEmail; - return Align( - alignment: isMe - ? Alignment.centerRight - : Alignment.centerLeft, - child: Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 10, - ), - constraints: BoxConstraints( - maxWidth: MediaQuery.of(context).size.width * 0.75, - ), - decoration: BoxDecoration( - color: isMe - ? const Color(0xFF0032A0) - : const Color(0xFFF1F5F9), - borderRadius: BorderRadius.only( - topLeft: const Radius.circular(16), - topRight: const Radius.circular(16), - bottomLeft: isMe - ? const Radius.circular(16) - : Radius.zero, - bottomRight: isMe - ? Radius.zero - : const Radius.circular(16), - ), - ), - child: Text( - msg['content'], - style: TextStyle( - color: isMe ? Colors.white : const Color(0xFF0F172A), - fontSize: 14, - ), - ), - ), - ); - }, - ), - ), - Container( - padding: const EdgeInsets.all(16), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: Color(0xFFF1F5F9))), - ), - child: SafeArea( - top: false, - child: Row( - children: [ - Expanded( - child: Container( - height: 48, - decoration: BoxDecoration( - color: const Color(0xFFF8FAFC), - borderRadius: BorderRadius.circular(12), - ), - child: TextField( - controller: _messageController, - decoration: const InputDecoration( - hintText: "Type a message...", - hintStyle: TextStyle(color: Color(0xFF94A3B8)), - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 16), - ), - ), - ), - ), - const SizedBox(width: 8), - GestureDetector( - onTap: () { - if (_messageController.text.isNotEmpty) { - setState(() { - (_selectedChat!['messages'] as List).add({ - 'content': _messageController.text, - 'senderId': _userEmail, - }); - _messageController.clear(); - }); - } - }, - child: Container( - width: 48, - height: 48, - decoration: BoxDecoration( - color: const Color(0xFF0032A0), - borderRadius: BorderRadius.circular(12), - ), - alignment: Alignment.center, - child: const Icon( - LucideIcons.send, - color: Colors.white, - size: 20, - ), - ), - ), - ], - ), - ), - ), - ], - ), - ); - } - - String _formatDate(DateTime date) { - return "${date.month}/${date.day}/${date.year}"; - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/support/privacy_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/support/privacy_screen.dart deleted file mode 100644 index 89254c18..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile/support/privacy_screen.dart +++ /dev/null @@ -1,267 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../../../theme.dart'; - -class PrivacyScreen extends StatefulWidget { - const PrivacyScreen({super.key}); - - @override - State createState() => _PrivacyScreenState(); -} - -class _PrivacyScreenState extends State { - // Mock Settings State - bool _locationSharing = true; - bool _profileVisibility = true; - bool _pushNotifications = true; - bool _emailNotifications = true; - bool _smsNotifications = false; - bool _twoFactor = false; - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.krowBackground, - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: GestureDetector( - onTap: () => context.pop(), - child: const Icon( - LucideIcons.chevronLeft, - color: AppColors.krowMuted, - ), - ), - title: const Text( - "Privacy & Security", - style: TextStyle( - color: AppColors.krowCharcoal, - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1), - child: Container(color: AppColors.krowBorder, height: 1), - ), - ), - body: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - _buildSection( - title: "Privacy", - icon: LucideIcons.eye, - children: [ - _buildSwitchTile( - title: "Location Sharing", - subtitle: "Share location during shifts", - value: _locationSharing, - onChanged: (val) => setState(() => _locationSharing = val), - ), - _buildDivider(), - _buildSwitchTile( - title: "Profile Visibility", - subtitle: "Let clients see your profile", - value: _profileVisibility, - onChanged: (val) => setState(() => _profileVisibility = val), - ), - ], - ), - const SizedBox(height: 24), - _buildSection( - title: "Notifications", - icon: LucideIcons.bell, - children: [ - _buildSwitchTile( - title: "Push Notifications", - subtitle: "Receive push notifications", - value: _pushNotifications, - onChanged: (val) => setState(() => _pushNotifications = val), - ), - _buildDivider(), - _buildSwitchTile( - title: "Email Notifications", - subtitle: "Receive email updates", - value: _emailNotifications, - onChanged: (val) => setState(() => _emailNotifications = val), - ), - _buildDivider(), - _buildSwitchTile( - title: "SMS Notifications", - subtitle: "Receive text messages", - value: _smsNotifications, - onChanged: (val) => setState(() => _smsNotifications = val), - ), - ], - ), - const SizedBox(height: 24), - _buildSection( - title: "Security", - icon: LucideIcons.lock, - children: [ - _buildSwitchTile( - title: "Two-Factor Authentication", - subtitle: "Add extra security to your account", - value: _twoFactor, - onChanged: (val) => setState(() => _twoFactor = val), - ), - _buildDivider(), - _buildActionTile( - title: "Change Password", - subtitle: "Update your password", - onTap: () {}, - ), - _buildDivider(), - _buildActionTile( - title: "Active Sessions", - subtitle: "Manage logged in devices", - onTap: () {}, - ), - ], - ), - const SizedBox(height: 24), - _buildSection( - title: "Legal", - icon: LucideIcons.shield, - children: [ - _buildActionTile(title: "Terms of Service", onTap: () {}), - _buildDivider(), - _buildActionTile(title: "Privacy Policy", onTap: () {}), - _buildDivider(), - _buildActionTile(title: "Data Request", onTap: () {}), - ], - ), - ], - ), - ), - ); - } - - Widget _buildSection({ - required String title, - required IconData icon, - required List children, - }) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon(icon, size: 20, color: AppColors.krowBlue), - const SizedBox(width: 8), - Text( - title, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - const SizedBox(height: 12), - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column(children: children), - ), - ], - ); - } - - Widget _buildSwitchTile({ - required String title, - required String subtitle, - required bool value, - required ValueChanged onChanged, - }) { - return Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - Text( - subtitle, - style: const TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - Switch( - value: value, - onChanged: onChanged, - activeColor: AppColors.krowBlue, - ), - ], - ), - ); - } - - Widget _buildActionTile({ - required String title, - String? subtitle, - required VoidCallback onTap, - }) { - return InkWell( - onTap: onTap, - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - if (subtitle != null) - Text( - subtitle, - style: const TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - const Icon( - LucideIcons.chevronRight, - size: 20, - color: AppColors.krowMuted, - ), - ], - ), - ), - ); - } - - Widget _buildDivider() { - return const Divider(height: 1, color: AppColors.krowBorder); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile_screen.dart b/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile_screen.dart deleted file mode 100644 index 6f2456bd..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/screens/worker/worker_profile_screen.dart +++ /dev/null @@ -1,667 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; -import 'worker_profile/support/faqs_screen.dart'; -import 'worker_profile/support/privacy_screen.dart'; -import 'worker_profile/support/messages_screen.dart'; - -class WorkerProfileScreen extends StatefulWidget { - const WorkerProfileScreen({super.key}); - - @override - State createState() => _WorkerProfileScreenState(); -} - -class _WorkerProfileScreenState extends State { - // Mock Data - final Map _user = { - 'id': 't8P3fYh4y1cPoZbbVPXUhfQCsDo3', - 'fullName': 'Krower', - 'email': 'worker@krow.com', - 'photoUrl': null, - 'userRole': 'staff', - }; - - final Map _staff = { - 'id': '93673c8f-91aa-405d-8647-f1aac29cc19b', - 'userId': 't8P3fYh4y1cPoZbbVPXUhfQCsDo3', - 'fullName': 'Krower', - 'level': 'Krower I', - 'totalShifts': 0, - 'averageRating': 5.0, - 'onTimeRate': 100, - 'noShowCount': 0, - 'cancellationCount': 0, - 'reliabilityScore': 100, - 'phone': '555-123-4567', // Mock for hasPersonalInfo - 'skills': [], // Mock for hasExperience - 'emergencyContacts': [], // Mock for hasEmergencyContact - 'bio': - 'Experienced warehouse staff with a passion for hospitality and a keen eye for detail. Always ready for a new challenge!', - 'preferredLocations': ['Montreal', 'Quebec City'], - 'maxDistanceMiles': 25, - 'industries': [], - 'languages': ['English', 'Spanish'], - 'vendorId': '93678f7v-01aa-505d-9647-g1aac29cc123', - }; - - // Mock computed properties - bool get _hasPersonalInfo => _staff['phone'] != null; - bool get _hasEmergencyContact => false; - bool get _hasExperience => (_staff['skills'] as List).isNotEmpty; - bool get _hasAttire => false; - bool get _hasDocuments => true; - bool get _hasCertificates => false; - bool get _hasTaxForms => false; - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: SingleChildScrollView( - padding: const EdgeInsets.only(bottom: 100), - child: Column( - children: [ - _buildHeader(context), - Transform.translate( - offset: const Offset(0, -24), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - children: [ - _buildReliabilityStatsCard(), - const SizedBox(height: 24), - _buildReliabilityScoreBar(), - const SizedBox(height: 24), - _buildSectionTitle("Onboarding"), - _buildGrid( - crossAxisCount: 2, - childAspectRatio: 0.7, - children: [ - _buildGridItem( - LucideIcons.user, - "Personal Info", - completed: _hasPersonalInfo, - onTap: () => context.push('/personal-info'), - ), - _buildGridItem( - LucideIcons.phone, - "Emergency Contact", - completed: _hasEmergencyContact, - onTap: () => context.push('/emergency-contact'), - ), - _buildGridItem( - LucideIcons.briefcase, - "Experience", - completed: _hasExperience, - onTap: () => context.push('/experience'), - ), - _buildGridItem( - LucideIcons.shirt, - "Attire", - completed: _hasAttire, - onTap: () => context.push('/attire'), - ), - ], - ), - const SizedBox(height: 24), - _buildSectionTitle("Compliance"), - _buildGrid( - crossAxisCount: 3, - childAspectRatio: 0.9, - children: [ - _buildGridItem( - LucideIcons.fileText, - "Documents", - completed: _hasDocuments, - onTap: () => context.push('/documents'), - ), - _buildGridItem( - LucideIcons.award, - "Certificates", - completed: _hasCertificates, - onTap: () => context.push('/certificates'), - ), - _buildGridItem( - LucideIcons.fileText, - "Tax Forms", - completed: _hasTaxForms, - onTap: () => context.push('/tax-forms'), - ), - ], - ), - const SizedBox(height: 24), - _buildSectionTitle("Level Up"), - _buildGrid( - crossAxisCount: 3, - childAspectRatio: 0.9, - children: [ - _buildGridItem( - LucideIcons.graduationCap, - "Krow University", - onTap: () => context.push('/krow-university'), - ), - _buildGridItem( - LucideIcons.bookOpen, - "Trainings", - onTap: () => context.push('/trainings'), - ), - _buildGridItem( - LucideIcons.award, - "Leaderboard", - onTap: () => context.push('/leaderboard'), - ), - ], - ), - const SizedBox(height: 24), - _buildSectionTitle("Finance"), - _buildGrid( - crossAxisCount: 3, - childAspectRatio: 0.9, - children: [ - _buildGridItem( - LucideIcons.building2, - "Bank Account", - onTap: () => context.push('/bank-account'), - ), - _buildGridItem( - LucideIcons.creditCard, - "Payments", - onTap: () => context.go('/payments'), - ), - _buildGridItem( - LucideIcons.clock, - "Timecard", - onTap: () => context.push('/time-card'), - ), - ], - ), - const SizedBox(height: 24), - _buildSectionTitle("Support"), - _buildGrid( - crossAxisCount: 3, - childAspectRatio: 0.9, - children: [ - _buildGridItem( - LucideIcons.helpCircle, - "FAQs", - onTap: () => context.push('/faqs'), - ), - _buildGridItem( - LucideIcons.shield, - "Privacy & Security", - onTap: () => context.push('/privacy'), - ), - _buildGridItem( - LucideIcons.messageCircle, - "Messages", - onTap: () => context.push('/messages'), - ), - ], - ), - const SizedBox(height: 24), - _buildLogoutButton(), - ], - ), - ), - ), - ], - ), - ), - ); - } - - Widget _buildHeader(BuildContext context) { - return Container( - width: double.infinity, - padding: const EdgeInsets.fromLTRB(20, 20, 20, 64), - decoration: const BoxDecoration( - color: AppColors.krowBlue, - borderRadius: BorderRadius.vertical(bottom: Radius.circular(24)), - ), - child: SafeArea( - bottom: false, - child: Column( - children: [ - // Top Bar - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - "Profile", - style: TextStyle( - color: Colors.white, - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - GestureDetector( - onTap: () => context.go('/get-started'), - child: Text( - "SIGN OUT", - style: TextStyle( - color: Colors.white.withOpacity(0.8), - fontSize: 14, - fontWeight: FontWeight.w500, - ), - ), - ), - ], - ), - const SizedBox(height: 32), - // Avatar Section - Stack( - alignment: Alignment.bottomRight, - children: [ - Container( - width: 112, - height: 112, - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - shape: BoxShape.circle, - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - AppColors.krowYellow, - AppColors.krowYellow.withOpacity(0.5), - Colors.white, - ], - ), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.2), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: Colors.white.withOpacity(0.2), - width: 4, - ), - ), - child: CircleAvatar( - backgroundColor: Colors.white, - backgroundImage: _user['photoUrl'] != null - ? NetworkImage(_user['photoUrl']) - : null, - child: _user['photoUrl'] == null - ? Container( - width: double.infinity, - height: double.infinity, - decoration: BoxDecoration( - shape: BoxShape.circle, - gradient: const LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - AppColors.krowYellow, - Color(0xFFFFD700), - ], - ), - ), - alignment: Alignment.center, - child: Text( - (_user['fullName'] as String)[0], - style: const TextStyle( - fontSize: 48, - fontWeight: FontWeight.bold, - color: AppColors.krowBlue, - ), - ), - ) - : null, - ), - ), - ), - Container( - width: 36, - height: 36, - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle, - border: Border.all(color: AppColors.krowBlue, width: 2), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 4, - ), - ], - ), - child: const Icon( - LucideIcons.camera, - size: 16, - color: AppColors.krowBlue, - ), - ), - ], - ), - const SizedBox(height: 16), - Text( - _user['fullName'] ?? 'Krower', - style: const TextStyle( - color: Colors.white, - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 4), - Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: AppColors.krowYellow.withOpacity(0.2), - borderRadius: BorderRadius.circular(20), - ), - child: Text( - _staff['level'] ?? 'Krower I', - style: const TextStyle( - color: AppColors.krowYellow, - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - ], - ), - ), - ); - } - - Widget _buildReliabilityStatsCard() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 4, - offset: const Offset(0, 1), - ), - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _buildStatItem( - LucideIcons.briefcase, - "${_staff['totalShifts']}", - "Shifts", - ), - _buildStatItem( - LucideIcons.star, - "${_staff['averageRating'].toStringAsFixed(1)}", - "Rating", - ), - _buildStatItem( - LucideIcons.clock, - "${_staff['onTimeRate']}%", - "On Time", - ), - _buildStatItem( - LucideIcons.xCircle, - "${_staff['noShowCount']}", - "No Shows", - ), - _buildStatItem( - LucideIcons.ban, - "${_staff['cancellationCount']}", - "Cancel.", - ), - ], - ), - ); - } - - Widget _buildStatItem(IconData icon, String value, String label) { - return Expanded( - child: Column( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: AppColors.krowBlue.withOpacity(0.1), - borderRadius: BorderRadius.circular(8), - ), - alignment: Alignment.center, - child: Icon(icon, size: 20, color: AppColors.krowBlue), - ), - const SizedBox(height: 4), - Text( - value, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - FittedBox( - fit: BoxFit.scaleDown, - child: Text( - label, - style: const TextStyle(fontSize: 10, color: AppColors.krowMuted), - ), - ), - ], - ), - ); - } - - Widget _buildReliabilityScoreBar() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFFE8EEFF), - borderRadius: BorderRadius.circular(12), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - "Reliability Score", - style: TextStyle( - color: AppColors.krowBlue, - fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), - Text( - "${_staff['reliabilityScore']}%", - style: const TextStyle( - color: AppColors.krowBlue, - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 8), - ClipRRect( - borderRadius: BorderRadius.circular(4), - child: LinearProgressIndicator( - value: (_staff['reliabilityScore'] as int) / 100, - backgroundColor: Colors.white, - color: AppColors.krowBlue, - minHeight: 8, - ), - ), - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Text( - "Keep your score above 45% to continue picking up shifts.", - style: const TextStyle(color: AppColors.krowMuted, fontSize: 10), - ), - ), - ], - ), - ); - } - - Widget _buildSectionTitle(String title) { - return Container( - width: double.infinity, - padding: const EdgeInsets.only(left: 4), - margin: const EdgeInsets.only(bottom: 12), - child: Text( - title.toUpperCase(), - style: const TextStyle( - color: AppColors.krowMuted, - fontSize: 12, - fontWeight: FontWeight.w600, - letterSpacing: 0.5, - ), - ), - ); - } - - Widget _buildGrid({ - required int crossAxisCount, - required List children, - double childAspectRatio = 1.0, - }) { - return Wrap( - spacing: 12, - runSpacing: 12, - children: children.map((child) { - return SizedBox( - width: - (MediaQuery.of(context).size.width - - 40 - - (12 * (crossAxisCount - 1))) / - crossAxisCount, - child: child, - ); - }).toList(), - ); - } - - Widget _buildGridItem( - IconData icon, - String label, { - bool? completed, - VoidCallback? onTap, - }) { - return GestureDetector( - onTap: onTap, - child: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - padding: const EdgeInsets.all(6), - child: Stack( - children: [ - Align( - alignment: Alignment.center, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 48, - height: 48, - decoration: BoxDecoration( - color: AppColors.krowBlue.withOpacity(0.08), - borderRadius: BorderRadius.circular(12), - ), - alignment: Alignment.center, - child: Icon(icon, color: AppColors.krowBlue, size: 24), - ), - const SizedBox(height: 8), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Text( - label, - textAlign: TextAlign.center, - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: const TextStyle( - color: AppColors.krowCharcoal, - fontSize: 12, - fontWeight: FontWeight.w500, - height: 1.2, - ), - ), - ), - ], - ), - ), - if (completed != null) - Positioned( - top: 8, - right: 8, - child: Container( - width: 16, - height: 16, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: completed - ? AppColors.krowBlue - : const Color(0xFFE8EEFF), - ), - alignment: Alignment.center, - child: completed - ? const Icon(Icons.check, size: 10, color: Colors.white) - : const Text( - "!", - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: AppColors.krowBlue, - ), - ), - ), - ), - ], - ), - ), - ); - } - - Widget _buildLogoutButton() { - return Container( - width: double.infinity, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: () => context.go('/get-started'), - borderRadius: BorderRadius.circular(12), - child: const Padding( - padding: EdgeInsets.symmetric(vertical: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(LucideIcons.logOut, color: Colors.red, size: 20), - SizedBox(width: 8), - Text( - "Sign Out", - style: TextStyle( - color: Colors.red, - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/services/mock_service.dart b/apps/mobile/prototypes/staff_mobile_application/lib/services/mock_service.dart deleted file mode 100644 index f87b620c..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/services/mock_service.dart +++ /dev/null @@ -1,78 +0,0 @@ -import '../models/shift.dart'; - -class MockService { - static final Shift _sampleShift1 = Shift( - id: '1', - title: 'Line Cook', - clientName: 'The Burger Joint', - hourlyRate: 22.50, - location: 'Downtown, NY', - locationAddress: '123 Main St, New York, NY 10001', - date: DateTime.now().toIso8601String(), - startTime: '16:00', - endTime: '22:00', - createdDate: DateTime.now() - .subtract(const Duration(hours: 2)) - .toIso8601String(), - tipsAvailable: true, - mealProvided: true, - managers: [ShiftManager(name: 'John Doe', phone: '+1 555 0101')], - description: 'Help with dinner service. Must be experienced with grill.', - ); - - static final Shift _sampleShift2 = Shift( - id: '2', - title: 'Dishwasher', - clientName: 'Pasta Place', - hourlyRate: 18.00, - location: 'Brooklyn, NY', - locationAddress: '456 Bedford Ave, Brooklyn, NY 11211', - date: DateTime.now().add(const Duration(days: 1)).toIso8601String(), - startTime: '18:00', - endTime: '23:00', - createdDate: DateTime.now() - .subtract(const Duration(hours: 5)) - .toIso8601String(), - tipsAvailable: false, - mealProvided: true, - ); - - static final Shift _sampleShift3 = Shift( - id: '3', - title: 'Bartender', - clientName: 'Rooftop Bar', - hourlyRate: 25.00, - location: 'Manhattan, NY', - locationAddress: '789 5th Ave, New York, NY 10022', - date: DateTime.now().add(const Duration(days: 2)).toIso8601String(), - startTime: '19:00', - endTime: '02:00', - createdDate: DateTime.now() - .subtract(const Duration(hours: 1)) - .toIso8601String(), - tipsAvailable: true, - parkingAvailable: true, - description: 'High volume bar. Mixology experience required.', - ); - - Future> getTodayShifts() async { - await Future.delayed(const Duration(milliseconds: 500)); - return [_sampleShift1]; - } - - Future> getTomorrowShifts() async { - await Future.delayed(const Duration(milliseconds: 500)); - return [_sampleShift2]; - } - - Future> getRecommendedShifts() async { - await Future.delayed(const Duration(milliseconds: 500)); - return [_sampleShift3, _sampleShift1, _sampleShift2]; - } - - Future createWorkerProfile(Map data) async { - await Future.delayed(const Duration(seconds: 1)); - } -} - -final mockService = MockService(); diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/theme.dart b/apps/mobile/prototypes/staff_mobile_application/lib/theme.dart deleted file mode 100644 index 2e5291b1..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/theme.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; - -class AppColors { - static const Color krowBlue = Color(0xFF0A39DF); - static const Color krowYellow = Color(0xFFFFED4A); - static const Color krowCharcoal = Color(0xFF121826); - static const Color krowMuted = Color(0xFF6A7382); - static const Color krowBorder = Color(0xFFE3E6E9); - static const Color krowBackground = Color(0xFFFAFBFC); - - static const Color white = Colors.white; - static const Color black = Colors.black; -} - -class AppTheme { - static ThemeData get lightTheme { - return ThemeData( - useMaterial3: true, - scaffoldBackgroundColor: AppColors.krowBackground, - colorScheme: ColorScheme.fromSeed( - seedColor: AppColors.krowBlue, - primary: AppColors.krowBlue, - secondary: AppColors.krowYellow, - surface: AppColors.white, - background: AppColors.krowBackground, - ), - textTheme: GoogleFonts.instrumentSansTextTheme().apply( - bodyColor: AppColors.krowCharcoal, - displayColor: AppColors.krowCharcoal, - ), - appBarTheme: const AppBarTheme( - backgroundColor: AppColors.krowBackground, - elevation: 0, - iconTheme: IconThemeData(color: AppColors.krowCharcoal), - titleTextStyle: TextStyle( - color: AppColors.krowCharcoal, - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/attendance_card.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/attendance_card.dart deleted file mode 100644 index 6d150f2f..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/attendance_card.dart +++ /dev/null @@ -1,129 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; - -enum AttendanceType { checkin, checkout, breaks, days } - -class AttendanceCard extends StatelessWidget { - final AttendanceType type; - final String title; - final String value; - final String subtitle; - final String? scheduledTime; - - const AttendanceCard({ - super.key, - required this.type, - required this.title, - required this.value, - required this.subtitle, - this.scheduledTime, - }); - - @override - Widget build(BuildContext context) { - final styles = _getStyles(type); - - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: Colors.grey.shade100), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 36, - height: 36, - decoration: BoxDecoration( - color: styles.bgColor, - borderRadius: BorderRadius.circular(12), - ), - child: Icon(styles.icon, size: 16, color: styles.iconColor), - ), - const SizedBox(height: 12), - Text( - title, - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), // slate-500 - ), - ), - const SizedBox(height: 4), - Text( - value, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), // slate-900 - ), - ), - if (scheduledTime != null) ...[ - const SizedBox(height: 2), - Text( - "Scheduled: $scheduledTime", - style: const TextStyle( - fontSize: 10, - color: Color(0xFF94A3B8), // slate-400 - ), - ), - ], - const SizedBox(height: 2), - Text( - subtitle, - style: const TextStyle(fontSize: 12, color: Color(0xFF0032A0)), - ), - ], - ), - ); - } - - _AttendanceStyle _getStyles(AttendanceType type) { - switch (type) { - case AttendanceType.checkin: - return _AttendanceStyle( - icon: LucideIcons.logIn, - bgColor: const Color(0xFF0032A0).withOpacity(0.1), - iconColor: const Color(0xFF0032A0), - ); - case AttendanceType.checkout: - return _AttendanceStyle( - icon: LucideIcons.logOut, - bgColor: const Color(0xFF333F48).withOpacity(0.1), - iconColor: const Color(0xFF333F48), - ); - case AttendanceType.breaks: - return _AttendanceStyle( - icon: LucideIcons.coffee, - bgColor: const Color(0xFFF8E08E).withOpacity(0.3), - iconColor: const Color(0xFF333F48), - ); - case AttendanceType.days: - return _AttendanceStyle( - icon: LucideIcons.calendar, - bgColor: const Color(0xFFF7E600).withOpacity(0.2), - iconColor: const Color(0xFF333F48), - ); - } - } -} - -class _AttendanceStyle { - final IconData icon; - final Color bgColor; - final Color iconColor; - - _AttendanceStyle({ - required this.icon, - required this.bgColor, - required this.iconColor, - }); -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/commute_tracker.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/commute_tracker.dart deleted file mode 100644 index 96dc225c..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/commute_tracker.dart +++ /dev/null @@ -1,542 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; -import '../../models/shift.dart'; - -enum CommuteMode { - lockedNoShift, - needsConsent, - preShiftCommuteAllowed, - commuteModeActive, - arrivedCanClockIn, -} - -class CommuteTracker extends StatefulWidget { - final Shift? shift; - final Function(CommuteMode)? onModeChange; - final bool hasLocationConsent; - final bool isCommuteModeOn; - final double? distanceMeters; - final int? etaMinutes; - - const CommuteTracker({ - super.key, - this.shift, - this.onModeChange, - this.hasLocationConsent = false, - this.isCommuteModeOn = false, - this.distanceMeters, - this.etaMinutes, - }); - - @override - State createState() => _CommuteTrackerState(); -} - -class _CommuteTrackerState extends State { - bool _localHasConsent = false; - bool _localIsCommuteOn = false; - - @override - void initState() { - super.initState(); - _localHasConsent = widget.hasLocationConsent; - _localIsCommuteOn = widget.isCommuteModeOn; - } - - CommuteMode _getAppMode() { - if (widget.shift == null) return CommuteMode.lockedNoShift; - - // For demo purposes, check if we're within 24 hours of shift - final now = DateTime.now(); - final shiftStart = DateTime.parse( - '${widget.shift!.date} ${widget.shift!.startTime}', - ); - final hoursUntilShift = shiftStart.difference(now).inHours; - final inCommuteWindow = hoursUntilShift <= 24 && hoursUntilShift >= 0; - - if (_localIsCommuteOn) { - // Check if arrived (mock: if distance < 200m) - if (widget.distanceMeters != null && widget.distanceMeters! <= 200) { - return CommuteMode.arrivedCanClockIn; - } - return CommuteMode.commuteModeActive; - } - - if (inCommuteWindow) { - return _localHasConsent - ? CommuteMode.preShiftCommuteAllowed - : CommuteMode.needsConsent; - } - - return CommuteMode.lockedNoShift; - } - - String _formatDistance(double meters) { - final miles = meters / 1609.34; - return miles < 0.1 - ? '${meters.round()} m' - : '${miles.toStringAsFixed(1)} mi'; - } - - int _getMinutesUntilShift() { - if (widget.shift == null) return 0; - final now = DateTime.now(); - final shiftStart = DateTime.parse( - '${widget.shift!.date} ${widget.shift!.startTime}', - ); - return shiftStart.difference(now).inMinutes; - } - - @override - Widget build(BuildContext context) { - final mode = _getAppMode(); - - // Notify parent of mode change - WidgetsBinding.instance.addPostFrameCallback((_) { - widget.onModeChange?.call(mode); - }); - - switch (mode) { - case CommuteMode.lockedNoShift: - return const SizedBox.shrink(); - - case CommuteMode.needsConsent: - return _buildConsentCard(); - - case CommuteMode.preShiftCommuteAllowed: - return _buildPreShiftCard(); - - case CommuteMode.commuteModeActive: - return _buildActiveCommuteScreen(); - - case CommuteMode.arrivedCanClockIn: - return _buildArrivedCard(); - } - } - - Widget _buildConsentCard() { - return Container( - margin: const EdgeInsets.only(bottom: 20), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - gradient: const LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Color(0xFFEFF6FF), // blue-50 - Color(0xFFECFEFF), // cyan-50 - ], - ), - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - color: Color(0xFF2563EB), // blue-600 - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.mapPin, - size: 16, - color: Colors.white, - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Enable Commute Tracking?', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - const SizedBox(height: 4), - Text( - 'Share location 1hr before shift so your manager can see you\'re on the way.', - style: TextStyle( - fontSize: 12, - color: Color(0xFF475569), // slate-600 - ), - ), - ], - ), - ), - ], - ), - const SizedBox(height: 12), - Row( - children: [ - Expanded( - child: OutlinedButton( - onPressed: () { - setState(() => _localHasConsent = false); - }, - style: OutlinedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 8), - side: const BorderSide(color: Color(0xFFE2E8F0)), - ), - child: const Text('Not Now', style: TextStyle(fontSize: 12)), - ), - ), - const SizedBox(width: 8), - Expanded( - child: ElevatedButton( - onPressed: () { - setState(() => _localHasConsent = true); - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF2563EB), // blue-600 - padding: const EdgeInsets.symmetric(vertical: 8), - ), - child: const Text( - 'Enable', - style: TextStyle(fontSize: 12, color: Colors.white), - ), - ), - ), - ], - ), - ], - ), - ); - } - - Widget _buildPreShiftCard() { - return Container( - margin: const EdgeInsets.only(bottom: 20), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Row( - children: [ - Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - color: Color(0xFFF1F5F9), // slate-100 - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.navigation, - size: 16, - color: Color(0xFF475569), // slate-600 - ), - ), - const SizedBox(width: 8), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Text( - 'On My Way', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - const SizedBox(width: 8), - Row( - children: [ - const Icon( - LucideIcons.clock, - size: 12, - color: Color(0xFF64748B), // slate-500 - ), - const SizedBox(width: 2), - Text( - 'Shift starts in ${_getMinutesUntilShift()} min', - style: const TextStyle( - fontSize: 11, - color: Color(0xFF64748B), // slate-500 - ), - ), - ], - ), - ], - ), - const Text( - 'Track arrival', - style: TextStyle( - fontSize: 10, - color: Color(0xFF64748B), // slate-500 - ), - ), - ], - ), - ), - Switch( - value: _localIsCommuteOn, - onChanged: (value) { - setState(() => _localIsCommuteOn = value); - }, - activeColor: AppColors.krowBlue, - ), - ], - ), - ); - } - - Widget _buildActiveCommuteScreen() { - return Container( - height: MediaQuery.of(context).size.height, - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Color(0xFF2563EB), // blue-600 - Color(0xFF0891B2), // cyan-600 - ], - ), - ), - child: SafeArea( - child: Column( - children: [ - Expanded( - child: Center( - child: Padding( - padding: const EdgeInsets.all(20), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - TweenAnimationBuilder( - tween: Tween(begin: 1.0, end: 1.1), - duration: const Duration(seconds: 1), - curve: Curves.easeInOut, - builder: (context, double scale, child) { - return Transform.scale( - scale: scale, - child: Container( - width: 96, - height: 96, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.navigation, - size: 48, - color: Colors.white, - ), - ), - ); - }, - onEnd: () { - // Restart animation - setState(() {}); - }, - ), - const SizedBox(height: 24), - const Text( - 'On My Way', - style: TextStyle( - fontSize: 32, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - const SizedBox(height: 8), - Text( - 'Your manager can see you\'re heading to the site', - style: TextStyle( - fontSize: 14, - color: Colors.blue.shade100, - ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 32), - if (widget.distanceMeters != null) ...[ - Container( - width: double.infinity, - constraints: const BoxConstraints(maxWidth: 300), - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.1), - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: Colors.white.withOpacity(0.2), - ), - ), - child: Column( - children: [ - Text( - 'Distance to Site', - style: TextStyle( - fontSize: 14, - color: Colors.blue.shade100, - ), - ), - const SizedBox(height: 4), - Text( - _formatDistance(widget.distanceMeters!), - style: const TextStyle( - fontSize: 36, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ], - ), - ), - if (widget.etaMinutes != null) ...[ - const SizedBox(height: 12), - Container( - width: double.infinity, - constraints: const BoxConstraints(maxWidth: 300), - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.1), - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: Colors.white.withOpacity(0.2), - ), - ), - child: Column( - children: [ - Text( - 'Estimated Arrival', - style: TextStyle( - fontSize: 14, - color: Colors.blue.shade100, - ), - ), - const SizedBox(height: 4), - Text( - '${widget.etaMinutes} min', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ], - ), - ), - ], - ], - const SizedBox(height: 32), - Text( - 'Most app features are locked while commute mode is on. You\'ll be able to clock in once you arrive.', - style: TextStyle( - fontSize: 12, - color: Colors.blue.shade100, - ), - textAlign: TextAlign.center, - ), - ], - ), - ), - ), - ), - Padding( - padding: const EdgeInsets.all(20), - child: OutlinedButton( - onPressed: () { - setState(() => _localIsCommuteOn = false); - }, - style: OutlinedButton.styleFrom( - foregroundColor: Colors.white, - side: BorderSide(color: Colors.white.withOpacity(0.3)), - padding: const EdgeInsets.symmetric(vertical: 16), - minimumSize: const Size(double.infinity, 48), - ), - child: const Text('Turn Off Commute Mode'), - ), - ), - ], - ), - ), - ); - } - - Widget _buildArrivedCard() { - return Container( - margin: const EdgeInsets.only(bottom: 20), - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - gradient: const LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Color(0xFFECFDF5), // emerald-50 - Color(0xFFD1FAE5), // green-50 - ], - ), - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 8, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - children: [ - Container( - width: 64, - height: 64, - decoration: const BoxDecoration( - color: Color(0xFF10B981), // emerald-500 - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.checkCircle, - size: 32, - color: Colors.white, - ), - ), - const SizedBox(height: 16), - const Text( - 'You\'ve Arrived! 🎉', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), // slate-900 - ), - ), - const SizedBox(height: 8), - const Text( - 'You\'re at the shift location. Ready to clock in?', - style: TextStyle( - fontSize: 14, - color: Color(0xFF475569), // slate-600 - ), - textAlign: TextAlign.center, - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/date_selector.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/date_selector.dart deleted file mode 100644 index 320ba176..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/date_selector.dart +++ /dev/null @@ -1,114 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; - -class DateSelector extends StatelessWidget { - final DateTime selectedDate; - final ValueChanged onSelect; - final List shiftDates; - - const DateSelector({ - super.key, - required this.selectedDate, - required this.onSelect, - this.shiftDates = const [], - }); - - @override - Widget build(BuildContext context) { - final today = DateTime.now(); - final dates = List.generate(7, (index) { - return today.add(Duration(days: index - 3)); - }); - - return SizedBox( - height: 80, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: dates.map((date) { - final isSelected = _isSameDay(date, selectedDate); - final isToday = _isSameDay(date, today); - final hasShift = shiftDates.contains(_formatDateIso(date)); - - return Expanded( - child: GestureDetector( - onTap: () => onSelect(date), - child: AnimatedContainer( - duration: const Duration(milliseconds: 200), - margin: const EdgeInsets.symmetric(horizontal: 4), - decoration: BoxDecoration( - color: isSelected ? const Color(0xFF0032A0) : Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: isSelected - ? [ - BoxShadow( - color: const Color(0xFF0032A0).withOpacity(0.3), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ] - : [], - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - DateFormat('d').format(date), - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: isSelected - ? Colors.white - : const Color(0xFF0F172A), - ), - ), - const SizedBox(height: 2), - Text( - DateFormat('E').format(date), - style: TextStyle( - fontSize: 12, - color: isSelected - ? Colors.white.withOpacity(0.8) - : const Color(0xFF94A3B8), - ), - ), - const SizedBox(height: 4), - if (hasShift) - Container( - width: 6, - height: 6, - decoration: BoxDecoration( - color: isSelected - ? Colors.white - : const Color(0xFF0032A0), - shape: BoxShape.circle, - ), - ) - else if (isToday && !isSelected) - Container( - width: 6, - height: 6, - decoration: BoxDecoration( - color: Colors.grey.shade300, - shape: BoxShape.circle, - ), - ) - else - const SizedBox(height: 6), - ], - ), - ), - ), - ); - }).toList(), - ), - ); - } - - bool _isSameDay(DateTime a, DateTime b) { - return a.year == b.year && a.month == b.month && a.day == b.day; - } - - String _formatDateIso(DateTime date) { - return DateFormat('yyyy-MM-dd').format(date); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/lunch_break_modal.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/lunch_break_modal.dart deleted file mode 100644 index 99a59bd9..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/lunch_break_modal.dart +++ /dev/null @@ -1,518 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; - -class LunchBreakDialog extends StatefulWidget { - final VoidCallback onComplete; - - const LunchBreakDialog({super.key, required this.onComplete}); - - @override - State createState() => _LunchBreakDialogState(); -} - -class _LunchBreakDialogState extends State { - int _step = 1; - bool? _tookLunch; - String? _breakStart = '12:00pm'; - String? _breakEnd = '12:30pm'; - String? _noLunchReason; - String _additionalNotes = ''; - - final List _timeOptions = _generateTimeOptions(); - final List _noLunchReasons = [ - 'Unpredictable Workflows', - 'Poor Time Management', - 'Lack of coverage or short Staff', - 'No Lunch Area', - 'Other (Please specify)', - ]; - - static List _generateTimeOptions() { - List options = []; - for (int h = 0; h < 24; h++) { - for (int m = 0; m < 60; m += 15) { - final hour = h % 12 == 0 ? 12 : h % 12; - final ampm = h < 12 ? 'am' : 'pm'; - final timeStr = '$hour:${m.toString().padLeft(2, '0')}$ampm'; - options.add(timeStr); - } - } - return options; - } - - @override - Widget build(BuildContext context) { - return Dialog( - backgroundColor: Colors.white, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), - child: AnimatedSwitcher( - duration: const Duration(milliseconds: 300), - child: _buildCurrentStep(), - ), - ); - } - - Widget _buildCurrentStep() { - switch (_step) { - case 1: - return _buildStep1(); - case 2: - return _buildStep2(); - case 102: // 2b: No lunch reason - return _buildStep2b(); - case 3: - return _buildStep3(); - case 4: - return _buildStep4(); - default: - return const SizedBox.shrink(); - } - } - - Widget _buildStep1() { - return Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 80, - height: 80, - decoration: BoxDecoration( - color: Colors.grey.shade100, - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.coffee, - size: 40, - color: Color(0xFF6A7382), - ), - ), - const SizedBox(height: 24), - const Text( - "Did You Take\na Lunch?", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Color(0xFF121826), - ), - ), - const SizedBox(height: 8), - const Text( - "Taking regular breaks helps you stay productive and focused. Did you take a break during your shift?", - textAlign: TextAlign.center, - style: TextStyle(fontSize: 14, color: Color(0xFF6A7382)), - ), - const SizedBox(height: 32), - SizedBox( - width: double.infinity, - height: 56, - child: ElevatedButton( - onPressed: () { - setState(() { - _tookLunch = true; - _step = 2; - }); - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF121826), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28), - ), - ), - child: const Text("Yes, I Took a Lunch"), - ), - ), - const SizedBox(height: 12), - SizedBox( - width: double.infinity, - height: 56, - child: OutlinedButton( - onPressed: () { - setState(() { - _tookLunch = false; - _step = 102; // 2b - }); - }, - style: OutlinedButton.styleFrom( - foregroundColor: const Color(0xFF121826), - side: const BorderSide(color: Color(0xFFE3E6E9)), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28), - ), - ), - child: const Text("No, I Didn't take a Lunch"), - ), - ), - ], - ), - ); - } - - Widget _buildStep2() { - return Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 80, - height: 80, - decoration: BoxDecoration( - color: Colors.grey.shade100, - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.coffee, - size: 40, - color: Color(0xFF6A7382), - ), - ), - const SizedBox(height: 24), - const Text( - "Did You\nTake a Lunch?", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Color(0xFF121826), - ), - ), - const SizedBox(height: 8), - const Text( - "Select your break time.", - textAlign: TextAlign.center, - style: TextStyle(fontSize: 14, color: Color(0xFF6A7382)), - ), - const SizedBox(height: 24), - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "BREAK START TIME", - style: TextStyle(fontSize: 10, color: Color(0xFF6A7382)), - ), - const SizedBox(height: 8), - _buildDropdown( - _breakStart, - (val) => setState(() => _breakStart = val), - ), - ], - ), - ), - const SizedBox(width: 16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "BREAK END TIME", - style: TextStyle(fontSize: 10, color: Color(0xFF6A7382)), - ), - const SizedBox(height: 8), - _buildDropdown( - _breakEnd, - (val) => setState(() => _breakEnd = val), - ), - ], - ), - ), - ], - ), - const SizedBox(height: 32), - SizedBox( - width: double.infinity, - height: 56, - child: ElevatedButton( - onPressed: () => setState(() => _step = 3), - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF121826), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28), - ), - ), - child: const Text("Submit Lunch Time"), - ), - ), - const SizedBox(height: 12), - SizedBox( - width: double.infinity, - height: 56, - child: OutlinedButton( - onPressed: () => setState(() => _step = 1), - style: OutlinedButton.styleFrom( - foregroundColor: const Color(0xFF121826), - side: const BorderSide(color: Color(0xFFE3E6E9)), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28), - ), - ), - child: const Text("Cancel"), - ), - ), - ], - ), - ); - } - - Widget _buildStep2b() { - return Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 80, - height: 80, - decoration: BoxDecoration( - color: Colors.red.shade50, - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.coffee, - size: 40, - color: Color(0xFFF87171), - ), - ), - const SizedBox(height: 24), - const Text( - "Help Us Understand:\nWhat Kept You From\nTaking a Lunch?", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF121826), - ), - ), - const SizedBox(height: 24), - DropdownButtonFormField( - value: _noLunchReason, - hint: const Text("Select reason from a list"), - decoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - ), - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - ), - items: _noLunchReasons - .map( - (r) => DropdownMenuItem( - value: r, - child: Text(r, style: const TextStyle(fontSize: 12)), - ), - ) - .toList(), - onChanged: (val) => setState(() => _noLunchReason = val), - ), - const SizedBox(height: 16), - TextField( - maxLines: 4, - onChanged: (val) => setState(() => _additionalNotes = val), - decoration: InputDecoration( - hintText: "Enter your main text here...", - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - ), - const SizedBox(height: 4), - Align( - alignment: Alignment.centerRight, - child: Text( - "${_additionalNotes.length}/300", - style: const TextStyle(fontSize: 10, color: Colors.grey), - ), - ), - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - height: 56, - child: ElevatedButton( - onPressed: _noLunchReason == null - ? null - : () => setState(() => _step = 4), - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF121826), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28), - ), - ), - child: const Text("Submit Reason"), - ), - ), - const SizedBox(height: 12), - SizedBox( - width: double.infinity, - height: 56, - child: OutlinedButton( - onPressed: () => setState(() => _step = 1), - style: OutlinedButton.styleFrom( - foregroundColor: const Color(0xFF121826), - side: const BorderSide(color: Color(0xFFE3E6E9)), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28), - ), - ), - child: const Text("Cancel"), - ), - ), - ], - ), - ); - } - - Widget _buildStep3() { - return Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 80, - height: 80, - decoration: BoxDecoration( - color: const Color(0xFF10B981).withOpacity(0.1), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.check, - size: 40, - color: Color(0xFF10B981), - ), - ), - const SizedBox(height: 24), - const Text( - "Congratulations,\nShift Completed!", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Color(0xFF121826), - ), - ), - const SizedBox(height: 8), - const Text( - "Your break has been logged and added to your timeline. Keep up the good work!", - textAlign: TextAlign.center, - style: TextStyle(fontSize: 14, color: Color(0xFF6A7382)), - ), - const SizedBox(height: 32), - SizedBox( - width: double.infinity, - height: 56, - child: ElevatedButton( - onPressed: () { - Navigator.of(context).pop(); - widget.onComplete(); - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF121826), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28), - ), - ), - child: const Text("Back to Shift"), - ), - ), - ], - ), - ); - } - - Widget _buildStep4() { - return Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 80, - height: 80, - decoration: BoxDecoration( - color: Colors.red.shade50, - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.alertTriangle, - size: 40, - color: Color(0xFFF87171), - ), - ), - const SizedBox(height: 24), - const Text( - "Your Selection\nis under review", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Color(0xFF121826), - ), - ), - const SizedBox(height: 8), - const Text( - "Labor Code § 512 requires California employers to give unpaid lunch breaks...", - textAlign: TextAlign.center, - style: TextStyle(fontSize: 12, color: Color(0xFF6A7382)), - ), - const SizedBox(height: 16), - const Text( - "Once resolved you will be notify.\nNo further Action", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: Color(0xFF121826), - ), - ), - const SizedBox(height: 32), - SizedBox( - width: double.infinity, - height: 56, - child: ElevatedButton( - onPressed: () { - Navigator.of(context).pop(); - widget.onComplete(); - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF121826), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28), - ), - ), - child: const Text("Continue"), - ), - ), - ], - ), - ); - } - - Widget _buildDropdown(String? value, ValueChanged onChanged) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 12), - decoration: BoxDecoration( - border: Border.all(color: const Color(0xFFE3E6E9)), - borderRadius: BorderRadius.circular(12), - ), - child: DropdownButtonHideUnderline( - child: DropdownButton( - value: value, - isExpanded: true, - items: _timeOptions - .map((t) => DropdownMenuItem(value: t, child: Text(t))) - .toList(), - onChanged: onChanged, - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/swipe_to_check_in.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/swipe_to_check_in.dart deleted file mode 100644 index ffd960fb..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/clock_in/swipe_to_check_in.dart +++ /dev/null @@ -1,224 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; - -class SwipeToCheckIn extends StatefulWidget { - final VoidCallback? onCheckIn; - final VoidCallback? onCheckOut; - final bool isLoading; - final String mode; // 'swipe' or 'nfc' - final bool isCheckedIn; - - const SwipeToCheckIn({ - super.key, - this.onCheckIn, - this.onCheckOut, - this.isLoading = false, - this.mode = 'swipe', - this.isCheckedIn = false, - }); - - @override - State createState() => _SwipeToCheckInState(); -} - -class _SwipeToCheckInState extends State - with SingleTickerProviderStateMixin { - double _dragValue = 0.0; - final double _maxWidth = 300.0; // Estimate, will get from LayoutBuilder - final double _handleSize = 48.0; - bool _isComplete = false; - - @override - void didUpdateWidget(SwipeToCheckIn oldWidget) { - super.didUpdateWidget(oldWidget); - if (widget.isCheckedIn != oldWidget.isCheckedIn) { - setState(() { - _isComplete = false; - _dragValue = 0.0; - }); - } - } - - void _onDragUpdate(DragUpdateDetails details, double maxWidth) { - if (_isComplete || widget.isLoading) return; - setState(() { - _dragValue = (_dragValue + details.delta.dx).clamp( - 0.0, - maxWidth - _handleSize - 8, - ); - }); - } - - void _onDragEnd(DragEndDetails details, double maxWidth) { - if (_isComplete || widget.isLoading) return; - final threshold = (maxWidth - _handleSize - 8) * 0.8; - if (_dragValue > threshold) { - setState(() { - _dragValue = maxWidth - _handleSize - 8; - _isComplete = true; - }); - Future.delayed(const Duration(milliseconds: 300), () { - if (widget.isCheckedIn) { - widget.onCheckOut?.call(); - } else { - widget.onCheckIn?.call(); - } - }); - } else { - setState(() { - _dragValue = 0.0; - }); - } - } - - @override - Widget build(BuildContext context) { - final baseColor = widget.isCheckedIn - ? const Color(0xFF10B981) - : const Color(0xFF0032A0); - - if (widget.mode == 'nfc') { - return GestureDetector( - onTap: () { - if (widget.isLoading) return; - // Simulate completion for NFC tap - Future.delayed(const Duration(milliseconds: 300), () { - if (widget.isCheckedIn) { - widget.onCheckOut?.call(); - } else { - widget.onCheckIn?.call(); - } - }); - }, - child: Container( - height: 56, - decoration: BoxDecoration( - color: baseColor, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: baseColor.withOpacity(0.4), - blurRadius: 25, - offset: const Offset(0, 10), - spreadRadius: -5, - ), - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(LucideIcons.wifi, color: Colors.white), - const SizedBox(width: 12), - Text( - widget.isLoading - ? (widget.isCheckedIn - ? "Checking out..." - : "Checking in...") - : (widget.isCheckedIn ? "NFC Check Out" : "NFC Check In"), - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 18, - ), - ), - ], - ), - ), - ); - } - - return LayoutBuilder( - builder: (context, constraints) { - final maxWidth = constraints.maxWidth; - final maxDrag = maxWidth - _handleSize - 8; - - // Calculate background color based on drag - final progress = _dragValue / maxDrag; - final startColor = widget.isCheckedIn - ? const Color(0xFF10B981) - : const Color(0xFF0032A0); - final endColor = widget.isCheckedIn - ? const Color(0xFF0032A0) - : const Color(0xFF10B981); - final currentColor = - Color.lerp(startColor, endColor, progress) ?? startColor; - - return Container( - height: 56, - decoration: BoxDecoration( - color: currentColor, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Stack( - children: [ - Center( - child: Opacity( - opacity: 1.0 - progress, - child: Text( - widget.isCheckedIn - ? "Swipe to Check Out" - : "Swipe to Check In", - style: TextStyle( - color: Colors.white.withOpacity(0.8), - fontWeight: FontWeight.w600, - fontSize: 18, - ), - ), - ), - ), - if (_isComplete) - Center( - child: Text( - widget.isCheckedIn ? "Check Out!" : "Check In!", - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.w600, - fontSize: 18, - ), - ), - ), - Positioned( - left: 4 + _dragValue, - top: 4, - child: GestureDetector( - onHorizontalDragUpdate: (d) => _onDragUpdate(d, maxWidth), - onHorizontalDragEnd: (d) => _onDragEnd(d, maxWidth), - child: Container( - width: _handleSize, - height: _handleSize, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Center( - child: Icon( - _isComplete - ? LucideIcons.check - : LucideIcons.arrowRight, - color: startColor, - ), - ), - ), - ), - ), - ], - ), - ); - }, - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/payments/payment_history_item.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/payments/payment_history_item.dart deleted file mode 100644 index 9c49df1e..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/payments/payment_history_item.dart +++ /dev/null @@ -1,209 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; - -class PaymentHistoryItem extends StatelessWidget { - final double amount; - final String title; - final String location; - final String address; - final String date; - final String workedTime; - final int hours; - final double rate; - final String status; - - const PaymentHistoryItem({ - super.key, - required this.amount, - required this.title, - required this.location, - required this.address, - required this.date, - required this.workedTime, - required this.hours, - required this.rate, - required this.status, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Status Badge - Row( - children: [ - Container( - width: 6, - height: 6, - decoration: const BoxDecoration( - color: Color(0xFF3B82F6), // blue-500 - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 6), - const Text( - "PAID", - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w700, - color: Color(0xFF2563EB), // blue-600 - letterSpacing: 0.5, - ), - ), - ], - ), - const SizedBox(height: 12), - - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Icon - Container( - width: 44, - height: 44, - decoration: BoxDecoration( - color: const Color(0xFFF1F5F9), // slate-100 - borderRadius: BorderRadius.circular(12), - ), - child: const Icon( - LucideIcons.dollarSign, - color: Color(0xFF334155), // slate-700 - size: 24, - ), - ), - const SizedBox(width: 12), - - // Content - Expanded( - child: Column( - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - Text( - location, - style: const TextStyle( - fontSize: 12, - color: Color(0xFF475569), // slate-600 - ), - ), - ], - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - "\$${amount.toStringAsFixed(0)}", - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), // slate-900 - ), - ), - Text( - "\$${rate.toStringAsFixed(0)}/hr · ${hours}h", - style: const TextStyle( - fontSize: 10, - color: Color(0xFF64748B), // slate-500 - ), - ), - ], - ), - ], - ), - const SizedBox(height: 8), - - // Date and Time - Row( - children: [ - const Icon( - LucideIcons.calendar, - size: 12, - color: Color(0xFF64748B), - ), - const SizedBox(width: 8), - Text( - date, - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), - ), - ), - const SizedBox(width: 8), - const Icon( - LucideIcons.clock, - size: 12, - color: Color(0xFF64748B), - ), - const SizedBox(width: 8), - Text( - workedTime, - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), - ), - ), - ], - ), - const SizedBox(height: 4), - - // Address - Row( - children: [ - const Icon( - LucideIcons.mapPin, - size: 12, - color: Color(0xFF64748B), - ), - const SizedBox(width: 8), - Expanded( - child: Text( - address, - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ], - ), - ), - ], - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/payments/payment_stats_card.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/payments/payment_stats_card.dart deleted file mode 100644 index aad2cf9b..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/payments/payment_stats_card.dart +++ /dev/null @@ -1,62 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; - -class PaymentStatsCard extends StatelessWidget { - final IconData icon; - final Color iconColor; - final String label; - final String amount; - - const PaymentStatsCard({ - super.key, - required this.icon, - required this.iconColor, - required this.label, - required this.amount, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon(icon, size: 16, color: iconColor), - const SizedBox(width: 8), - Text( - label, - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), // slate-500 - ), - ), - ], - ), - const SizedBox(height: 8), - Text( - amount, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), // slate-900 - ), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/payments/pending_pay_card.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/payments/pending_pay_card.dart deleted file mode 100644 index 3ca7c602..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/payments/pending_pay_card.dart +++ /dev/null @@ -1,98 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; - -class PendingPayCard extends StatelessWidget { - final double amount; - final VoidCallback onCashOut; - - const PendingPayCard({ - super.key, - required this.amount, - required this.onCashOut, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(14), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFFEFF6FF), Color(0xFFEFF6FF)], // blue-50 to blue-50 - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: const Color(0xFFE8F0FF), - borderRadius: BorderRadius.circular(8), - ), - child: const Icon( - LucideIcons.dollarSign, - color: Color(0xFF0047FF), - size: 20, - ), - ), - const SizedBox(width: 10), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "Pending", - style: TextStyle( - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), // slate-900 - fontSize: 14, - ), - ), - Text( - "\$${amount.toStringAsFixed(0)} available", - style: const TextStyle( - fontSize: 12, - color: Color(0xFF475569), // slate-600 - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ], - ), - ElevatedButton.icon( - onPressed: onCashOut, - icon: const Icon(LucideIcons.zap, size: 14), - label: const Text("Early Pay"), - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0047FF), - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8), - elevation: 4, - shadowColor: Colors.black.withOpacity(0.2), - textStyle: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/scaffold_with_nav_bar.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/scaffold_with_nav_bar.dart deleted file mode 100644 index 041232ae..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/scaffold_with_nav_bar.dart +++ /dev/null @@ -1,138 +0,0 @@ -import 'dart:ui'; -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../theme.dart'; - -class ScaffoldWithNavBar extends StatelessWidget { - const ScaffoldWithNavBar({required this.navigationShell, super.key}); - - final StatefulNavigationShell navigationShell; - - @override - Widget build(BuildContext context) { - return Scaffold( - body: navigationShell, - extendBody: true, - bottomNavigationBar: _buildBottomBar(context), - ); - } - - Widget _buildBottomBar(BuildContext context) { - // TODO: Get from provider - bool isWorker = true; - final activeColor = isWorker ? AppColors.krowBlue : AppColors.krowCharcoal; - final inactiveColor = const Color(0xFF8E8E93); - - return Stack( - clipBehavior: Clip.none, - children: [ - Positioned.fill( - child: ClipRect( - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), - child: Container( - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.85), - border: const Border( - top: BorderSide(color: Color.fromRGBO(0, 0, 0, 0.1)), - ), - ), - ), - ), - ), - ), - Container( - padding: EdgeInsets.only( - bottom: MediaQuery.of(context).padding.bottom + 8, - top: 16, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - _buildNavItem( - 0, - LucideIcons.briefcase, - 'Shifts', - activeColor, - inactiveColor, - ), - _buildNavItem( - 1, - LucideIcons.dollarSign, - 'Payments', - activeColor, - inactiveColor, - ), - _buildNavItem( - 2, - LucideIcons.home, - 'Home', - activeColor, - inactiveColor, - ), - _buildNavItem( - 3, - LucideIcons.clock, - 'Clock In', - activeColor, - inactiveColor, - ), - _buildNavItem( - 4, - LucideIcons.users, - 'Profile', - activeColor, - inactiveColor, - ), - ], - ), - ), - ], - ); - } - - Widget _buildNavItem( - int index, - IconData icon, - String label, - Color activeColor, - Color inactiveColor, - ) { - final isSelected = navigationShell.currentIndex == index; - return Expanded( - child: GestureDetector( - onTap: () => _onTap(index), - behavior: HitTestBehavior.opaque, - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Icon( - icon, - color: isSelected ? activeColor : inactiveColor, - size: 24, - ), - const SizedBox(height: 2), - Text( - label, - style: TextStyle( - color: isSelected ? activeColor : inactiveColor, - fontSize: 10, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ), - ); - } - - void _onTap(int index) { - navigationShell.goBranch( - index, - initialLocation: index == navigationShell.currentIndex, - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/shift_card.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/shift_card.dart deleted file mode 100644 index d3817305..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/shift_card.dart +++ /dev/null @@ -1,495 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:intl/intl.dart'; -import '../models/shift.dart'; -import '../theme.dart'; - -class ShiftCard extends StatefulWidget { - final Shift shift; - final VoidCallback? onApply; - final VoidCallback? onDecline; - final bool compact; - final bool disableTapNavigation; // Added property - - const ShiftCard({ - super.key, - required this.shift, - this.onApply, - this.onDecline, - this.compact = false, - this.disableTapNavigation = false, // Default to false - }); - - @override - State createState() => _ShiftCardState(); -} - -class _ShiftCardState extends State { - bool isExpanded = false; - - String _formatTime(String time) { - if (time.isEmpty) return ''; - try { - final parts = time.split(':'); - final hour = int.parse(parts[0]); - final minute = int.parse(parts[1]); - final dt = DateTime(2022, 1, 1, hour, minute); - return DateFormat('h:mma').format(dt).toLowerCase(); - } catch (e) { - return time; - } - } - - String _formatDate(String dateStr) { - if (dateStr.isEmpty) return ''; - try { - final date = DateTime.parse(dateStr); - return DateFormat('MMMM d').format(date); - } catch (e) { - return dateStr; - } - } - - String _getTimeAgo(String dateStr) { - if (dateStr.isEmpty) return ''; - try { - final date = DateTime.parse(dateStr); - final diff = DateTime.now().difference(date); - if (diff.inHours < 1) return 'Just now'; - if (diff.inHours < 24) return 'Pending ${diff.inHours}h ago'; - return 'Pending ${diff.inDays}d ago'; - } catch (e) { - return ''; - } - } - - Map _calculateDuration() { - if (widget.shift.startTime.isEmpty || widget.shift.endTime.isEmpty) { - return {'hours': 0, 'breakTime': '1 hour'}; - } - try { - final startParts = widget.shift.startTime - .split(':') - .map(int.parse) - .toList(); - final endParts = widget.shift.endTime.split(':').map(int.parse).toList(); - double hours = - (endParts[0] - startParts[0]) + (endParts[1] - startParts[1]) / 60; - if (hours < 0) hours += 24; - return {'hours': hours.round(), 'breakTime': '1 hour'}; - } catch (e) { - return {'hours': 0, 'breakTime': '1 hour'}; - } - } - - @override - Widget build(BuildContext context) { - if (widget.compact) { - return GestureDetector( - onTap: widget.disableTapNavigation - ? null - : () { - setState(() => isExpanded = !isExpanded); - GoRouter.of( - context, - ).push('/shift-details/${widget.shift.id}', extra: widget.shift); - }, - child: Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: AppColors.krowBorder), - boxShadow: [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Row( - children: [ - Container( - width: 48, - height: 48, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: widget.shift.logoUrl != null - ? ClipRRect( - borderRadius: BorderRadius.circular(12), - child: Image.network( - widget.shift.logoUrl!, - fit: BoxFit.contain, - ), - ) - : const Icon( - LucideIcons.building2, - color: AppColors.krowMuted, - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Text( - widget.shift.title, - style: const TextStyle( - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - overflow: TextOverflow.ellipsis, - ), - ), - Text.rich( - TextSpan( - text: '\$${widget.shift.hourlyRate}', - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16, - color: AppColors.krowCharcoal, - ), - children: const [ - TextSpan( - text: '/h', - style: TextStyle( - fontWeight: FontWeight.normal, - fontSize: 12, - ), - ), - ], - ), - ), - ], - ), - Text( - widget.shift.clientName, - style: const TextStyle( - color: AppColors.krowMuted, - fontSize: 13, - ), - overflow: TextOverflow.ellipsis, - ), - const SizedBox(height: 4), - Text( - '${_formatTime(widget.shift.startTime)} • ${widget.shift.location}', - style: const TextStyle( - color: AppColors.krowMuted, - fontSize: 12, - ), - ), - ], - ), - ), - ], - ), - ), - ); - } - - return Container( - margin: const EdgeInsets.only(bottom: 16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: AppColors.krowBorder), - boxShadow: [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.05), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - // Header - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - width: 56, - height: 56, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: widget.shift.logoUrl != null - ? ClipRRect( - borderRadius: BorderRadius.circular(12), - child: Image.network( - widget.shift.logoUrl!, - fit: BoxFit.contain, - ), - ) - : const Icon( - LucideIcons.building2, - size: 28, - color: AppColors.krowBlue, - ), - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 6, - ), - decoration: BoxDecoration( - color: AppColors.krowBlue, - borderRadius: BorderRadius.circular(20), - ), - child: Text( - 'Assigned ${_getTimeAgo(widget.shift.createdDate).replaceAll('Pending ', '')}', - style: const TextStyle( - color: Colors.white, - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - ], - ), - const SizedBox(height: 16), - - // Title and Rate - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - widget.shift.title, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Text( - widget.shift.clientName, - style: const TextStyle( - color: AppColors.krowMuted, - fontSize: 14, - ), - ), - ], - ), - ), - Text.rich( - TextSpan( - text: '\$${widget.shift.hourlyRate}', - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 20, - color: AppColors.krowCharcoal, - ), - children: const [ - TextSpan( - text: '/h', - style: TextStyle( - fontWeight: FontWeight.normal, - fontSize: 16, - ), - ), - ], - ), - ), - ], - ), - const SizedBox(height: 16), - - // Location and Date - Row( - children: [ - const Icon( - LucideIcons.mapPin, - size: 16, - color: AppColors.krowMuted, - ), - const SizedBox(width: 6), - Expanded( - child: Text( - widget.shift.location, - style: const TextStyle( - color: AppColors.krowMuted, - fontSize: 14, - ), - overflow: TextOverflow.ellipsis, - ), - ), - const SizedBox(width: 16), - const Icon( - LucideIcons.calendar, - size: 16, - color: AppColors.krowMuted, - ), - const SizedBox(width: 6), - Text( - '${_formatDate(widget.shift.date)}, ${_formatTime(widget.shift.startTime)}', - style: const TextStyle( - color: AppColors.krowMuted, - fontSize: 14, - ), - ), - ], - ), - const SizedBox(height: 16), - - // Tags - Wrap( - spacing: 8, - runSpacing: 8, - children: [ - _buildTag( - LucideIcons.zap, - 'Immediate start', - AppColors.krowYellow.withValues(alpha: 0.3), - AppColors.krowCharcoal, - ), - _buildTag( - LucideIcons.timer, - 'No experience', - const Color(0xFFFEE2E2), - const Color(0xFFDC2626), - ), - ], - ), - - const SizedBox(height: 16), - ], - ), - ), - - // Actions - if (!widget.compact) - Padding( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), - child: Column( - children: [ - SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: widget.onApply, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowCharcoal, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: const Text( - 'Accept shift', - style: TextStyle(fontWeight: FontWeight.w600), - ), - ), - ), - const SizedBox(height: 8), - SizedBox( - width: double.infinity, - height: 48, - child: OutlinedButton( - onPressed: widget.onDecline, - style: OutlinedButton.styleFrom( - foregroundColor: const Color(0xFFEF4444), - side: const BorderSide(color: Color(0xFFFCA5A5)), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: const Text( - 'Decline shift', - style: TextStyle(fontWeight: FontWeight.w600), - ), - ), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildTag(IconData icon, String label, Color bg, Color text) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), - decoration: BoxDecoration( - color: bg, - borderRadius: BorderRadius.circular(20), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(icon, size: 14, color: text), - const SizedBox(width: 4), - Flexible( - child: Text( - label, - style: TextStyle( - color: text, - fontSize: 12, - fontWeight: FontWeight.w600, - ), - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ); - } - - Widget _buildDetailRow(IconData icon, String label, bool? value) { - return Container( - padding: const EdgeInsets.symmetric(vertical: 12), - decoration: const BoxDecoration( - border: Border(bottom: BorderSide(color: AppColors.krowBorder)), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Icon(icon, size: 16, color: AppColors.krowMuted), - const SizedBox(width: 8), - Text( - label, - style: const TextStyle( - color: AppColors.krowMuted, - fontSize: 14, - ), - ), - ], - ), - Text( - value == true ? 'Yes' : 'No', - style: TextStyle( - color: value == true - ? const Color(0xFF10B981) - : AppColors.krowMuted, - fontWeight: FontWeight.w600, - fontSize: 14, - ), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/shifts/my_shift_card.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/shifts/my_shift_card.dart deleted file mode 100644 index 7044a92b..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/shifts/my_shift_card.dart +++ /dev/null @@ -1,775 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:intl/intl.dart'; -import '../../theme.dart'; -import '../../models/shift.dart'; - -class MyShiftCard extends StatefulWidget { - final Shift shift; - final bool historyMode; - final VoidCallback? onAccept; - final VoidCallback? onDecline; - final VoidCallback? onRequestSwap; - final int index; - - const MyShiftCard({ - super.key, - required this.shift, - this.historyMode = false, - this.onAccept, - this.onDecline, - this.onRequestSwap, - this.index = 0, - }); - - @override - State createState() => _MyShiftCardState(); -} - -class _MyShiftCardState extends State { - bool _isExpanded = false; - - String _formatTime(String time) { - if (time.isEmpty) return ''; - try { - final parts = time.split(':'); - final hour = int.parse(parts[0]); - final minute = int.parse(parts[1]); - final dt = DateTime(2022, 1, 1, hour, minute); - return DateFormat('h:mm a').format(dt); - } catch (e) { - return time; - } - } - - String _formatDate(String dateStr) { - if (dateStr.isEmpty) return ''; - try { - final date = DateTime.parse(dateStr); - final now = DateTime.now(); - final today = DateTime(now.year, now.month, now.day); - final tomorrow = today.add(const Duration(days: 1)); - final d = DateTime(date.year, date.month, date.day); - - if (d == today) return 'Today'; - if (d == tomorrow) return 'Tomorrow'; - return DateFormat('EEE, MMM d').format(date); - } catch (e) { - return dateStr; - } - } - - double _calculateDuration() { - if (widget.shift.startTime.isEmpty || widget.shift.endTime.isEmpty) - return 0; - try { - final s = widget.shift.startTime.split(':').map(int.parse).toList(); - final e = widget.shift.endTime.split(':').map(int.parse).toList(); - double hours = ((e[0] * 60 + e[1]) - (s[0] * 60 + s[1])) / 60; - if (hours < 0) hours += 24; - return hours.roundToDouble(); - } catch (_) { - return 0; - } - } - - String _getShiftType() { - // Check title for type indicators (for mock data) - if (widget.shift.title.contains('Long Term')) return 'Long Term'; - if (widget.shift.title.contains('Multi-Day')) return 'Multi-Day'; - return 'One Day'; - } - - @override - Widget build(BuildContext context) { - final duration = _calculateDuration(); - final estimatedTotal = (widget.shift.hourlyRate) * duration; - - // Status Logic - String? status = widget.shift.status; - Color statusColor = AppColors.krowBlue; - Color statusBg = AppColors.krowBlue; - String statusText = ''; - IconData? statusIcon; - - if (status == 'confirmed') { - statusText = 'CONFIRMED'; - statusColor = AppColors.krowBlue; - statusBg = AppColors.krowBlue; - } else if (status == 'pending' || status == 'open') { - statusText = 'ACT NOW'; - statusColor = const Color(0xFFDC2626); - statusBg = const Color(0xFFEF4444); - } else if (status == 'swap') { - statusText = 'SWAP REQUESTED'; - statusColor = const Color(0xFFF59E0B); - statusBg = const Color(0xFFF59E0B); - statusIcon = LucideIcons.arrowLeftRight; - } else if (status == 'completed') { - statusText = 'COMPLETED'; - statusColor = const Color(0xFF10B981); - statusBg = const Color(0xFF10B981); - } else if (status == 'no_show') { - statusText = 'NO SHOW'; - statusColor = const Color(0xFFEF4444); - statusBg = const Color(0xFFEF4444); - } - - return GestureDetector( - onTap: () => setState(() => _isExpanded = !_isExpanded), - child: AnimatedContainer( - duration: const Duration(milliseconds: 300), - margin: const EdgeInsets.only(bottom: 12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: AppColors.krowBorder), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - children: [ - // Collapsed Content - Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Status Badge - if (statusText.isNotEmpty) - Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Row( - children: [ - if (statusIcon != null) - Padding( - padding: const EdgeInsets.only(right: 6), - child: Icon( - statusIcon, - size: 12, - color: statusColor, - ), - ) - else - Container( - width: 6, - height: 6, - margin: const EdgeInsets.only(right: 6), - decoration: BoxDecoration( - color: statusBg, - shape: BoxShape.circle, - ), - ), - Text( - statusText, - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w600, - color: statusColor, - letterSpacing: 0.5, - ), - ), - // Shift Type Badge for available/pending shifts - if (status == 'open' || status == 'pending') ...[ - const SizedBox(width: 8), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 6, - vertical: 2, - ), - decoration: BoxDecoration( - color: AppColors.krowBlue.withOpacity(0.1), - borderRadius: BorderRadius.circular(4), - ), - child: Text( - _getShiftType(), - style: TextStyle( - fontSize: 8, - fontWeight: FontWeight.w500, - color: AppColors.krowBlue, - ), - ), - ), - ], - ], - ), - ), - - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Logo - Container( - width: 44, - height: 44, - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - AppColors.krowBlue.withOpacity(0.09), - AppColors.krowBlue.withOpacity(0.03), - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: AppColors.krowBlue.withOpacity(0.09), - ), - ), - child: widget.shift.logoUrl != null - ? ClipRRect( - borderRadius: BorderRadius.circular(12), - child: Image.network( - widget.shift.logoUrl!, - fit: BoxFit.contain, - ), - ) - : const Center( - child: Icon( - LucideIcons.briefcase, - color: AppColors.krowBlue, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - - // Details - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - widget.shift.title, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - overflow: TextOverflow.ellipsis, - ), - Text( - widget.shift.clientName, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - overflow: TextOverflow.ellipsis, - ), - ], - ), - ), - const SizedBox(width: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - "\$${estimatedTotal.toStringAsFixed(0)}", - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Text( - "\$${widget.shift.hourlyRate}/hr · ${duration}h", - style: const TextStyle( - fontSize: 10, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - ), - const SizedBox(height: 8), - - // Date & Time - Multi-Day or Single Day - if (_getShiftType() == 'Multi-Day' && - widget.shift.durationDays != null) ...[ - // Multi-Day Schedule Display - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Icon( - LucideIcons.clock, - size: 12, - color: AppColors.krowBlue, - ), - const SizedBox(width: 4), - Text( - '${widget.shift.durationDays} schedules', - style: const TextStyle( - fontSize: 10, - fontWeight: FontWeight.w500, - color: AppColors.krowBlue, - ), - ), - ], - ), - const SizedBox(height: 4), - ...List.generate(widget.shift.durationDays!, ( - index, - ) { - final shiftDate = DateTime.parse( - widget.shift.date, - ); - final scheduleDate = shiftDate.add( - Duration(days: index), - ); - final dayName = DateFormat( - 'E', - ).format(scheduleDate); - final dateStr = DateFormat( - 'MMM d', - ).format(scheduleDate); - - return Padding( - padding: const EdgeInsets.only(bottom: 2), - child: Text( - '$dayName, $dateStr ${_formatTime(widget.shift.startTime)} – ${_formatTime(widget.shift.endTime)}', - style: const TextStyle( - fontSize: 10, - color: AppColors.krowBlue, - ), - ), - ); - }), - ], - ), - ] else ...[ - // Single Day Display - Row( - children: [ - const Icon( - LucideIcons.calendar, - size: 12, - color: AppColors.krowMuted, - ), - const SizedBox(width: 4), - Text( - _formatDate(widget.shift.date), - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - const SizedBox(width: 12), - const Icon( - LucideIcons.clock, - size: 12, - color: AppColors.krowMuted, - ), - const SizedBox(width: 4), - Text( - "${_formatTime(widget.shift.startTime)} - ${_formatTime(widget.shift.endTime)}", - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - const SizedBox(height: 4), - - // Location - Row( - children: [ - const Icon( - LucideIcons.mapPin, - size: 12, - color: AppColors.krowMuted, - ), - const SizedBox(width: 4), - Expanded( - child: Text( - widget.shift.locationAddress.isNotEmpty - ? widget.shift.locationAddress - : widget.shift.location, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ], - ), - ), - ], - ), - ], - ), - ), - - // Expanded Content - AnimatedSize( - duration: const Duration(milliseconds: 300), - child: _isExpanded - ? Column( - children: [ - const Divider(height: 1, color: AppColors.krowBorder), - Padding( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - // Stats Row - Row( - children: [ - Expanded( - child: _buildStatCard( - LucideIcons.dollarSign, - "\$${estimatedTotal.toStringAsFixed(0)}", - "Total", - ), - ), - const SizedBox(width: 12), - Expanded( - child: _buildStatCard( - LucideIcons.dollarSign, - "\$${widget.shift.hourlyRate}", - "Hourly Rate", - ), - ), - const SizedBox(width: 12), - Expanded( - child: _buildStatCard( - LucideIcons.timer, - "${duration}", - "Hours", - ), - ), - ], - ), - const SizedBox(height: 24), - - // In/Out Time - Row( - children: [ - Expanded( - child: _buildTimeBox( - "CLOCK IN TIME", - widget.shift.startTime, - ), - ), - const SizedBox(width: 12), - Expanded( - child: _buildTimeBox( - "CLOCK OUT TIME", - widget.shift.endTime, - ), - ), - ], - ), - const SizedBox(height: 24), - - // Location - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "LOCATION", - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: AppColors.krowMuted, - letterSpacing: 0.5, - ), - ), - const SizedBox(height: 8), - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - widget.shift.location.isEmpty - ? "TBD" - : widget.shift.location, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - OutlinedButton.icon( - onPressed: () { - // Show snackbar with the address - ScaffoldMessenger.of( - context, - ).showSnackBar( - SnackBar( - content: Text( - widget.shift.locationAddress ?? - widget.shift.location, - ), - duration: const Duration( - seconds: 3, - ), - ), - ); - }, - icon: const Icon( - LucideIcons.navigation, - size: 14, - ), - label: const Text( - "Get direction", - style: TextStyle(fontSize: 12), - ), - style: OutlinedButton.styleFrom( - foregroundColor: - AppColors.krowCharcoal, - side: const BorderSide( - color: AppColors.krowBorder, - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - 20, - ), - ), - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 0, - ), - minimumSize: const Size(0, 32), - ), - ), - ], - ), - const SizedBox(height: 12), - Container( - height: 128, - decoration: BoxDecoration( - color: Colors.grey.shade100, - borderRadius: BorderRadius.circular(12), - ), - // Placeholder for Map - ), - ], - ), - const SizedBox(height: 24), - - // Additional Info - if (widget.shift.description != null) ...[ - SizedBox( - width: double.infinity, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - const Text( - "ADDITIONAL INFO", - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: AppColors.krowMuted, - letterSpacing: 0.5, - ), - ), - const SizedBox(height: 8), - Text( - widget.shift.description!.split('.')[0], - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ), - Text( - widget.shift.description!, - style: const TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - const SizedBox(height: 24), - ], - - // Actions - if (!widget.historyMode) - if (status == 'confirmed') - SizedBox( - width: double.infinity, - height: 48, - child: OutlinedButton.icon( - onPressed: widget.onRequestSwap, - icon: const Icon( - LucideIcons.arrowLeftRight, - size: 16, - ), - label: const Text("Request Swap"), - style: OutlinedButton.styleFrom( - foregroundColor: AppColors.krowBlue, - side: const BorderSide( - color: AppColors.krowBlue, - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - 12, - ), - ), - ), - ), - ) - else if (status == 'swap') - Container( - width: double.infinity, - height: 48, - decoration: BoxDecoration( - color: const Color( - 0xFFFFFBEB, - ), // amber-50 - border: Border.all( - color: const Color(0xFFFDE68A), - ), // amber-200 - borderRadius: BorderRadius.circular(12), - ), - child: const Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Icon( - LucideIcons.arrowLeftRight, - size: 16, - color: Color(0xFFB45309), - ), // amber-700 - SizedBox(width: 8), - Text( - "Swap Pending", - style: TextStyle( - fontWeight: FontWeight.w600, - color: Color(0xFFB45309), - ), - ), - ], - ), - ) - else - Column( - children: [ - SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: widget.onAccept, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(12), - ), - ), - child: const Text( - "Book Shift", - style: TextStyle( - fontWeight: FontWeight.w600, - ), - ), - ), - ), - ], - ), - ], - ), - ), - ], - ) - : const SizedBox.shrink(), - ), - ], - ), - ), - ); - } - - Widget _buildStatCard(IconData icon, String value, String label) { - return Container( - padding: const EdgeInsets.symmetric(vertical: 16), - decoration: BoxDecoration( - color: const Color(0xFFF8FAFC), - borderRadius: BorderRadius.circular(16), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - children: [ - Container( - width: 40, - height: 40, - decoration: const BoxDecoration( - color: Colors.white, - shape: BoxShape.circle, - ), - child: Icon(icon, size: 20, color: AppColors.krowMuted), - ), - const SizedBox(height: 8), - Text( - value, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Text( - label, - style: const TextStyle(fontSize: 10, color: AppColors.krowMuted), - ), - ], - ), - ); - } - - Widget _buildTimeBox(String label, String time) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFFF8FAFC), - borderRadius: BorderRadius.circular(16), - ), - child: Column( - children: [ - Text( - label, - style: const TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: AppColors.krowMuted, - letterSpacing: 0.5, - ), - ), - const SizedBox(height: 4), - Text( - _formatTime(time), - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/shifts/shift_assignment_card.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/shifts/shift_assignment_card.dart deleted file mode 100644 index 2b7413de..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/shifts/shift_assignment_card.dart +++ /dev/null @@ -1,282 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:intl/intl.dart'; -import '../../theme.dart'; -import '../../models/shift.dart'; - -class ShiftAssignmentCard extends StatelessWidget { - final Shift shift; - final VoidCallback onConfirm; - final VoidCallback onDecline; - final bool isConfirming; - - const ShiftAssignmentCard({ - super.key, - required this.shift, - required this.onConfirm, - required this.onDecline, - this.isConfirming = false, - }); - - String _formatTime(String time) { - if (time.isEmpty) return ''; - try { - final parts = time.split(':'); - final hour = int.parse(parts[0]); - final minute = int.parse(parts[1]); - final dt = DateTime(2022, 1, 1, hour, minute); - return DateFormat('h:mm a').format(dt); - } catch (e) { - return time; - } - } - - String _formatDate(String dateStr) { - if (dateStr.isEmpty) return ''; - try { - final date = DateTime.parse(dateStr); - final now = DateTime.now(); - final today = DateTime(now.year, now.month, now.day); - final tomorrow = today.add(const Duration(days: 1)); - final d = DateTime(date.year, date.month, date.day); - - if (d == today) return 'Today'; - if (d == tomorrow) return 'Tomorrow'; - return DateFormat('EEE, MMM d').format(date); - } catch (e) { - return dateStr; - } - } - - double _calculateHours(String start, String end) { - if (start.isEmpty || end.isEmpty) return 0; - try { - final s = start.split(':').map(int.parse).toList(); - final e = end.split(':').map(int.parse).toList(); - return ((e[0] * 60 + e[1]) - (s[0] * 60 + s[1])) / 60; - } catch (_) { - return 0; - } - } - - @override - Widget build(BuildContext context) { - final hours = _calculateHours(shift.startTime, shift.endTime); - final totalPay = shift.hourlyRate * hours; - - return Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: Colors.grey.shade200), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - children: [ - // Header - Padding( - padding: const EdgeInsets.fromLTRB(16, 16, 16, 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Container( - width: 36, - height: 36, - decoration: BoxDecoration( - color: Colors.grey.shade100, - borderRadius: BorderRadius.circular(8), - ), - child: Center( - child: Text( - shift.clientName.isNotEmpty - ? shift.clientName[0] - : 'K', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Colors.grey.shade600, - ), - ), - ), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - shift.title, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ), - Text( - shift.clientName, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - "\$${totalPay.toStringAsFixed(0)}", - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Text( - "\$${shift.hourlyRate}/hr · ${hours}h", - style: const TextStyle( - fontSize: 10, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - ), - ), - - // Details - Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Icon( - LucideIcons.calendar, - size: 14, - color: AppColors.krowMuted, - ), - const SizedBox(width: 6), - Text( - _formatDate(shift.date), - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - const SizedBox(width: 16), - const Icon( - LucideIcons.clock, - size: 14, - color: AppColors.krowMuted, - ), - const SizedBox(width: 6), - Text( - "${_formatTime(shift.startTime)} - ${_formatTime(shift.endTime)}", - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - const SizedBox(height: 8), - Row( - children: [ - const Icon( - LucideIcons.mapPin, - size: 14, - color: AppColors.krowMuted, - ), - const SizedBox(width: 6), - Expanded( - child: Text( - shift.locationAddress.isNotEmpty - ? shift.locationAddress - : shift.location, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - // Skills would go here if they were in the Shift model - ], - ), - ), - - // Actions - Padding( - padding: const EdgeInsets.fromLTRB(16, 4, 16, 16), - child: Row( - children: [ - Expanded( - child: SizedBox( - height: 36, - child: OutlinedButton( - onPressed: onDecline, - style: OutlinedButton.styleFrom( - foregroundColor: AppColors.krowMuted, - side: BorderSide(color: Colors.grey.shade200), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - padding: EdgeInsets.zero, - ), - child: const Text( - "Decline", - style: TextStyle(fontSize: 12), - ), - ), - ), - ), - const SizedBox(width: 8), - Expanded( - child: SizedBox( - height: 36, - child: ElevatedButton( - onPressed: isConfirming ? null : onConfirm, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - padding: EdgeInsets.zero, - disabledBackgroundColor: AppColors.krowBlue.withOpacity( - 0.6, - ), - ), - child: Text( - isConfirming ? "Confirming..." : "Confirm", - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ), - ), - ), - ], - ), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/web_mobile_frame.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/web_mobile_frame.dart deleted file mode 100644 index 8b515056..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/web_mobile_frame.dart +++ /dev/null @@ -1,271 +0,0 @@ -import 'dart:ui'; - -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:google_fonts/google_fonts.dart'; - -/// A wrapper widget that renders the application inside an iPhone 14 Pro Max-like frame -/// specifically for Flutter Web. On other platforms, it simply returns the child. -class WebMobileFrame extends StatelessWidget { - final Widget child; - - const WebMobileFrame({super.key, required this.child}); - - @override - Widget build(BuildContext context) { - if (!kIsWeb) return child; - - return MaterialApp( - debugShowCheckedModeBanner: false, - theme: ThemeData.dark(), - home: _WebFrameContent(child: child), - ); - } -} - -class _WebFrameContent extends StatefulWidget { - final Widget child; - const _WebFrameContent({required this.child}); - - @override - State<_WebFrameContent> createState() => _WebFrameContentState(); -} - -class _WebFrameContentState extends State<_WebFrameContent> { - Offset _cursorPosition = Offset.zero; - bool _isHovering = false; - - @override - Widget build(BuildContext context) { - // iPhone 14 Pro Max-ish dimensions (scaled for frame look) - const double frameWidth = 390 * 1.2; - const double frameHeight = 844 * 1.3; - const double borderRadius = 54.0; - const double borderThickness = 12.0; - - return Scaffold( - backgroundColor: const Color(0xFF121212), - body: MouseRegion( - cursor: SystemMouseCursors.none, - onHover: (event) { - setState(() { - _cursorPosition = event.position; - _isHovering = true; - }); - }, - onExit: (_) => setState(() => _isHovering = false), - child: Stack( - children: [ - // Logo and Title on the left (Web only) - Positioned( - left: 60, - top: 0, - bottom: 0, - child: Center( - child: Opacity( - opacity: 0.5, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset('assets/logo.png', width: 140), - const SizedBox(height: 12), - Text( - 'KROW Staff \nApplication', - textAlign: TextAlign.left, - style: GoogleFonts.instrumentSans( - color: Colors.white, - fontSize: 28, - fontWeight: FontWeight.bold, - letterSpacing: -0.5, - ), - ), - const SizedBox(height: 4), - Container( - height: 2, - width: 40, - color: Colors.white.withOpacity(0.3), - ), - ], - ), - ), - ), - ), - - // Frame and Content - Center( - child: LayoutBuilder( - builder: (context, constraints) { - // Scale down if screen is too small - double scaleX = constraints.maxWidth / (frameWidth + 80); - double scaleY = constraints.maxHeight / (frameHeight + 80); - double scale = (scaleX < 1 || scaleY < 1) - ? (scaleX < scaleY ? scaleX : scaleY) - : 1.0; - - return Transform.scale( - scale: scale, - child: Container( - width: frameWidth, - height: frameHeight, - decoration: BoxDecoration( - color: Colors.black, - borderRadius: BorderRadius.circular(borderRadius), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.6), - blurRadius: 40, - spreadRadius: 10, - ), - ], - border: Border.all( - color: const Color(0xFF2C2C2C), - width: borderThickness, - ), - ), - child: ClipRRect( - borderRadius: BorderRadius.circular( - borderRadius - borderThickness, - ), - child: Stack( - children: [ - // The actual app + status bar - Column( - children: [ - // Mock iOS Status Bar - Container( - height: 48, - padding: const EdgeInsets.symmetric( - horizontal: 24, - ), - decoration: const BoxDecoration( - color: Color(0xFFF9F6EE), - border: Border( - bottom: BorderSide( - color: Color(0xFFEEEEEE), - width: 0.5, - ), - ), - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - // Time side - const SizedBox( - width: 80, - child: Text( - '3:12 PM', - textAlign: TextAlign.center, - style: TextStyle( - color: Colors.black54, - fontWeight: FontWeight.w700, - fontSize: 14, - letterSpacing: -0.2, - ), - ), - ), - // Status Icons side - const SizedBox( - width: 80, - child: Row( - mainAxisAlignment: - MainAxisAlignment.end, - spacing: 12, - children: [ - Icon( - FontAwesomeIcons.signal, - size: 12, - color: Colors.black54, - ), - Icon( - FontAwesomeIcons.wifi, - size: 12, - color: Colors.black54, - ), - Icon( - FontAwesomeIcons.batteryFull, - size: 12, - color: Colors.black54, - ), - ], - ), - ), - ], - ), - ), - // The main app content content - Expanded(child: widget.child), - ], - ), - - // Notch / Dynamic Island - Align( - alignment: Alignment.topCenter, - child: Padding( - padding: const EdgeInsets.only(top: 8), - child: Container( - width: 125, - height: 35, - decoration: BoxDecoration( - color: Colors.black, - borderRadius: BorderRadius.circular(20), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Container( - width: 8, - height: 8, - margin: const EdgeInsets.only( - right: 20, - ), - decoration: const BoxDecoration( - color: Color(0xFF0F0F0F), - shape: BoxShape.circle, - ), - ), - ], - ), - ), - ), - ), - ], - ), - ), - ), - ); - }, - ), - ), - - // Custom Circle Cursor - if (_isHovering) - Positioned( - left: _cursorPosition.dx - 20, - top: _cursorPosition.dy - 20, - child: IgnorePointer( - child: ClipRRect( - borderRadius: BorderRadius.circular(25), - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 2.5, sigmaY: 2.5), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.grey.withAlpha(50), - shape: BoxShape.circle, - border: Border.all(color: Colors.white, width: 1.5), - ), - ), - ), - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/auto_match_toggle.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/auto_match_toggle.dart deleted file mode 100644 index a0d0de1e..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/auto_match_toggle.dart +++ /dev/null @@ -1,166 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; - -class AutoMatchToggle extends StatefulWidget { - final bool enabled; - final ValueChanged onToggle; - - const AutoMatchToggle({ - super.key, - required this.enabled, - required this.onToggle, - }); - - @override - State createState() => _AutoMatchToggleState(); -} - -class _AutoMatchToggleState extends State - with SingleTickerProviderStateMixin { - @override - Widget build(BuildContext context) { - return AnimatedContainer( - duration: const Duration(milliseconds: 300), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16), - gradient: widget.enabled - ? const LinearGradient( - colors: [Color(0xFF0032A0), Color(0xFF0047CC)], - begin: Alignment.centerLeft, - end: Alignment.centerRight, - ) - : null, - color: widget.enabled ? null : Colors.white, - border: widget.enabled ? null : Border.all(color: Colors.grey.shade200), - boxShadow: widget.enabled - ? [ - BoxShadow( - color: const Color(0xFF0032A0).withOpacity(0.3), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ] - : null, - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: widget.enabled - ? Colors.white.withOpacity(0.2) - : const Color(0xFF0032A0).withOpacity(0.1), - borderRadius: BorderRadius.circular(12), - ), - child: Icon( - LucideIcons.zap, - color: widget.enabled - ? Colors.white - : const Color(0xFF0032A0), - size: 20, - ), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Auto-Match", - style: TextStyle( - fontWeight: FontWeight.bold, - color: widget.enabled - ? Colors.white - : const Color(0xFF0F172A), // slate-900 - ), - ), - Text( - widget.enabled - ? "Finding shifts for you" - : "Get matched automatically", - style: TextStyle( - fontSize: 12, - color: widget.enabled - ? const Color(0xFFF8E08E) - : Colors.grey.shade500, - ), - ), - ], - ), - ], - ), - Switch( - value: widget.enabled, - onChanged: widget.onToggle, - activeColor: Colors.white, - activeTrackColor: Colors.white.withOpacity(0.3), - inactiveThumbColor: Colors.white, - inactiveTrackColor: Colors.grey.shade300, - ), - ], - ), - AnimatedSize( - duration: const Duration(milliseconds: 300), - child: widget.enabled - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 16), - Container( - height: 1, - color: Colors.white.withOpacity(0.2), - ), - const SizedBox(height: 16), - const Text( - "Matching based on:", - style: TextStyle( - color: Color(0xFFF8E08E), - fontSize: 12, - ), - ), - const SizedBox(height: 12), - Wrap( - spacing: 8, - children: [ - _buildChip(LucideIcons.mapPin, "Location"), - _buildChip(LucideIcons.clock, "Availability"), - _buildChip(LucideIcons.briefcase, "Skills"), - ], - ), - ], - ) - : const SizedBox.shrink(), - ), - ], - ), - ); - } - - Widget _buildChip(IconData icon, String label) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(8), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(icon, size: 12, color: Colors.white), - const SizedBox(width: 4), - Text( - label, - style: const TextStyle(color: Colors.white, fontSize: 12), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/benefits_widget.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/benefits_widget.dart deleted file mode 100644 index 2f5c7d09..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/benefits_widget.dart +++ /dev/null @@ -1,199 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import 'dart:math' as math; -import '../../theme.dart'; - -class BenefitsWidget extends StatelessWidget { - const BenefitsWidget({super.key}); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: Colors.grey.shade100), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - "Your Benefits", - style: TextStyle( - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), // slate-900 - ), - GestureDetector( - onTap: () => context.push('/benefits'), - child: const Row( - children: [ - Text( - "View all", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF0032A0), - ), - ), - Icon( - LucideIcons.chevronRight, - size: 16, - color: Color(0xFF0032A0), - ), - ], - ), - ), - ], - ), - const SizedBox(height: 16), - const Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _BenefitItem( - label: "Sick Days", - current: 10, - total: 40, - color: Color(0xFF0A39DF), - ), - _BenefitItem( - label: "Vacation", - current: 40, - total: 40, - color: Color(0xFF0A39DF), - ), - _BenefitItem( - label: "Holidays", - current: 24, - total: 24, - color: Color(0xFF0A39DF), - ), - ], - ), - ], - ), - ); - } -} - -class _BenefitItem extends StatelessWidget { - final String label; - final double current; - final double total; - final Color color; - - const _BenefitItem({ - required this.label, - required this.current, - required this.total, - required this.color, - }); - - @override - Widget build(BuildContext context) { - return Column( - children: [ - SizedBox( - width: 56, - height: 56, - child: CustomPaint( - painter: _CircularProgressPainter( - progress: current / total, - color: color, - backgroundColor: const Color(0xFFE5E7EB), // slate-200 - strokeWidth: 4, - ), - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "${current.toInt()}/${total.toInt()}", - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Color(0xFF1E293B), // slate-800 - ), - ), - const Text( - "hours", - style: TextStyle( - fontSize: 8, - color: Color(0xFF94A3B8), // slate-400 - ), - ), - ], - ), - ), - ), - ), - const SizedBox(height: 8), - Text( - label, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Color(0xFF475569), // slate-600 - ), - ), - ], - ); - } -} - -class _CircularProgressPainter extends CustomPainter { - final double progress; - final Color color; - final Color backgroundColor; - final double strokeWidth; - - _CircularProgressPainter({ - required this.progress, - required this.color, - required this.backgroundColor, - required this.strokeWidth, - }); - - @override - void paint(Canvas canvas, Size size) { - final center = Offset(size.width / 2, size.height / 2); - final radius = (size.width - strokeWidth) / 2; - - final backgroundPaint = Paint() - ..color = backgroundColor - ..style = PaintingStyle.stroke - ..strokeWidth = strokeWidth; - - canvas.drawCircle(center, radius, backgroundPaint); - - final progressPaint = Paint() - ..color = color - ..style = PaintingStyle.stroke - ..strokeWidth = strokeWidth - ..strokeCap = StrokeCap.round; - - final sweepAngle = 2 * math.pi * progress; - // Start from top (-pi/2) - canvas.drawArc( - Rect.fromCircle(center: center, radius: radius), - -math.pi / 2, - sweepAngle, - false, - progressPaint, - ); - } - - @override - bool shouldRepaint(covariant CustomPainter oldDelegate) => true; -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/improve_yourself_widget.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/improve_yourself_widget.dart deleted file mode 100644 index 4a6ab75e..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/improve_yourself_widget.dart +++ /dev/null @@ -1,119 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; - -class ImproveYourselfWidget extends StatelessWidget { - const ImproveYourselfWidget({super.key}); - - final List> items = const [ - { - 'id': 'training', - 'title': 'Training Section', - 'description': 'Improve your skills and get certified.', - 'image': - 'https://images.unsplash.com/photo-1524995997946-a1c2e315a42f?w=400&h=300&fit=crop', - 'page': '/krow-university', - }, - { - 'id': 'podcast', - 'title': 'Krow Podcast', - 'description': 'Listen to tips from top workers.', - 'image': - 'https://images.unsplash.com/photo-1478737270239-2f02b77fc618?w=400&h=300&fit=crop', - 'page': '/krow-university', - }, - ]; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "Improve Yourself", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - const SizedBox(height: 12), - SingleChildScrollView( - scrollDirection: Axis.horizontal, - clipBehavior: Clip.none, - child: Row( - children: items.map((item) => _buildCard(context, item)).toList(), - ), - ), - ], - ); - } - - Widget _buildCard(BuildContext context, Map item) { - return GestureDetector( - onTap: () => context.push(item['page']!), - child: Container( - width: 160, - margin: const EdgeInsets.only(right: 12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: Colors.grey.shade100), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - clipBehavior: Clip.antiAlias, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: 96, - width: double.infinity, - child: Image.network( - item['image']!, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) => Container( - color: Colors.grey.shade200, - child: const Icon( - Icons.image_not_supported, - color: Colors.grey, - ), - ), - ), - ), - Padding( - padding: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - item['title']!, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - const SizedBox(height: 2), - Text( - item['description']!, - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), // slate-500 - ), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - ], - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/more_ways_widget.dart b/apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/more_ways_widget.dart deleted file mode 100644 index 0ee2e47f..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/lib/widgets/worker/more_ways_widget.dart +++ /dev/null @@ -1,102 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; - -class MoreWaysToUseKrowWidget extends StatelessWidget { - const MoreWaysToUseKrowWidget({super.key}); - - final List> items = const [ - { - 'id': 'benefits', - 'title': 'Krow Benefits', - 'image': - 'https://images.unsplash.com/photo-1481627834876-b7833e8f5570?w=400&h=300&fit=crop', - 'page': '/benefits', - }, - { - 'id': 'refer', - 'title': 'Refer a Friend', - 'image': - 'https://images.unsplash.com/photo-1529156069898-49953e39b3ac?w=400&h=300&fit=crop', - 'page': '/worker-profile', - }, - ]; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - "More Ways To Use Krow", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - const SizedBox(height: 12), - SingleChildScrollView( - scrollDirection: Axis.horizontal, - clipBehavior: Clip.none, - child: Row( - children: items.map((item) => _buildCard(context, item)).toList(), - ), - ), - ], - ); - } - - Widget _buildCard(BuildContext context, Map item) { - return GestureDetector( - onTap: () => context.push(item['page']!), - child: Container( - width: 160, - margin: const EdgeInsets.only(right: 12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: Colors.grey.shade100), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - clipBehavior: Clip.antiAlias, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: 96, - width: double.infinity, - child: Image.network( - item['image']!, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) => Container( - color: Colors.grey.shade200, - child: const Icon( - Icons.image_not_supported, - color: Colors.grey, - ), - ), - ), - ), - Padding( - padding: const EdgeInsets.all(12), - child: Text( - item['title']!, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/linux/.gitignore b/apps/mobile/prototypes/staff_mobile_application/linux/.gitignore deleted file mode 100644 index d3896c98..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/linux/.gitignore +++ /dev/null @@ -1 +0,0 @@ -flutter/ephemeral diff --git a/apps/mobile/prototypes/staff_mobile_application/linux/CMakeLists.txt b/apps/mobile/prototypes/staff_mobile_application/linux/CMakeLists.txt deleted file mode 100644 index ba0b4567..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/linux/CMakeLists.txt +++ /dev/null @@ -1,128 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.13) -project(runner LANGUAGES CXX) - -# The name of the executable created for the application. Change this to change -# the on-disk name of your application. -set(BINARY_NAME "staff_app_mvp") -# The unique GTK application identifier for this application. See: -# https://wiki.gnome.org/HowDoI/ChooseApplicationID -set(APPLICATION_ID "com.example.staff_app_mvp") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(SET CMP0063 NEW) - -# Load bundled libraries from the lib/ directory relative to the binary. -set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") - -# Root filesystem for cross-building. -if(FLUTTER_TARGET_PLATFORM_SYSROOT) - set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) - set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -endif() - -# Define build configuration options. -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") -endif() - -# Compilation settings that should be applied to most targets. -# -# Be cautious about adding new options here, as plugins use this function by -# default. In most cases, you should add new options to specific targets instead -# of modifying this function. -function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror) - target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") - target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") -endfunction() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# System-level dependencies. -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) - -# Application build; see runner/CMakeLists.txt. -add_subdirectory("runner") - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble) - -# Only the install-generated bundle's copy of the executable will launch -# correctly, since the resources must in the right relative locations. To avoid -# people trying to run the unbundled copy, put it in a subdirectory instead of -# the default top-level location. -set_target_properties(${BINARY_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" -) - - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# By default, "installing" just makes a relocatable bundle in the build -# directory. -set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() - -# Start with a clean build bundle directory every time. -install(CODE " - file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") - " COMPONENT Runtime) - -set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") -set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") - -install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) - install(FILES "${bundled_library}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endforeach(bundled_library) - -# Copy the native assets provided by the build.dart from all packages. -set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") -install(DIRECTORY "${NATIVE_ASSETS_DIR}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -# Fully re-copy the assets directory on each build to avoid having stale files -# from a previous install. -set(FLUTTER_ASSET_DIR_NAME "flutter_assets") -install(CODE " - file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") - " COMPONENT Runtime) -install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) - -# Install the AOT library on non-Debug builds only. -if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") - install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() diff --git a/apps/mobile/prototypes/staff_mobile_application/linux/flutter/CMakeLists.txt b/apps/mobile/prototypes/staff_mobile_application/linux/flutter/CMakeLists.txt deleted file mode 100644 index d5bd0164..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/linux/flutter/CMakeLists.txt +++ /dev/null @@ -1,88 +0,0 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.10) - -set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") - -# Configuration provided via flutter tool. -include(${EPHEMERAL_DIR}/generated_config.cmake) - -# TODO: Move the rest of this into files in ephemeral. See -# https://github.com/flutter/flutter/issues/57146. - -# Serves the same purpose as list(TRANSFORM ... PREPEND ...), -# which isn't available in 3.10. -function(list_prepend LIST_NAME PREFIX) - set(NEW_LIST "") - foreach(element ${${LIST_NAME}}) - list(APPEND NEW_LIST "${PREFIX}${element}") - endforeach(element) - set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) -endfunction() - -# === Flutter Library === -# System-level dependencies. -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) -pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) -pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) - -set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") - -# Published to parent scope for install step. -set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) -set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) -set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) -set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) - -list(APPEND FLUTTER_LIBRARY_HEADERS - "fl_basic_message_channel.h" - "fl_binary_codec.h" - "fl_binary_messenger.h" - "fl_dart_project.h" - "fl_engine.h" - "fl_json_message_codec.h" - "fl_json_method_codec.h" - "fl_message_codec.h" - "fl_method_call.h" - "fl_method_channel.h" - "fl_method_codec.h" - "fl_method_response.h" - "fl_plugin_registrar.h" - "fl_plugin_registry.h" - "fl_standard_message_codec.h" - "fl_standard_method_codec.h" - "fl_string_codec.h" - "fl_value.h" - "fl_view.h" - "flutter_linux.h" -) -list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") -add_library(flutter INTERFACE) -target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" -) -target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") -target_link_libraries(flutter INTERFACE - PkgConfig::GTK - PkgConfig::GLIB - PkgConfig::GIO -) -add_dependencies(flutter flutter_assemble) - -# === Flutter tool backend === -# _phony_ is a non-existent file to force this command to run every time, -# since currently there's no way to get a full input/output list from the -# flutter tool. -add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CMAKE_CURRENT_BINARY_DIR}/_phony_ - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} - VERBATIM -) -add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} -) diff --git a/apps/mobile/prototypes/staff_mobile_application/linux/flutter/generated_plugin_registrant.cc b/apps/mobile/prototypes/staff_mobile_application/linux/flutter/generated_plugin_registrant.cc deleted file mode 100644 index e71a16d2..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/linux/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,11 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - - -void fl_register_plugins(FlPluginRegistry* registry) { -} diff --git a/apps/mobile/prototypes/staff_mobile_application/linux/flutter/generated_plugin_registrant.h b/apps/mobile/prototypes/staff_mobile_application/linux/flutter/generated_plugin_registrant.h deleted file mode 100644 index e0f0a47b..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/linux/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void fl_register_plugins(FlPluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/apps/mobile/prototypes/staff_mobile_application/linux/flutter/generated_plugins.cmake b/apps/mobile/prototypes/staff_mobile_application/linux/flutter/generated_plugins.cmake deleted file mode 100644 index 2e1de87a..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/linux/flutter/generated_plugins.cmake +++ /dev/null @@ -1,23 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/apps/mobile/prototypes/staff_mobile_application/linux/runner/CMakeLists.txt b/apps/mobile/prototypes/staff_mobile_application/linux/runner/CMakeLists.txt deleted file mode 100644 index e97dabc7..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/linux/runner/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -cmake_minimum_required(VERSION 3.13) -project(runner LANGUAGES CXX) - -# Define the application target. To change its name, change BINARY_NAME in the -# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer -# work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add preprocessor definitions for the application ID. -add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") - -# Add dependency libraries. Add any application-specific dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter) -target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) - -target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/apps/mobile/prototypes/staff_mobile_application/linux/runner/main.cc b/apps/mobile/prototypes/staff_mobile_application/linux/runner/main.cc deleted file mode 100644 index e7c5c543..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/linux/runner/main.cc +++ /dev/null @@ -1,6 +0,0 @@ -#include "my_application.h" - -int main(int argc, char** argv) { - g_autoptr(MyApplication) app = my_application_new(); - return g_application_run(G_APPLICATION(app), argc, argv); -} diff --git a/apps/mobile/prototypes/staff_mobile_application/linux/runner/my_application.cc b/apps/mobile/prototypes/staff_mobile_application/linux/runner/my_application.cc deleted file mode 100644 index e35b1dcf..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/linux/runner/my_application.cc +++ /dev/null @@ -1,148 +0,0 @@ -#include "my_application.h" - -#include -#ifdef GDK_WINDOWING_X11 -#include -#endif - -#include "flutter/generated_plugin_registrant.h" - -struct _MyApplication { - GtkApplication parent_instance; - char** dart_entrypoint_arguments; -}; - -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) - -// Called when first Flutter frame received. -static void first_frame_cb(MyApplication* self, FlView* view) { - gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view))); -} - -// Implements GApplication::activate. -static void my_application_activate(GApplication* application) { - MyApplication* self = MY_APPLICATION(application); - GtkWindow* window = - GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - - // Use a header bar when running in GNOME as this is the common style used - // by applications and is the setup most users will be using (e.g. Ubuntu - // desktop). - // If running on X and not using GNOME then just use a traditional title bar - // in case the window manager does more exotic layout, e.g. tiling. - // If running on Wayland assume the header bar will work (may need changing - // if future cases occur). - gboolean use_header_bar = TRUE; -#ifdef GDK_WINDOWING_X11 - GdkScreen* screen = gtk_window_get_screen(window); - if (GDK_IS_X11_SCREEN(screen)) { - const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); - if (g_strcmp0(wm_name, "GNOME Shell") != 0) { - use_header_bar = FALSE; - } - } -#endif - if (use_header_bar) { - GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_widget_show(GTK_WIDGET(header_bar)); - gtk_header_bar_set_title(header_bar, "staff_app_mvp"); - gtk_header_bar_set_show_close_button(header_bar, TRUE); - gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); - } else { - gtk_window_set_title(window, "staff_app_mvp"); - } - - gtk_window_set_default_size(window, 1280, 720); - - g_autoptr(FlDartProject) project = fl_dart_project_new(); - fl_dart_project_set_dart_entrypoint_arguments( - project, self->dart_entrypoint_arguments); - - FlView* view = fl_view_new(project); - GdkRGBA background_color; - // Background defaults to black, override it here if necessary, e.g. #00000000 - // for transparent. - gdk_rgba_parse(&background_color, "#000000"); - fl_view_set_background_color(view, &background_color); - gtk_widget_show(GTK_WIDGET(view)); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); - - // Show the window when Flutter renders. - // Requires the view to be realized so we can start rendering. - g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), - self); - gtk_widget_realize(GTK_WIDGET(view)); - - fl_register_plugins(FL_PLUGIN_REGISTRY(view)); - - gtk_widget_grab_focus(GTK_WIDGET(view)); -} - -// Implements GApplication::local_command_line. -static gboolean my_application_local_command_line(GApplication* application, - gchar*** arguments, - int* exit_status) { - MyApplication* self = MY_APPLICATION(application); - // Strip out the first argument as it is the binary name. - self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); - - g_autoptr(GError) error = nullptr; - if (!g_application_register(application, nullptr, &error)) { - g_warning("Failed to register: %s", error->message); - *exit_status = 1; - return TRUE; - } - - g_application_activate(application); - *exit_status = 0; - - return TRUE; -} - -// Implements GApplication::startup. -static void my_application_startup(GApplication* application) { - // MyApplication* self = MY_APPLICATION(object); - - // Perform any actions required at application startup. - - G_APPLICATION_CLASS(my_application_parent_class)->startup(application); -} - -// Implements GApplication::shutdown. -static void my_application_shutdown(GApplication* application) { - // MyApplication* self = MY_APPLICATION(object); - - // Perform any actions required at application shutdown. - - G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); -} - -// Implements GObject::dispose. -static void my_application_dispose(GObject* object) { - MyApplication* self = MY_APPLICATION(object); - g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); - G_OBJECT_CLASS(my_application_parent_class)->dispose(object); -} - -static void my_application_class_init(MyApplicationClass* klass) { - G_APPLICATION_CLASS(klass)->activate = my_application_activate; - G_APPLICATION_CLASS(klass)->local_command_line = - my_application_local_command_line; - G_APPLICATION_CLASS(klass)->startup = my_application_startup; - G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; - G_OBJECT_CLASS(klass)->dispose = my_application_dispose; -} - -static void my_application_init(MyApplication* self) {} - -MyApplication* my_application_new() { - // Set the program name to the application ID, which helps various systems - // like GTK and desktop environments map this running application to its - // corresponding .desktop file. This ensures better integration by allowing - // the application to be recognized beyond its binary name. - g_set_prgname(APPLICATION_ID); - - return MY_APPLICATION(g_object_new(my_application_get_type(), - "application-id", APPLICATION_ID, "flags", - G_APPLICATION_NON_UNIQUE, nullptr)); -} diff --git a/apps/mobile/prototypes/staff_mobile_application/linux/runner/my_application.h b/apps/mobile/prototypes/staff_mobile_application/linux/runner/my_application.h deleted file mode 100644 index db16367a..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/linux/runner/my_application.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef FLUTTER_MY_APPLICATION_H_ -#define FLUTTER_MY_APPLICATION_H_ - -#include - -G_DECLARE_FINAL_TYPE(MyApplication, - my_application, - MY, - APPLICATION, - GtkApplication) - -/** - * my_application_new: - * - * Creates a new Flutter-based application. - * - * Returns: a new #MyApplication. - */ -MyApplication* my_application_new(); - -#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/.gitignore b/apps/mobile/prototypes/staff_mobile_application/macos/.gitignore deleted file mode 100644 index 746adbb6..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Flutter-related -**/Flutter/ephemeral/ -**/Pods/ - -# Xcode-related -**/dgph -**/xcuserdata/ diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Flutter/Flutter-Debug.xcconfig b/apps/mobile/prototypes/staff_mobile_application/macos/Flutter/Flutter-Debug.xcconfig deleted file mode 100644 index 4b81f9b2..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Flutter/Flutter-Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Flutter/Flutter-Release.xcconfig b/apps/mobile/prototypes/staff_mobile_application/macos/Flutter/Flutter-Release.xcconfig deleted file mode 100644 index 5caa9d15..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Flutter/Flutter-Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Flutter/GeneratedPluginRegistrant.swift b/apps/mobile/prototypes/staff_mobile_application/macos/Flutter/GeneratedPluginRegistrant.swift deleted file mode 100644 index f9c2b8ab..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Flutter/GeneratedPluginRegistrant.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// Generated file. Do not edit. -// - -import FlutterMacOS -import Foundation - -import firebase_core -import path_provider_foundation - -func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) -} diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Podfile b/apps/mobile/prototypes/staff_mobile_application/macos/Podfile deleted file mode 100644 index ff5ddb3b..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Podfile +++ /dev/null @@ -1,42 +0,0 @@ -platform :osx, '10.15' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_macos_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_macos_build_settings(target) - end -end diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcodeproj/project.pbxproj b/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index f0915628..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,705 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXAggregateTarget section */ - 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; - buildPhases = ( - 33CC111E2044C6BF0003C045 /* ShellScript */, - ); - dependencies = ( - ); - name = "Flutter Assemble"; - productName = FLX; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC10EC2044A3C60003C045; - remoteInfo = Runner; - }; - 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC111A2044C6BA0003C045; - remoteInfo = FLX; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 33CC110E2044A8840003C045 /* Bundle Framework */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Bundle Framework"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* staff_app_mvp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "staff_app_mvp.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; - 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; - 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; - 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; - 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 331C80D2294CF70F00263BE5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EA2044A3C60003C045 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C80D6294CF71000263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C80D7294CF71000263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 33BA886A226E78AF003329D5 /* Configs */ = { - isa = PBXGroup; - children = ( - 33E5194F232828860026EE4D /* AppInfo.xcconfig */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, - ); - path = Configs; - sourceTree = ""; - }; - 33CC10E42044A3C60003C045 = { - isa = PBXGroup; - children = ( - 33FAB671232836740065AC1E /* Runner */, - 33CEB47122A05771004F2AC0 /* Flutter */, - 331C80D6294CF71000263BE5 /* RunnerTests */, - 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, - ); - sourceTree = ""; - }; - 33CC10EE2044A3C60003C045 /* Products */ = { - isa = PBXGroup; - children = ( - 33CC10ED2044A3C60003C045 /* staff_app_mvp.app */, - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 33CC11242044D66E0003C045 /* Resources */ = { - isa = PBXGroup; - children = ( - 33CC10F22044A3C60003C045 /* Assets.xcassets */, - 33CC10F42044A3C60003C045 /* MainMenu.xib */, - 33CC10F72044A3C60003C045 /* Info.plist */, - ); - name = Resources; - path = ..; - sourceTree = ""; - }; - 33CEB47122A05771004F2AC0 /* Flutter */ = { - isa = PBXGroup; - children = ( - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, - ); - path = Flutter; - sourceTree = ""; - }; - 33FAB671232836740065AC1E /* Runner */ = { - isa = PBXGroup; - children = ( - 33CC10F02044A3C60003C045 /* AppDelegate.swift */, - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, - 33E51913231747F40026EE4D /* DebugProfile.entitlements */, - 33E51914231749380026EE4D /* Release.entitlements */, - 33CC11242044D66E0003C045 /* Resources */, - 33BA886A226E78AF003329D5 /* Configs */, - ); - path = Runner; - sourceTree = ""; - }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { - isa = PBXGroup; - children = ( - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C80D4294CF70F00263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 331C80D1294CF70F00263BE5 /* Sources */, - 331C80D2294CF70F00263BE5 /* Frameworks */, - 331C80D3294CF70F00263BE5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 331C80DA294CF71000263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 33CC10EC2044A3C60003C045 /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 33CC10E92044A3C60003C045 /* Sources */, - 33CC10EA2044A3C60003C045 /* Frameworks */, - 33CC10EB2044A3C60003C045 /* Resources */, - 33CC110E2044A8840003C045 /* Bundle Framework */, - 3399D490228B24CF009A79C7 /* ShellScript */, - ); - buildRules = ( - ); - dependencies = ( - 33CC11202044C79F0003C045 /* PBXTargetDependency */, - ); - name = Runner; - productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* staff_app_mvp.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 33CC10E52044A3C60003C045 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C80D4294CF70F00263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 33CC10EC2044A3C60003C045; - }; - 33CC10EC2044A3C60003C045 = { - CreatedOnToolsVersion = 9.2; - LastSwiftMigration = 1100; - ProvisioningStyle = Automatic; - SystemCapabilities = { - com.apple.Sandbox = { - enabled = 1; - }; - }; - }; - 33CC111A2044C6BA0003C045 = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Manual; - }; - }; - }; - buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 33CC10E42044A3C60003C045; - productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 33CC10EC2044A3C60003C045 /* Runner */, - 331C80D4294CF70F00263BE5 /* RunnerTests */, - 33CC111A2044C6BA0003C045 /* Flutter Assemble */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C80D3294CF70F00263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EB2044A3C60003C045 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3399D490228B24CF009A79C7 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; - }; - 33CC111E2044C6BF0003C045 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - Flutter/ephemeral/FlutterInputs.xcfilelist, - ); - inputPaths = ( - Flutter/ephemeral/tripwire, - ); - outputFileListPaths = ( - Flutter/ephemeral/FlutterOutputs.xcfilelist, - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C80D1294CF70F00263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10E92044A3C60003C045 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC10EC2044A3C60003C045 /* Runner */; - targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; - }; - 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; - targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 33CC10F52044A3C60003C045 /* Base */, - ); - name = MainMenu.xib; - path = Runner; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 331C80DB294CF71000263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.staffAppMvp.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/staff_app_mvp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/staff_app_mvp"; - }; - name = Debug; - }; - 331C80DC294CF71000263BE5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.staffAppMvp.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/staff_app_mvp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/staff_app_mvp"; - }; - name = Release; - }; - 331C80DD294CF71000263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.staffAppMvp.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/staff_app_mvp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/staff_app_mvp"; - }; - name = Profile; - }; - 338D0CE9231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Profile; - }; - 338D0CEA231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; - }; - name = Profile; - }; - 338D0CEB231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Profile; - }; - 33CC10F92044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 33CC10FA2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Release; - }; - 33CC10FC2044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 33CC10FD2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 33CC111C2044C6BA0003C045 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 33CC111D2044C6BA0003C045 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C80DB294CF71000263BE5 /* Debug */, - 331C80DC294CF71000263BE5 /* Release */, - 331C80DD294CF71000263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10F92044A3C60003C045 /* Debug */, - 33CC10FA2044A3C60003C045 /* Release */, - 338D0CE9231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10FC2044A3C60003C045 /* Debug */, - 33CC10FD2044A3C60003C045 /* Release */, - 338D0CEA231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC111C2044C6BA0003C045 /* Debug */, - 33CC111D2044C6BA0003C045 /* Release */, - 338D0CEB231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 33CC10E52044A3C60003C045 /* Project object */; -} diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index 8b7ea736..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcworkspace/contents.xcworkspacedata b/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 1d526a16..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/AppDelegate.swift b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/AppDelegate.swift deleted file mode 100644 index b3c17614..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Cocoa -import FlutterMacOS - -@main -class AppDelegate: FlutterAppDelegate { - override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { - return true - } - - override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { - return true - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a2ec33f1..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "images" : [ - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" - }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png deleted file mode 100644 index 82b6f9d9a33e198f5747104729e1fcef999772a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102994 zcmeEugo5nb1G~3xi~y`}h6XHx5j$(L*3|5S2UfkG$|UCNI>}4f?MfqZ+HW-sRW5RKHEm z^unW*Xx{AH_X3Xdvb%C(Bh6POqg==@d9j=5*}oEny_IS;M3==J`P0R!eD6s~N<36C z*%-OGYqd0AdWClO!Z!}Y1@@RkfeiQ$Ib_ z&fk%T;K9h`{`cX3Hu#?({4WgtmkR!u3ICS~|NqH^fdNz>51-9)OF{|bRLy*RBv#&1 z3Oi_gk=Y5;>`KbHf~w!`u}!&O%ou*Jzf|Sf?J&*f*K8cftMOKswn6|nb1*|!;qSrlw= zr-@X;zGRKs&T$y8ENnFU@_Z~puu(4~Ir)>rbYp{zxcF*!EPS6{(&J}qYpWeqrPWW< zfaApz%<-=KqxrqLLFeV3w0-a0rEaz9&vv^0ZfU%gt9xJ8?=byvNSb%3hF^X_n7`(fMA;C&~( zM$cQvQ|g9X)1AqFvbp^B{JEX$o;4iPi?+v(!wYrN{L}l%e#5y{j+1NMiT-8=2VrCP zmFX9=IZyAYA5c2!QO96Ea-6;v6*$#ZKM-`%JCJtrA3d~6h{u+5oaTaGE)q2b+HvdZ zvHlY&9H&QJ5|uG@wDt1h99>DdHy5hsx)bN`&G@BpxAHh$17yWDyw_jQhhjSqZ=e_k z_|r3=_|`q~uA47y;hv=6-o6z~)gO}ZM9AqDJsR$KCHKH;QIULT)(d;oKTSPDJ}Jx~G#w-(^r<{GcBC*~4bNjfwHBumoPbU}M)O za6Hc2ik)2w37Yyg!YiMq<>Aov?F2l}wTe+>h^YXcK=aesey^i)QC_p~S zp%-lS5%)I29WfywP(r4@UZ@XmTkqo51zV$|U|~Lcap##PBJ}w2b4*kt7x6`agP34^ z5fzu_8rrH+)2u*CPcr6I`gL^cI`R2WUkLDE5*PX)eJU@H3HL$~o_y8oMRoQ0WF9w| z6^HZDKKRDG2g;r8Z4bn+iJNFV(CG;K-j2>aj229gl_C6n12Jh$$h!}KVhn>*f>KcH z;^8s3t(ccVZ5<{>ZJK@Z`hn_jL{bP8Yn(XkwfRm?GlEHy=T($8Z1Mq**IM`zxN9>-yXTjfB18m_$E^JEaYn>pj`V?n#Xu;Z}#$- zw0Vw;T*&9TK$tKI7nBk9NkHzL++dZ^;<|F6KBYh2+XP-b;u`Wy{~79b%IBZa3h*3^ zF&BKfQ@Ej{7ku_#W#mNJEYYp=)bRMUXhLy2+SPMfGn;oBsiG_6KNL8{p1DjuB$UZB zA)a~BkL)7?LJXlCc}bB~j9>4s7tlnRHC5|wnycQPF_jLl!Avs2C3^lWOlHH&v`nGd zf&U!fn!JcZWha`Pl-B3XEe;(ks^`=Z5R zWyQR0u|do2`K3ec=YmWGt5Bwbu|uBW;6D8}J3{Uep7_>L6b4%(d=V4m#(I=gkn4HT zYni3cnn>@F@Wr<hFAY3Y~dW+3bte;70;G?kTn4Aw5nZ^s5|47 z4$rCHCW%9qa4)4vE%^QPMGf!ET!^LutY$G zqdT(ub5T5b+wi+OrV}z3msoy<4)`IPdHsHJggmog0K*pFYMhH!oZcgc5a)WmL?;TPSrerTVPp<#s+imF3v#!FuBNNa`#6 z!GdTCF|IIpz#(eV^mrYKThA4Bnv&vQet@%v9kuRu3EHx1-2-it@E`%9#u`)HRN#M? z7aJ{wzKczn#w^`OZ>Jb898^Xxq)0zd{3Tu7+{-sge-rQ z&0PME&wIo6W&@F|%Z8@@N3)@a_ntJ#+g{pUP7i?~3FirqU`rdf8joMG^ld?(9b7Iv z>TJgBg#)(FcW)h!_if#cWBh}f+V08GKyg|$P#KTS&%=!+0a%}O${0$i)kn9@G!}En zv)_>s?glPiLbbx)xk(lD-QbY(OP3;MSXM5E*P&_`Zks2@46n|-h$Y2L7B)iH{GAAq19h5-y0q>d^oy^y+soJu9lXxAe%jcm?=pDLFEG2kla40e!5a}mpe zdL=WlZ=@U6{>g%5a+y-lx)01V-x;wh%F{=qy#XFEAqcd+m}_!lQ)-9iiOL%&G??t| z?&NSdaLqdPdbQs%y0?uIIHY7rw1EDxtQ=DU!i{)Dkn~c$LG5{rAUYM1j5*G@oVn9~ zizz{XH(nbw%f|wI=4rw^6mNIahQpB)OQy10^}ACdLPFc2@ldVi|v@1nWLND?)53O5|fg`RZW&XpF&s3@c-R?aad!$WoH6u0B|}zt)L($E^@U- zO#^fxu9}Zw7Xl~nG1FVM6DZSR0*t!4IyUeTrnp@?)Z)*!fhd3)&s(O+3D^#m#bAem zpf#*aiG_0S^ofpm@9O7j`VfLU0+{$x!u^}3!zp=XST0N@DZTp!7LEVJgqB1g{psNr za0uVmh3_9qah14@M_pi~vAZ#jc*&aSm$hCNDsuQ-zPe&*Ii#2=2gP+DP4=DY z_Y0lUsyE6yaV9)K)!oI6+*4|spx2at*30CAx~6-5kfJzQ`fN8$!lz%hz^J6GY?mVH zbYR^JZ(Pmj6@vy-&!`$5soyy-NqB^8cCT40&R@|6s@m+ZxPs=Bu77-+Os7+bsz4nA3DrJ8#{f98ZMaj-+BD;M+Jk?pgFcZIb}m9N z{ct9T)Kye&2>l^39O4Q2@b%sY?u#&O9PO4@t0c$NUXG}(DZJ<;_oe2~e==3Z1+`Zo zFrS3ns-c}ZognVBHbg#e+1JhC(Yq7==rSJQ8J~}%94(O#_-zJKwnBXihl#hUd9B_>+T& z7eHHPRC?5ONaUiCF7w|{J`bCWS7Q&xw-Sa={j-f)n5+I=9s;E#fBQB$`DDh<^mGiF zu-m_k+)dkBvBO(VMe2O4r^sf3;sk9K!xgXJU>|t9Vm8Ty;fl5pZzw z9j|}ZD}6}t;20^qrS?YVPuPRS<39d^y0#O1o_1P{tN0?OX!lc-ICcHI@2#$cY}_CY zev|xdFcRTQ_H)1fJ7S0*SpPs8e{d+9lR~IZ^~dKx!oxz?=Dp!fD`H=LH{EeC8C&z-zK$e=!5z8NL=4zx2{hl<5z*hEmO=b-7(k5H`bA~5gT30Sjy`@-_C zKM}^so9Ti1B;DovHByJkTK87cfbF16sk-G>`Q4-txyMkyQS$d}??|Aytz^;0GxvOs zPgH>h>K+`!HABVT{sYgzy3CF5ftv6hI-NRfgu613d|d1cg^jh+SK7WHWaDX~hlIJ3 z>%WxKT0|Db1N-a4r1oPKtF--^YbP=8Nw5CNt_ZnR{N(PXI>Cm$eqi@_IRmJ9#)~ZHK_UQ8mi}w^`+4$OihUGVz!kW^qxnCFo)-RIDbA&k-Y=+*xYv5y4^VQ9S)4W5Pe?_RjAX6lS6Nz#!Hry=+PKx2|o_H_3M`}Dq{Bl_PbP(qel~P@=m}VGW*pK96 zI@fVag{DZHi}>3}<(Hv<7cVfWiaVLWr@WWxk5}GDEbB<+Aj;(c>;p1qmyAIj+R!`@#jf$ zy4`q23L-72Zs4j?W+9lQD;CYIULt%;O3jPWg2a%Zs!5OW>5h1y{Qof!p&QxNt5=T( zd5fy&7=hyq;J8%86YBOdc$BbIFxJx>dUyTh`L z-oKa=OhRK9UPVRWS`o2x53bAv+py)o)kNL6 z9W1Dlk-g6Ht@-Z^#6%`9S9`909^EMj?9R^4IxssCY-hYzei^TLq7Cj>z$AJyaU5=z zl!xiWvz0U8kY$etrcp8mL;sYqGZD!Hs-U2N{A|^oEKA482v1T%cs%G@X9M?%lX)p$ zZoC7iYTPe8yxY0Jne|s)fCRe1mU=Vb1J_&WcIyP|x4$;VSVNC`M+e#oOA`#h>pyU6 z?7FeVpk`Hsu`~T3i<_4<5fu?RkhM;@LjKo6nX>pa%8dSdgPO9~Jze;5r>Tb1Xqh5q z&SEdTXevV@PT~!O6z|oypTk7Qq+BNF5IQ(8s18c=^0@sc8Gi|3e>VKCsaZ?6=rrck zl@oF5Bd0zH?@15PxSJIRroK4Wa?1o;An;p0#%ZJ^tI=(>AJ2OY0GP$E_3(+Zz4$AQ zW)QWl<4toIJ5TeF&gNXs>_rl}glkeG#GYbHHOv-G!%dJNoIKxn)FK$5&2Zv*AFic! z@2?sY&I*PSfZ8bU#c9fdIJQa_cQijnj39-+hS@+~e*5W3bj%A}%p9N@>*tCGOk+cF zlcSzI6j%Q|2e>QG3A<86w?cx6sBtLNWF6_YR?~C)IC6_10SNoZUHrCpp6f^*+*b8` zlx4ToZZuI0XW1W)24)92S)y0QZa);^NRTX6@gh8@P?^=#2dV9s4)Q@K+gnc{6|C}& zDLHr7nDOLrsH)L@Zy{C_2UrYdZ4V{|{c8&dRG;wY`u>w%$*p>PO_}3`Y21pk?8Wtq zGwIXTulf7AO2FkPyyh2TZXM1DJv>hI`}x`OzQI*MBc#=}jaua&czSkI2!s^rOci|V zFkp*Vbiz5vWa9HPFXMi=BV&n3?1?%8#1jq?p^3wAL`jgcF)7F4l<(H^!i=l-(OTDE zxf2p71^WRIExLf?ig0FRO$h~aA23s#L zuZPLkm>mDwBeIu*C7@n@_$oSDmdWY7*wI%aL73t~`Yu7YwE-hxAATmOi0dmB9|D5a zLsR7OQcA0`vN9m0L|5?qZ|jU+cx3_-K2!K$zDbJ$UinQy<9nd5ImWW5n^&=Gg>Gsh zY0u?m1e^c~Ug39M{{5q2L~ROq#c{eG8Oy#5h_q=#AJj2Yops|1C^nv0D1=fBOdfAG z%>=vl*+_w`&M7{qE#$xJJp_t>bSh7Mpc(RAvli9kk3{KgG5K@a-Ue{IbU{`umXrR3ra5Y7xiX42+Q%N&-0#`ae_ z#$Y6Wa++OPEDw@96Zz##PFo9sADepQe|hUy!Zzc2C(L`k9&=a8XFr+!hIS>D2{pdGP1SzwyaGLiH3j--P>U#TWw90t8{8Bt%m7Upspl#=*hS zhy|(XL6HOqBW}Og^tLX7 z+`b^L{O&oqjwbxDDTg2B;Yh2(fW>%S5Pg8^u1p*EFb z`(fbUM0`afawYt%VBfD&b3MNJ39~Ldc@SAuzsMiN%E}5{uUUBc7hc1IUE~t-Y9h@e7PC|sv$xGx=hZiMXNJxz5V(np%6u{n24iWX#!8t#>Ob$in<>dw96H)oGdTHnU zSM+BPss*5)Wz@+FkooMxxXZP1{2Nz7a6BB~-A_(c&OiM)UUNoa@J8FGxtr$)`9;|O z(Q?lq1Q+!E`}d?KemgC!{nB1JJ!B>6J@XGQp9NeQvtbM2n7F%v|IS=XWPVZY(>oq$ zf=}8O_x`KOxZoGnp=y24x}k6?gl_0dTF!M!T`={`Ii{GnT1jrG9gPh)R=RZG8lIR| z{ZJ6`x8n|y+lZuy${fuEDTAf`OP!tGySLXD}ATJO5UoZv|Xo3%7O~L63+kw}v)Ci=&tWx3bQJfL@5O18CbPlkR^IcKA zy1=^Vl-K-QBP?9^R`@;czcUw;Enbbyk@vJQB>BZ4?;DM%BUf^eZE+sOy>a){qCY6Y znYy;KGpch-zf=5|p#SoAV+ie8M5(Xg-{FoLx-wZC9IutT!(9rJ8}=!$!h%!J+vE2e z(sURwqCC35v?1>C1L)swfA^sr16{yj7-zbT6Rf26-JoEt%U?+|rQ zeBuGohE?@*!zR9)1P|3>KmJSgK*fOt>N>j}LJB`>o(G#Dduvx7@DY7};W7K;Yj|8O zGF<+gTuoIKe7Rf+LQG3-V1L^|E;F*}bQ-{kuHq}| ze_NwA7~US19sAZ)@a`g*zkl*ykv2v3tPrb4Og2#?k6Lc7@1I~+ew48N&03hW^1Cx+ zfk5Lr4-n=#HYg<7ka5i>2A@ZeJ60gl)IDX!!p zzfXZQ?GrT>JEKl7$SH!otzK6=0dIlqN)c23YLB&Krf9v-{@V8p+-e2`ujFR!^M%*; ze_7(Jh$QgoqwB!HbX=S+^wqO15O_TQ0-qX8f-|&SOuo3ZE{{9Jw5{}>MhY}|GBhO& zv48s_B=9aYQfa;d>~1Z$y^oUUaDer>7ve5+Gf?rIG4GZ!hRKERlRNgg_C{W_!3tsI2TWbX8f~MY)1Q`6Wj&JJ~*;ay_0@e zzx+mE-pu8{cEcVfBqsnm=jFU?H}xj@%CAx#NO>3 z_re3Rq%d1Y7VkKy{=S73&p;4^Praw6Y59VCP6M?!Kt7{v#DG#tz?E)`K95gH_mEvb z%$<~_mQ$ad?~&T=O0i0?`YSp?E3Dj?V>n+uTRHAXn`l!pH9Mr}^D1d@mkf+;(tV45 zH_yfs^kOGLXlN*0GU;O&{=awxd?&`{JPRr$z<1HcAO2K`K}92$wC}ky&>;L?#!(`w z68avZGvb728!vgw>;8Z8I@mLtI`?^u6R>sK4E7%=y)jpmE$fH!Dj*~(dy~-2A5Cm{ zl{1AZw`jaDmfvaB?jvKwz!GC}@-Dz|bFm1OaPw(ia#?>vF7Y5oh{NVbyD~cHB1KFn z9C@f~X*Wk3>sQH9#D~rLPslAd26@AzMh=_NkH_yTNXx6-AdbAb z{Ul89YPHslD?xAGzOlQ*aMYUl6#efCT~WI zOvyiewT=~l1W(_2cEd(8rDywOwjM-7P9!8GCL-1<9KXXO=6%!9=W++*l1L~gRSxLVd8K=A7&t52ql=J&BMQu{fa6y zXO_e>d?4X)xp2V8e3xIQGbq@+vo#&n>-_WreTTW0Yr?|YRPP43cDYACMQ(3t6(?_k zfgDOAU^-pew_f5U#WxRXB30wcfDS3;k~t@b@w^GG&<5n$Ku?tT(%bQH(@UHQGN)N|nfC~7?(etU`}XB)$>KY;s=bYGY#kD%i9fz= z2nN9l?UPMKYwn9bX*^xX8Y@%LNPFU>s#Ea1DaP%bSioqRWi9JS28suTdJycYQ+tW7 zrQ@@=13`HS*dVKaVgcem-45+buD{B;mUbY$YYULhxK)T{S?EB<8^YTP$}DA{(&)@S zS#<8S96y9K2!lG^VW-+CkfXJIH;Vo6wh)N}!08bM$I7KEW{F6tqEQ?H@(U zAqfi%KCe}2NUXALo;UN&k$rU0BLNC$24T_mcNY(a@lxR`kqNQ0z%8m>`&1ro40HX} z{{3YQ;2F9JnVTvDY<4)x+88i@MtXE6TBd7POk&QfKU-F&*C`isS(T_Q@}K)=zW#K@ zbXpcAkTT-T5k}Wj$dMZl7=GvlcCMt}U`#Oon1QdPq%>9J$rKTY8#OmlnNWBYwafhx zqFnym@okL#Xw>4SeRFejBnZzY$jbO)e^&&sHBgMP%Ygfi!9_3hp17=AwLBNFTimf0 zw6BHNXw19Jg_Ud6`5n#gMpqe%9!QB^_7wAYv8nrW94A{*t8XZu0UT&`ZHfkd(F{Px zD&NbRJP#RX<=+sEeGs2`9_*J2OlECpR;4uJie-d__m*(aaGE}HIo+3P{my@;a~9Y$ zHBXVJ83#&@o6{M+pE9^lI<4meLLFN_3rwgR4IRyp)~OF0n+#ORrcJ2_On9-78bWbG zuCO0esc*n1X3@p1?lN{qWS?l7J$^jbpeel{w~51*0CM+q9@9X=>%MF(ce~om(}?td zjkUmdUR@LOn-~6LX#=@a%rvj&>DFEoQscOvvC@&ZB5jVZ-;XzAshwx$;Qf@U41W=q zOSSjQGQV8Qi3*4DngNMIM&Cxm7z*-K`~Bl(TcEUxjQ1c=?)?wF8W1g;bAR%sM#LK( z_Op?=P%)Z+J!>vpN`By0$?B~Out%P}kCriDq@}In&fa_ZyKV+nLM0E?hfxuu%ciUz z>yAk}OydbWNl7{)#112j&qmw;*Uj&B;>|;Qwfc?5wIYIHH}s6Mve@5c5r+y)jK9i( z_}@uC(98g)==AGkVN?4>o@w=7x9qhW^ zB(b5%%4cHSV?3M?k&^py)j*LK16T^Ef4tb05-h-tyrjt$5!oo4spEfXFK7r_Gfv7#x$bsR7T zs;dqxzUg9v&GjsQGKTP*=B(;)be2aN+6>IUz+Hhw-n>^|`^xu*xvjGPaDoFh2W4-n z@Wji{5Y$m>@Vt7TE_QVQN4*vcfWv5VY-dT0SV=l=8LAEq1go*f zkjukaDV=3kMAX6GAf0QOQHwP^{Z^=#Lc)sh`QB)Ftl&31jABvq?8!3bt7#8vxB z53M{4{GR4Hl~;W3r}PgXSNOt477cO62Yj(HcK&30zsmWpvAplCtpp&mC{`2Ue*Bwu zF&UX1;w%`Bs1u%RtGPFl=&sHu@Q1nT`z={;5^c^^S~^?2-?<|F9RT*KQmfgF!7=wD@hytxbD;=9L6PZrK*1<4HMObNWehA62DtTy)q5H|57 z9dePuC!1;0MMRRl!S@VJ8qG=v^~aEU+}2Qx``h1LII!y{crP2ky*R;Cb;g|r<#ryo zju#s4dE?5CTIZKc*O4^3qWflsQ(voX>(*_JP7>Q&$%zCAIBTtKC^JUi@&l6u&t0hXMXjz_y!;r@?k|OU9aD%938^TZ>V? zqJmom_6dz4DBb4Cgs_Ef@}F%+cRCR%UMa9pi<-KHN;t#O@cA%(LO1Rb=h?5jiTs93 zPLR78p+3t>z4|j=<>2i4b`ketv}9Ax#B0)hn7@bFl;rDfP8p7u9XcEb!5*PLKB(s7wQC2kzI^@ae)|DhNDmSy1bOLid%iIap@24A(q2XI!z_hkl-$1T10 z+KKugG4-}@u8(P^S3PW4x>an;XWEF-R^gB{`t8EiP{ZtAzoZ!JRuMRS__-Gg#Qa3{<;l__CgsF+nfmFNi}p z>rV!Y6B@cC>1up)KvaEQiAvQF!D>GCb+WZsGHjDeWFz?WVAHP65aIA8u6j6H35XNYlyy8>;cWe3ekr};b;$9)0G`zsc9LNsQ&D?hvuHRpBxH)r-1t9|Stc*u<}Ol&2N+wPMom}d15_TA=Aprp zjN-X3*Af$7cDWMWp##kOH|t;c2Pa9Ml4-)o~+7P;&q8teF-l}(Jt zTGKOQqJTeT!L4d}Qw~O0aanA$Vn9Rocp-MO4l*HK)t%hcp@3k0%&_*wwpKD6ThM)R z8k}&7?)YS1ZYKMiy?mn>VXiuzX7$Ixf7EW8+C4K^)m&eLYl%#T=MC;YPvD&w#$MMf zQ=>`@rh&&r!@X&v%ZlLF42L_c=5dSU^uymKVB>5O?AouR3vGv@ei%Z|GX5v1GK2R* zi!!}?+-8>J$JH^fPu@)E6(}9$d&9-j51T^n-e0Ze%Q^)lxuex$IL^XJ&K2oi`wG}QVGk2a7vC4X?+o^z zsCK*7`EUfSuQA*K@Plsi;)2GrayQOG9OYF82Hc@6aNN5ulqs1Of-(iZQdBI^U5of^ zZg2g=Xtad7$hfYu6l~KDQ}EU;oIj(3nO#u9PDz=eO3(iax7OCmgT2p_7&^3q zg7aQ;Vpng*)kb6=sd5?%j5Dm|HczSChMo8HHq_L8R;BR5<~DVyU$8*Tk5}g0eW5x7 z%d)JFZ{(Y<#OTKLBA1fwLM*fH7Q~7Sc2Ne;mVWqt-*o<;| z^1@vo_KTYaMnO$7fbLL+qh#R$9bvnpJ$RAqG+z8h|} z3F5iwG*(sCn9Qbyg@t0&G}3fE0jGq3J!JmG2K&$urx^$z95) z7h?;4vE4W=v)uZ*Eg3M^6f~|0&T)2D;f+L_?M*21-I1pnK(pT$5l#QNlT`SidYw~o z{`)G)Asv#cue)Ax1RNWiRUQ(tQ(bzd-f2U4xlJK+)ZWBxdq#fp=A>+Qc%-tl(c)`t z$e2Ng;Rjvnbu7((;v4LF9Y1?0el9hi!g>G{^37{ z`^s-03Z5jlnD%#Mix19zkU_OS|86^_x4<0(*YbPN}mi-$L?Z4K(M|2&VV*n*ZYN_UqI?eKZi3!b)i z%n3dzUPMc-dc|q}TzvPy!VqsEWCZL(-eURDRG4+;Eu!LugSSI4Fq$Ji$Dp08`pfP_C5Yx~`YKcywlMG;$F z)R5!kVml_Wv6MSpeXjG#g?kJ0t_MEgbXlUN3k|JJ%N>|2xn8yN>>4qxh!?dGI}s|Y zDTKd^JCrRSN+%w%D_uf=Tj6wIV$c*g8D96jb^Kc#>5Fe-XxKC@!pIJw0^zu;`_yeb zhUEm-G*C=F+jW%cP(**b61fTmPn2WllBr4SWNdKe*P8VabZsh0-R|?DO=0x`4_QY) zR7sthW^*BofW7{Sak&S1JdiG?e=SfL24Y#w_)xrBVhGB-13q$>mFU|wd9Xqe-o3{6 zSn@@1@&^)M$rxb>UmFuC+pkio#T;mSnroMVZJ%nZ!uImi?%KsIX#@JU2VY(`kGb1A z7+1MEG)wd@)m^R|a2rXeviv$!emwcY(O|M*xV!9%tBzarBOG<4%gI9SW;Um_gth4=gznYzOFd)y8e+3APCkL)i-OI`;@7-mCJgE`js(M} z;~ZcW{{FMVVO)W>VZ}ILouF#lWGb%Couu}TI4kubUUclW@jEn6B_^v!Ym*(T*4HF9 zWhNKi8%sS~viSdBtnrq!-Dc5(G^XmR>DFx8jhWvR%*8!m*b*R8e1+`7{%FACAK`7 zzdy8TmBh?FVZ0vtw6npnWwM~XjF2fNvV#ZlGG z?FxHkXHN>JqrBYoPo$)zNC7|XrQfcqmEXWud~{j?La6@kbHG@W{xsa~l1=%eLly8B z4gCIH05&Y;6O2uFSopNqP|<$ml$N40^ikxw0`o<~ywS1(qKqQN!@?Ykl|bE4M?P+e zo$^Vs_+x)iuw?^>>`$&lOQOUkZ5>+OLnRA)FqgpDjW&q*WAe(_mAT6IKS9;iZBl8M z<@=Y%zcQUaSBdrs27bVK`c$)h6A1GYPS$y(FLRD5Yl8E3j0KyH08#8qLrsc_qlws; znMV%Zq8k+&T2kf%6ZO^2=AE9>?a587g%-={X}IS~P*I(NeCF9_9&`)|ok0iiIun zo+^odT0&Z4k;rn7I1v87=z!zKU(%gfB$(1mrRYeO$sbqM22Kq68z9wgdg8HBxp>_< zn9o%`f?sVO=IN#5jSX&CGODWlZfQ9A)njK2O{JutYwRZ?n0G_p&*uwpE`Md$iQxrd zoQfF^b8Ou)+3BO_3_K5y*~?<(BF@1l+@?Z6;^;U>qlB)cdro;rxOS1M{Az$s^9o5sXDCg8yD<=(pKI*0e zLk>@lo#&s0)^*Q+G)g}C0IErqfa9VbL*Qe=OT@&+N8m|GJF7jd83vY#SsuEv2s{Q> z>IpoubNs>D_5?|kXGAPgF@mb_9<%hjU;S0C8idI)a=F#lPLuQJ^7OnjJlH_Sks9JD zMl1td%YsWq3YWhc;E$H1<0P$YbSTqs`JKY%(}svsifz|h8BHguL82dBl+z0^YvWk8 zGy;7Z0v5_FJ2A$P0wIr)lD?cPR%cz>kde!=W%Ta^ih+Dh4UKdf7ip?rBz@%y2&>`6 zM#q{JXvW9ZlaSk1oD!n}kSmcDa2v6T^Y-dy+#fW^y>eS8_%<7tWXUp8U@s$^{JFfKMjDAvR z$YmVB;n3ofl!ro9RNT!TpQpcycXCR}$9k5>IPWDXEenQ58os?_weccrT+Bh5sLoiH zZ_7~%t(vT)ZTEO= zb0}@KaD{&IyK_sd8b$`Qz3%UA`nSo zn``!BdCeN!#^G;lK@G2ron*0jQhbdw)%m$2;}le@z~PSLnU-z@tL)^(p%P>OO^*Ff zNRR9oQ`W+x^+EU+3BpluwK77|B3=8QyT|$V;02bn_LF&3LhLA<#}{{)jE)}CiW%VEU~9)SW+=F%7U-iYlQ&q!#N zwI2{(h|Pi&<8_fqvT*}FLN^0CxN}#|3I9G_xmVg$gbn2ZdhbmGk7Q5Q2Tm*ox8NMo zv`iaZW|ZEOMyQga5fts?&T-eCCC9pS0mj7v0SDkD=*^MxurP@89v&Z#3q{FM!a_nr zb?KzMv`BBFOew>4!ft@A&(v-kWXny-j#egKef|#!+3>26Qq0 zv!~8ev4G`7Qk>V1TaMT-&ziqoY3IJp8_S*%^1j73D|=9&;tDZH^!LYFMmME4*Wj(S zRt~Q{aLb_O;wi4u&=}OYuj}Lw*j$@z*3>4&W{)O-oi@9NqdoU!=U%d|se&h?^$Ip# z)BY+(1+cwJz!yy4%l(aLC;T!~Ci>yAtXJb~b*yr&v7f{YCU8P|N1v~H`xmGsG)g)y z4%mv=cPd`s7a*#OR7f0lpD$ueP>w8qXj0J&*7xX+U!uat5QNk>zwU$0acn5p=$88L=jn_QCSYkTV;1~(yUem#0gB`FeqY98sf=>^@ z_MCdvylv~WL%y_%y_FE1)j;{Szj1+K7Lr_y=V+U zk6Tr;>XEqlEom~QGL!a+wOf(@ZWoxE<$^qHYl*H1a~kk^BLPn785%nQb$o;Cuz0h& za9LMx^bKEbPS%e8NM33Jr|1T|ELC(iE!FUci38xW_Y7kdHid#2ie+XZhP;2!Z;ZAM zB_cXKm)VrPK!SK|PY00Phwrpd+x0_Aa;}cDQvWKrwnQrqz##_gvHX2ja?#_{f#;bz`i>C^^ zTLDy;6@HZ~XQi7rph!mz9k!m;KchA)uMd`RK4WLK7)5Rl48m#l>b(#`WPsl<0j z-sFkSF6>Nk|LKnHtZ`W_NnxZP62&w)S(aBmmjMDKzF%G;3Y?FUbo?>b5;0j8Lhtc4 zr*8d5Y9>g@FFZaViw7c16VsHcy0u7M%6>cG1=s=Dtx?xMJSKIu9b6GU8$uSzf43Y3 zYq|U+IWfH;SM~*N1v`KJo!|yfLxTFS?oHsr3qvzeVndVV^%BWmW6re_S!2;g<|Oao z+N`m#*i!)R%i1~NO-xo{qpwL0ZrL7hli;S z3L0lQ_z}z`fdK39Mg~Zd*%mBdD;&5EXa~@H(!###L`ycr7gW`f)KRuqyHL3|uyy3h zSS^td#E&Knc$?dXs*{EnPYOp^-vjAc-h4z#XkbG&REC7;0>z^^Z}i8MxGKerEY z>l?(wReOlXEsNE5!DO&ZWyxY)gG#FSZs%fXuzA~XIAPVp-%yb2XLSV{1nH6{)5opg z(dZKckn}Q4Li-e=eUDs1Psg~5zdn1>ql(*(nn6)iD*OcVkwmKL(A{fix(JhcVB&}V zVt*Xb!{gzvV}dc446>(D=SzfCu7KB`oMjv6kPzSv&B>>HLSJP|wN`H;>oRw*tl#N) z*zZ-xwM7D*AIsBfgqOjY1Mp9aq$kRa^dZU_xw~KxP;|q(m+@e+YSn~`wEJzM|Ippb zzb@%;hB7iH4op9SqmX?j!KP2chsb79(mFossBO-Zj8~L}9L%R%Bw<`^X>hjkCY5SG z7lY!8I2mB#z)1o;*3U$G)3o0A&{0}#B;(zPd2`OF`Gt~8;0Re8nIseU z_yzlf$l+*-wT~_-cYk$^wTJ@~7i@u(CZs9FVkJCru<*yK8&>g+t*!JqCN6RH%8S-P zxH8+Cy#W?!;r?cLMC(^BtAt#xPNnwboI*xWw#T|IW^@3|q&QYY6Ehxoh@^URylR|T zne-Y6ugE^7p5bkRDWIh)?JH5V^ub82l-LuVjDr7UT^g`q4dB&mBFRWGL_C?hoeL(% zo}ocH5t7|1Mda}T!^{Qt9vmA2ep4)dQSZO>?Eq8}qRp&ZJ?-`Tnw+MG(eDswP(L*X3ahC2Ad0_wD^ff9hfzb%Jd`IXx5 zae@NMzBXJDwJS?7_%!TB^E$N8pvhOHDK$7YiOelTY`6KX8hK6YyT$tk*adwN>s^Kp zwM3wGVPhwKU*Yq-*BCs}l`l#Tej(NQ>jg*S0TN%D+GcF<14Ms6J`*yMY;W<-mMN&-K>((+P}+t+#0KPGrzjP zJ~)=Bcz%-K!L5ozIWqO(LM)l_9lVOc4*S65&DKM#TqsiWNG{(EZQw!bc>qLW`=>p-gVJ;T~aN2D_- z{>SZC=_F+%hNmH6ub%Ykih0&YWB!%sd%W5 zHC2%QMP~xJgt4>%bU>%6&uaDtSD?;Usm}ari0^fcMhi_)JZgb1g5j zFl4`FQ*%ROfYI}e7RIq^&^a>jZF23{WB`T>+VIxj%~A-|m=J7Va9FxXV^%UwccSZd zuWINc-g|d6G5;95*%{e;9S(=%yngpfy+7ao|M7S|Jb0-4+^_q-uIqVS&ufU880UDH*>(c)#lt2j zzvIEN>>$Y(PeALC-D?5JfH_j+O-KWGR)TKunsRYKLgk7eu4C{iF^hqSz-bx5^{z0h ze2+u>Iq0J4?)jIo)}V!!m)%)B;a;UfoJ>VRQ*22+ncpe9f4L``?v9PH&;5j{WF?S_C>Lq>nkChZB zjF8(*v0c(lU^ZI-)_uGZnnVRosrO4`YinzI-RSS-YwjYh3M`ch#(QMNw*)~Et7Qpy z{d<3$4FUAKILq9cCZpjvKG#yD%-juhMj>7xIO&;c>_7qJ%Ae8Z^m)g!taK#YOW3B0 zKKSMOd?~G4h}lrZbtPk)n*iOC1~mDhASGZ@N{G|dF|Q^@1ljhe=>;wusA&NvY*w%~ zl+R6B^1yZiF)YN>0ms%}qz-^U-HVyiN3R9k1q4)XgDj#qY4CE0)52%evvrrOc898^ z*^)XFR?W%g0@?|6Mxo1ZBp%(XNv_RD-<#b^?-Fs+NL^EUW=iV|+Vy*F%;rBz~pN7%-698U-VMfGEVnmEz7fL1p)-5sLT zL;Iz>FCLM$p$c}g^tbkGK1G$IALq1Gd|We@&TtW!?4C7x4l*=4oF&&sr0Hu`x<5!m zhX&&Iyjr?AkNXU_5P_b^Q3U9sy#f6ZF@2C96$>1k*E-E%DjwvA{VL0PdU~suN~DZo zm{T!>sRdp`Ldpp9olrH@(J$QyGq!?#o1bUo=XP2OEuT3`XzI>s^0P{manUaE4pI%! zclQq;lbT;nx7v3tR9U)G39h?ryrxzd0xq4KX7nO?piJZbzT_CU&O=T(Vt;>jm?MgC z2vUL#*`UcMsx%w#vvjdamHhmN!(y-hr~byCA-*iCD};#l+bq;gkwQ0oN=AyOf@8ow>Pj<*A~2*dyjK}eYdN);%!t1 z6Y=|cuEv-|5BhA?n2Db@4s%y~(%Wse4&JXw=HiO48%c6LB~Z0SL1(k^9y?ax%oj~l zf7(`iAYLdPRq*ztFC z7VtAb@s{as%&Y;&WnyYl+6Wm$ru*u!MKIg_@01od-iQft0rMjIj8e7P9eKvFnx_X5 zd%pDg-|8<>T2Jdqw>AII+fe?CgP+fL(m0&U??QL8YzSjV{SFi^vW~;wN@or_(q<0Y zRt~L}#JRcHOvm$CB)T1;;7U>m%)QYBLTR)KTARw%zoDxgssu5#v{UEVIa<>{8dtkm zXgbCGp$tfue+}#SD-PgiNT{Zu^YA9;4BnM(wZ9-biRo_7pN}=aaimjYgC=;9@g%6< zxol5sT_$<8{LiJ6{l1+sV)Z_QdbsfEAEMw!5*zz6)Yop?T0DMtR_~wfta)E6_G@k# zZRP11D}$ir<`IQ`<(kGfAS?O-DzCyuzBq6dxGTNNTK?r^?zT30mLY!kQ=o~Hv*k^w zvq!LBjW=zzIi%UF@?!g9vt1CqdwV(-2LYy2=E@Z?B}JDyVkluHtzGsWuI1W5svX~K z&?UJ45$R7g>&}SFnLnmw09R2tUgmr_w6mM9C}8GvQX>nL&5R#xBqnp~Se(I>R42`T zqZe9p6G(VzNB3QD><8+y%{e%6)sZDRXTR|MI zM#eZmao-~_`N|>Yf;a;7yvd_auTG#B?Vz5D1AHx=zpVUFe7*hME z+>KH5h1In8hsVhrstc>y0Q!FHR)hzgl+*Q&5hU9BVJlNGRkXiS&06eOBV^dz3;4d5 zeYX%$62dNOprZV$px~#h1RH?_E%oD6y;J;pF%~y8M)8pQ0olYKj6 zE+hd|7oY3ot=j9ZZ))^CCPADL6Jw%)F@A{*coMApcA$7fZ{T@3;WOQ352F~q6`Mgi z$RI6$8)a`Aaxy<8Bc;{wlDA%*%(msBh*xy$L-cBJvQ8hj#FCyT^%+Phw1~PaqyDou^JR0rxDkSrmAdjeYDFDZ`E z)G3>XtpaSPDlydd$RGHg;#4|4{aP5c_Om z2u5xgnhnA)K%8iU==}AxPxZCYC)lyOlj9as#`5hZ=<6<&DB%i_XCnt5=pjh?iusH$ z>)E`@HNZcAG&RW3Ys@`Ci{;8PNzE-ZsPw$~Wa!cP$ye+X6;9ceE}ah+3VY7Mx}#0x zbqYa}eO*FceiY2jNS&2cH9Y}(;U<^^cWC5Ob&)dZedvZA9HewU3R;gRQ)}hUdf+~Q zS_^4ds*W1T#bxS?%RH&<739q*n<6o|mV;*|1s>ly-Biu<2*{!!0#{_234&9byvn0* z5=>{95Zfb{(?h_Jk#ocR$FZ78O*UTOxld~0UF!kyGM|nH%B*qf)Jy}N!uT9NGeM19 z-@=&Y0yGGo_dw!FD>juk%P$6$qJkj}TwLBoefi;N-$9LAeV|)|-ET&culW9Sb_pc_ zp{cXI0>I0Jm_i$nSvGnYeLSSj{ccVS2wyL&0x~&5v;3Itc82 z5lIAkfn~wcY-bQB$G!ufWt%qO;P%&2B_R5UKwYxMemIaFm)qF1rA zc>gEihb=jBtsXCi0T%J37s&kt*3$s7|6)L(%UiY)6axuk{6RWIS8^+u;)6!R?Sgap z9|6<0bx~AgVi|*;zL@2x>Pbt2Bz*uv4x-`{F)XatTs`S>unZ#P^ZiyjpfL_q2z^fqgR-fbOcG=Y$q>ozkw1T6dH8-)&ww+z?E0 zR|rV(9bi6zpX3Ub>PrPK!{X>e$C66qCXAeFm)Y+lX8n2Olt7PNs*1^si)j!QmFV#t z0P2fyf$N^!dyTot&`Ew5{i5u<8D`8U`qs(KqaWq5iOF3x2!-z65-|HsyYz(MAKZ?< zCpQR;E)wn%s|&q(LVm0Ab>gdmCFJeKwVTnv@Js%!At;I=A>h=l=p^&<4;Boc{$@h< z38v`3&2wJtka@M}GS%9!+SpJ}sdtoYzMevVbnH+d_eMxN@~~ zZq@k)7V5f8u!yAX2qF3qjS7g%n$JuGrMhQF!&S^7(%Y{rP*w2FWj(v_J{+Hg*}wdWOd~pHQ19&n3RWeljK9W%sz&Y3Tm3 zR`>6YR54%qBHGa)2xbs`9cs_EsNHxsfraEgZ)?vrtooeA0sPKJK7an){ngtV@{SBa zkO6ORr1_Xqp+`a0e}sC*_y(|RKS13ikmHp3C^XkE@&wjbGWrt^INg^9lDz#B;bHiW zkK4{|cg08b!yHFSgPca5)vF&gqCgeu+c82%&FeM^Bb}GUxLy-zo)}N;#U?sJ2?G2BNe*9u_7kE5JeY!it=f`A_4gV3} z`M!HXZy#gN-wS!HvHRqpCHUmjiM;rVvpkC!voImG%OFVN3k(QG@X%e``VJSJ@Z7tb z*Onlf>z^D+&$0!4`IE$;2-NSO9HQWd+UFW(r;4hh;(j^p4H-~6OE!HQp^96v?{9Zt z;@!ZcccV%C2s6FMP#qvo4kG6C04A>XILt>JW}%0oE&HM5f6 zYLD!;My>CW+j<~=Wzev{aYtx2ZNw|ptTFV(4;9`6Tmbz6K1)fv4qPXa2mtoPt&c?P zhmO+*o8uP3ykL6E$il00@TDf6tOW7fmo?Oz_6GU^+5J=c22bWyuH#aNj!tT-^IHrJ zu{aqTYw@q;&$xDE*_kl50Jb*dp`(-^p={z}`rqECTi~3 z>0~A7L6X)=L5p#~$V}gxazgGT7$3`?a)zen>?TvAuQ+KAIAJ-s_v}O6@`h9n-sZk> z`3{IJeb2qu9w=P*@q>iC`5wea`KxCxrx{>(4{5P+!cPg|pn~;n@DiZ0Y>;k5mnKeS z!LIfT4{Lgd=MeysR5YiQKCeNhUQ;Os1kAymg6R!u?j%LF z4orCszIq_n52ulpes{(QN|zirdtBsc{9^Z72Ycb2ht?G^opkT_#|4$wa9`)8k3ilU z%ntAi`nakS1r10;#k^{-ZGOD&Z2|k=p40hRh5D7(&JG#Cty|ECOvwsSHkkSa)36$4 z?;v#%@D(=Raw(HP5s>#4Bm?f~n1@ebH}2tv#7-0l-i^H#H{PC|F@xeNS+Yw{F-&wH z07)bj8MaE6`|6NoqKM~`4%X> zKFl&7g1$Z3HB>lxn$J`P`6GSb6CE6_^NA1V%=*`5O!zP$a7Vq)IwJAki~XBLf=4TF zPYSL}>4nOGZ`fyHChq)jy-f{PKFp6$plHB2=;|>%Z^%)ecVue(*mf>EH_uO^+_zm? zJATFa9SF~tFwR#&0xO{LLf~@}s_xvCPU8TwIJgBs%FFzjm`u?1699RTui;O$rrR{# z1^MqMl5&6)G%@_k*$U5Kxq84!AdtbZ!@8FslBML}<`(Jr zenXrC6bFJP=R^FMBg7P?Pww-!a%G@kJH_zezKvuWU0>m1uyy}#Vf<$>u?Vzo3}@O% z1JR`B?~Tx2)Oa|{DQ_)y9=oY%haj!80GNHw3~qazgU-{|q+Bl~H94J!a%8UR?XsZ@ z0*ZyQugyru`V9b(0OrJOKISfi89bSVR zQy<+i_1XY}4>|D%X_`IKZUPz6=TDb)t1mC9eg(Z=tv zq@|r37AQM6A%H%GaH3szv1L^ku~H%5_V*fv$UvHl*yN4iaqWa69T2G8J2f3kxc7UE zOia@p0YNu_q-IbT%RwOi*|V|&)e5B-u>4=&n@`|WzH}BK4?33IPpXJg%`b=dr_`hU z8JibW_3&#uIN_#D&hX<)x(__jUT&lIH$!txEC@cXv$7yB&Rgu){M`9a`*PH} zRcU)pMWI2O?x;?hzR{WdzKt^;_pVGJAKKd)F$h;q=Vw$MP1XSd<;Mu;EU5ffyKIg+ z&n-Nb?h-ERN7(fix`htopPIba?0Gd^y(4EHvfF_KU<4RpN0PgVxt%7Yo99X*Pe|zR z?ytK&5qaZ$0KSS$3ZNS$$k}y(2(rCl=cuYZg{9L?KVgs~{?5adxS))Upm?LDo||`H zV)$`FF3icFmxcQshXX*1k*w3O+NjBR-AuE70=UYM*7>t|I-oix=bzDwp2*RoIwBp@r&vZukG; zyi-2zdyWJ3+E?{%?>e2Ivk`fAn&Ho(KhGSVE4C-zxM-!j01b~mTr>J|5={PrZHOgO zw@ND3=z(J7D>&C7aw{zT>GHhL2BmUX0GLt^=31RRPSnjoUO9LYzh_yegyPoAKhAQE z>#~O27dR4&LdQiak6={9_{LN}Z>;kyVYKH^d^*!`JVSXJlx#&r4>VnP$zb{XoTb=> zZsLvh>keP3fkLTIDdpf-@(ADfq4=@X=&n>dyU0%dwD{zsjCWc;r`-e~X$Q3NTz_TJ zOXG|LMQQIjGXY3o5tBm9>k6y<6XNO<=9H@IXF;63rzsC=-VuS*$E{|L_i;lZmHOD< zY92;>4spdeRn4L6pY4oUKZG<~+8U-q7ZvNOtW0i*6Q?H`9#U3M*k#4J;ek(MwF02x zUo1wgq9o6XG#W^mxl>pAD)Ll-V5BNsdVQ&+QS0+K+?H-gIBJ-ccB1=M_hxB6qcf`C zJ?!q!J4`kLhAMry4&a_0}up{CFevcjBl|N(uDM^N5#@&-nQt2>z*U}eJGi}m5f}l|IRVj-Q;a>wcLpK5RRWJ> zysdd$)Nv0tS?b~bw1=gvz3L_ZAIdDDPj)y|bp1;LE`!av!rODs-tlc}J#?erTgXRX z$@ph%*~_wr^bQYHM7<7=Q=45v|Hk7T=mDpW@OwRy3A_v`ou@JX5h!VI*e((v*5Aq3 zVYfB4<&^Dq5%^?~)NcojqK`(VXP$`#w+&VhQOn%;4pCkz;NEH6-FPHTQ+7I&JE1+Ozq-g43AEZV>ceQ^9PCx zZG@OlEF~!Lq@5dttlr%+gNjRyMwJdJU(6W_KpuVnd{3Yle(-p#6erIRc${l&qx$HA z89&sp=rT7MJ=DuTL1<5{)wtUfpPA|Gr6Q2T*=%2RFm@jyo@`@^*{5{lFPgv>84|pv z%y{|cVNz&`9C*cUely>-PRL)lHVErAKPO!NQ3<&l5(>Vp(MuJnrOf^4qpIa!o3D7( z1bjn#Vv$#or|s7Hct5D@%;@48mM%ISY7>7@ft8f?q~{s)@BqGiupoK1BAg?PyaDQ1 z`YT8{0Vz{zBwJ={I4)#ny{RP{K1dqzAaQN_aaFC%Z>OZ|^VhhautjDavGtsQwx@WH zr|1UKk^+X~S*RjCY_HN!=Jx>b6J8`Q(l4y|mc<6jnkHVng^Wk(A13-;AhawATsmmE#H%|8h}f1frs2x@Fwa_|ea+$tdG2Pz{7 z!ox^w^>^Cv4e{Xo7EQ7bxCe8U+LZG<_e$RnR?p3t?s^1Mb!ieB z#@45r*PTc_yjh#P=O8Zogo+>1#|a2nJvhOjIqKK1U&6P)O%5s~M;99O<|Y9zomWTL z666lK^QW`)cXV_^Y05yQZH3IRCW%25BHAM$c0>w`x!jh^15Zp6xYb!LoQ zr+RukTw0X2mxN%K0%=8|JHiaA3pg5+GMfze%9o5^#upx0M?G9$+P^DTx7~qq9$Qoi zV$o)yy zuUq>3c{_q+HA5OhdN*@*RkxRuD>Bi{Ttv_hyaaB;XhB%mJ2Cb{yL;{Zu@l{N?!GKE7es6_9J{9 zO(tmc0ra2;@oC%SS-8|D=omQ$-Dj>S)Utkthh{ovD3I%k}HoranSepC_yco2Q8 zY{tAuPIhD{X`KbhQIr%!t+GeH%L%q&p z3P%<-S0YY2Emjc~Gb?!su85}h_qdu5XN2XJUM}X1k^!GbwuUPT(b$Ez#LkG6KEWQB z7R&IF4srHe$g2R-SB;inW9T{@+W+~wi7VQd?}7||zi!&V^~o0kM^aby7YE_-B63^d zf_uo8#&C77HBautt_YH%v6!Q>H?}(0@4pv>cM6_7dHJ)5JdyV0Phi!)vz}dv{*n;t zf(+#Hdr=f8DbJqbMez)(n>@QT+amJ7g&w6vZ-vG^H1v~aZqG~u!1D(O+jVAG0EQ*aIsr*bsBdbD`)i^FNJ z&B@yxqPFCRGT#}@dmu-{0vp47xk(`xNM6E=7QZ5{tg6}#zFrd8Pb_bFg7XP{FsYP8 zbvWqG6#jfg*4gvY9!gJxJ3l2UjP}+#QMB(*(?Y&Q4PO`EknE&Cb~Yb@lCbk;-KY)n zzbjS~W5KZ3FV%y>S#$9Sqi$FIBCw`GfPDP|G=|y32VV-g@a1D&@%_oAbB@cAUx#aZ zlAPTJ{iz#Qda8(aNZE&0q+8r3&z_Ln)b=5a%U|OEcc3h1f&8?{b8ErEbilrun}mh3 z$1o^$-XzIiH|iGoJA`w`o|?w3m*NX|sd$`Mt+f*!hyJvQ2fS*&!SYn^On-M|pHGlu z4SC5bM7f6BAkUhGuN*w`97LLkbCx=p@K5RL2p>YpDtf{WTD|d3ucb6iVZ-*DRtoEA zCC5(x)&e=giR_id>5bE^l%Mxx>0@FskpCD4oq@%-Fg$8IcdRwkfn;DsjoX(v;mt3d z_4Mnf#Ft4x!bY!7Hz?RRMq9;5FzugD(sbt4up~6j?-or+ch~y_PqrM2hhTToJjR_~ z)E1idgt7EW>G*9%Q^K;o_#uFjX!V2pwfpgi>}J&p_^QlZki!@#dkvR`p?bckC`J*g z=%3PkFT3HAX2Q+dShHUbb1?ZcK8U7oaufLTCB#1W{=~k0Jabgv>q|H+GU=f-y|{p4 zwN|AE+YbCgx=7vlXE?@gkXW9PaqbO#GB=4$o0FkNT#EI?aLVd2(qnPK$Yh%YD%v(mdwn}bgsxyIBI^)tY?&G zi^2JfClZ@4b{xFjyTY?D61w@*ez2@5rWLpG#34id?>>oPg{`4F-l`7Lg@D@Hc}On} zx%BO4MsLYosLGACJ-d?ifZ35r^t*}wde>AAWO*J-X%jvD+gL9`u`r=kP zyeJ%FqqKfz8e_3K(M1RmB?gIYi{W7Z<THP2ihue0mbpu5n(x_l|e1tw(q!#m5lmef6ktqIb${ zV+ee#XRU}_dDDUiV@opHZ@EbQ<9qIZJMDsZDkW0^t3#j`S)G#>N^ZBs8k+FJhAfu< z%u!$%dyP3*_+jUvCf-%{x#MyDAK?#iPfE<(@Q0H7;a125eD%I(+!x1f;Sy`e<9>nm zQH4czZDQmW7^n>jL)@P@aAuAF$;I7JZE5a8~AJI5CNDqyf$gjloKR7C?OPt9yeH}n5 zNF8Vhmd%1O>T4EZD&0%Dt7YWNImmEV{7QF(dy!>q5k>Kh&Xy8hcBMUvVV~Xn8O&%{ z&q=JCYw#KlwM8%cu-rNadu(P~i3bM<_a{3!J*;vZhR6dln6#eW0^0kN)Vv3!bqM`w z{@j*eyzz=743dgFPY`Cx3|>ata;;_hQ3RJd+kU}~p~aphRx`03B>g4*~f%hUV+#D9rYRbsGD?jkB^$3XcgB|3N1L& zrmk9&Dg450mAd=Q_p?gIy5Zx7vRL?*rpNq76_rysFo)z)tp0B;7lSb9G5wX1vC9Lc z5Q8tb-alolVNWFsxO_=12o}X(>@Mwz1mkYh1##(qQwN=7VKz?61kay8A9(94Ky(4V zq6qd2+4a20Z0QRrmp6C?4;%U?@MatfXnkj&U6bP_&2Ny}BF%4{QhNx*Tabik9Y-~Z z@0WV6XD}aI(%pN}oW$X~Qo_R#+1$@J8(31?zM`#e`#(0f<-AZ^={^NgH#lc?oi(Mu zMk|#KR^Q;V@?&(sh5)D;-fu)rx%gXZ1&5)MR+Mhssy+W>V%S|PRNyTAd}74<(#J>H zR(1BfM%eIv0+ngHH6(i`?-%_4!6PpK*0X)79SX0X$`lv_q>9(E2kkkP;?c@rW2E^Q zs<;`9dg|lDMNECFrD3jTM^Mn-C$44}9d9Kc z#>*k&e#25;D^%82^1d@Yt{Y91MbEu0C}-;HR4+IaCeZ`l?)Q8M2~&E^FvJ?EBJJ(% zz1>tCW-E~FB}DI}z#+fUo+=kQME^=eH>^%V8w)dh*ugPFdhMUi3R2Cg}Zak4!k_8YW(JcR-)hY8C zXja}R7@%Q0&IzQTk@M|)2ViZDNCDRLNI)*lH%SDa^2TG4;%jE4n`8`aQAA$0SPH2@ z)2eWZuP26+uGq+m8F0fZn)X^|bNe z#f{qYZS!(CdBdM$N2(JH_a^b#R2=>yVf%JI_ieRFB{w&|o9txwMrVxv+n78*aXFGb z>Rkj2yq-ED<)A46T9CL^$iPynv`FoEhUM10@J+UZ@+*@_gyboQ>HY9CiwTUo7OM=w zd~$N)1@6U8H#Zu(wGLa_(Esx%h@*pmm5Y9OX@CY`3kPYPQx@z8yAgtm(+agDU%4?c zy8pR4SYbu8vY?JX6HgVq7|f=?w(%`m-C+a@E{euXo>XrGmkmFGzktI*rj*8D z)O|CHKXEzH{~iS+6)%ybRD|JRQ6j<+u_+=SgnJP%K+4$st+~XCVcAjI9e5`RYq$n{ zzy!X9Nv7>T4}}BZpSj9G9|(4ei-}Du<_IZw+CB`?fd$w^;=j8?vlp(#JOWiHaXJjB0Q00RHJ@sG6N#y^H7t^&V} z;VrDI4?75G$q5W9mV=J2iP24NHJy&d|HWHva>FaS#3AO?+ohh1__FMx;?`f{HG3v0 ztiO^Wanb>U4m9eLhoc_2B(ca@YdnHMB*~aYO+AE(&qh@?WukLbf_y z>*3?Xt-lxr?#}y%kTv+l8;!q?Hq8XSU+1E8x~o@9$)zO2z9K#(t`vPDri`mKhv|sh z{KREcy`#pnV>cTT7dm7M9B@9qJRt3lfo(C`CNkIq@>|2<(yn!AmVN?ST zbX_`JjtWa3&N*U{K7FYX8})*D#2@KBae` zhKS~s!r%SrXdhCsv~sF}7?ocyS?afya6%rDBu6g^b2j#TOGp^1zrMR}|70Z>CeYq- z1o|-=FBKlu{@;pm@QQJ_^!&hzi;0Z_Ho){x3O1KQ#TYk=rAt9`YKC0Y^}8GWIN{QW znYJyVTrmNvl!L=YS1G8BAxGmMUPi+Q7yb0XfG`l+L1NQVSbe^BICYrD;^(rke{jWCEZOtVv3xFze!=Z&(7}!)EcN;v0Dbit?RJ6bOr;N$ z=nk8}H<kCEE+IK3z<+3mkn4q!O7TMWpKShWWWM)X*)m6k%3luF6c>zOsFccvfLWf zH+mNkh!H@vR#~oe=ek}W3!71z$Dlj0c(%S|sJr>rvw!x;oCek+8f8s!U{DmfHcNpO z9>(IKOMfJwv?ey`V2ysSx2Npeh_x#bMh)Ngdj$al;5~R7Ac5R2?*f{hI|?{*$0qU- zY$6}ME%OGh^zA^z9zJUs-?a4ni8cw_{cYED*8x{bWg!Fn9)n;E9@B+t;#k}-2_j@# zg#b%R(5_SJAOtfgFCBZc`n<&z6)%nOIu@*yo!a% zpLg#36KBN$01W{b;qWN`Tp(T#jh%;Zp_zpS64lvBVY2B#UK)p`B4Oo)IO3Z&D6<3S zfF?ZdeNEnzE{}#gyuv)>;z6V{!#bx)` zY;hL*f(WVD*D9A4$WbRKF2vf;MoZVdhfWbWhr{+Db5@M^A4wrFReuWWimA4qp`GgoL2`W4WPUL5A=y3Y3P z%G?8lLUhqo@wJW8VDT`j&%YY7xh51NpVYlsrk_i4J|pLO(}(b8_>%U2M`$iVRDc-n zQiOdJbroQ%*vhN{!{pL~N|cfGooK_jTJCA3g_qs4c#6a&_{&$OoSQr_+-O^mKP=Fu zGObEx`7Qyu{nHTGNj(XSX*NPtAILL(0%8Jh)dQh+rtra({;{W2=f4W?Qr3qHi*G6B zOEj7%nw^sPy^@05$lOCjAI)?%B%&#cZ~nC|=g1r!9W@C8T0iUc%T*ne z)&u$n>Ue3FN|hv+VtA+WW)odO-sdtDcHfJ7s&|YCPfWaVHpTGN46V7Lx@feE#Od%0XwiZy40plD%{xl+K04*se zw@X4&*si2Z_0+FU&1AstR)7!Th(fdaOlsWh`d!y=+3m!QC$Zlkg8gnz!}_B7`+wSz z&kD?6{zPnE3uo~Tv8mLP%RaNt2hcCJBq=0T>%MW~Q@Tpt2pPP1?KcywH>in5@ zx+5;xu-ltFfo5vLU;2>r$-KCHjwGR&1XZ0YNyrXXAUK!FLM_7mV&^;;X^*YH(FLRr z`0Jjg7wiq2bisa`CG%o9i)o1`uG?oFjU_Zrv1S^ipz$G-lc^X@~6*)#%nn+RbgksJfl{w=k31(q>7a!PCMp5YY{+Neh~mo zG-3dd!0cy`F!nWR?=9f_KP$X?Lz&cLGm_ohy-|u!VhS1HG~e7~xKpYOh=GmiiU;nu zrZ5tWfan3kp-q_vO)}vY6a$19Q6UL0r znJ+iSHN-&w@vDEZ0V%~?(XBr|jz&vrBNLOngULxtH(Rp&U*rMY42n;05F11xh?k;n_DX2$4|vWIkXnbwfC z=ReH=(O~a;VEgVO?>qsP*#eOC9Y<_9Yt<6X}X{PyF7UXIA$f)>NR5P&4G_Ygq(9TwwQH*P>Rq>3T4I+t2X(b5ogXBAfNf!xiF#Gilm zp2h{&D4k!SkKz-SBa%F-ZoVN$7GX2o=(>vkE^j)BDSGXw?^%RS9F)d_4}PN+6MlI8*Uk7a28CZ)Gp*EK)`n5i z){aq=0SFSO-;sw$nAvJU-$S-cW?RSc7kjEBvWDr1zxb1J7i;!i+3PQwb=)www?7TZ zE~~u)vO>#55eLZW;)F(f0KFf8@$p)~llV{nO7K_Nq-+S^h%QV_CnXLi)p*Pq&`s!d zK2msiR;Hk_rO8`kqe_jfTmmv|$MMo0ll}mI)PO4!ikVd(ZThhi&4ZwK?tD-}noj}v zBJ?jH-%VS|=t)HuTk?J1XaDUjd_5p1kPZi6y#F6$lLeRQbj4hsr=hX z4tXkX2d5DeLMcAYTeYm|u(XvG5JpW}hcOs4#s8g#ihK%@hVz|kL=nfiBqJ{*E*WhC zht3mi$P3a(O5JiDq$Syu9p^HY&9~<#H89D8 zJm84@%TaL_BZ+qy8+T3_pG7Q%z80hnjN;j>S=&WZWF48PDD%55lVuC0%#r5(+S;WH zS7!HEzmn~)Ih`gE`faPRjPe^t%g=F ztpGVW=Cj5ZkpghCf~`ar0+j@A=?3(j@7*pq?|9)n*B4EQTA1xj<+|(Y72?m7F%&&& zdO44owDBPT(8~RO=dT-K4#Ja@^4_0v$O3kn73p6$s?mCmVDUZ+Xl@QcpR6R3B$=am z%>`r9r2Z79Q#RNK?>~lwk^nQlR=Hr-ji$Ss3ltbmB)x@0{VzHL-rxVO(++@Yr@Iu2 zTEX)_9sVM>cX$|xuqz~Y8F-(n;KLAfi*63M7mh&gsPR>N0pd9h!0bm%nA?Lr zS#iEmG|wQd^BSDMk0k?G>S-uE$vtKEF8Dq}%vLD07zK4RLoS?%F1^oZZI$0W->7Z# z?v&|a`u#UD=_>i~`kzBGaPj!mYX5g?3RC4$5EV*j0sV)>H#+$G6!ci=6`)85LWR=FCp-NUff`;2zG9nU6F~ z;3ZyE*>*LvUgae+uMf}aV}V*?DCM>{o31+Sx~6+sz;TI(VmIpDrN3z+BUj`oGGgLP z>h9~MP}Pw#YwzfGP8wSkz`V#}--6}7S9yZvb{;SX?6PM_KuYpbi~*=teZr-ga2QqIz{QrEyZ@>eN*qmy;N@FCBbRNEeeoTmQyrX;+ zCkaJ&vOIbc^2BD6_H+Mrcl?Nt7O{xz9R_L0ZPV_u!sz+TKbXmhK)0QWoe-_HwtKJ@@7=L+ z+K8hhf=4vbdg3GqGN<;v-SMIzvX=Z`WUa_91Yf89^#`G(f-Eq>odB^p-Eqx}ENk#&MxJ+%~Ad2-*`1LNT>2INPw?*V3&kE;tt?rQyBw? zI+xJD04GTz1$7~KMnfpkPRW>f%n|0YCML@ODe`10;^DXX-|Hb*IE%_Vi#Pn9@#ufA z_8NY*1U%VseqYrSm?%>F@`laz+f?+2cIE4Jg6 z_VTcx|DSEA`g!R%RS$2dSRM|9VQClsW-G<~=j5T`pTbu-x6O`R z98b;}`rPM(2={YiytrqX+uh65f?%XiPp`;4CcMT*E*dQJ+if9^D>c_Dk8A(cE<#r=&!& z_`Z01=&MEE+2@yr!|#El=yM}v>i=?w^2E_FLPy(*4A9XmCNy>cBWdx3U>1RylsItO z4V8T$z3W-qqq*H`@}lYpfh=>C!tieKhoMGUi)EpWDr;yIL&fy};Y&l|)f^QE*k~4C zH>y`Iu%#S)z)YUqWO%el*Z)ME#p{1_8-^~6UF;kBTW zMQ!eXQuzkR#}j{qb(y9^Y!X7&T}}-4$%4w@w=;w+>Z%uifR9OoQ>P?0d9xpcwa>7kTv2U zT-F?3`Q`7xOR!gS@j>7In>_h){j#@@(ynYh;nB~}+N6qO(JO1xA z@59Pxc#&I~I64slNR?#hB-4XE>EFU@lUB*D)tu%uEa))B#eJ@ZOX0hIulfnDQz-y8 z`CX@(O%_VC{Ogh&ot``jlDL%R!f>-8yq~oLGxBO?+tQb5%k@a9zTs!+=NOwSVH-cR zqFo^jHeXDA_!rx$NzdP;>{-j5w3QUrR<;}=u2|FBJ;D#v{SK@Z6mjeV7_kFmWt95$ zeGaF{IU?U>?W`jzrG_9=9}yN*LKyzz))PLE+)_jc#4Rd$yFGol;NIk(qO1$5VXR)+ zxF7%f4=Q!NzR>DVXUB&nUT&>Nyf+5QRF+Z`X-bB*7=`|Go5D1&h~ zflKLw??kpiRm0h3|1GvySC2^#kcFz^5{79KKlq@`(leBa=_4CgV9sSHr{RIJ^KwR_ zY??M}-x^=MD+9`v@I3jue=OCn0kxno#6i>b(XKk_XTp_LpI}X*UA<#* zsgvq@yKTe_dTh>q1aeae@8yur08S(Q^8kXkP_ty48V$pX#y9)FQa~E7P7}GP_CbCm zc2dQxTeW(-~Y6}im24*XOC8ySfH*HMEnW3 z4CXp8iK(Nk<^D$g0kUW`8PXn2kdcDk-H@P0?G8?|YVlIFb?a>QunCx%B9TzsqQQ~HD!UO7zq^V!v9jho_FUob&Hxi ztU1nNOK)a!gkb-K4V^QVX05*>-^i|{b`hhvQLyj`E1vAnj0fbqqO%r z6Q;X1x0dL~GqMv%8QindZ4CZ%7pYQW~ z9)I*#Gjref-q(4Z*E#1c&rE0-_(4;_M(V7rgH_7H;ps1s%GBmU z{4a|X##j#XUF2n({v?ZUUAP5k>+)^F)7n-npbV3jAlY8V3*W=fwroDS$c&r$>8aH` zH+irV{RG3^F3oW2&E%5hXgMH9>$WlqX76Cm+iFmFC-DToTa`AcuN9S!SB+BT-IA#3P)JW1m~Cuwjs`Ep(wDXE4oYmt*aU z!Naz^lM}B)JFp7ejro7MU9#cI>wUoi{lylR2~s)3M!6a=_W~ITXCPd@U9W)qA5(mdOf zd3PntGPJyRX<9cgX?(9~TZB5FdEHW~gkJXY51}?s4ZT_VEdwOwD{T2E-B>oC8|_ZwsPNj=-q(-kwy%xX2K0~H z{*+W`-)V`7@c#Iuaef=?RR2O&x>W0A^xSwh5MsjTz(DVG-EoD@asu<>72A_h<39_# zawWVU<9t{r*e^u-5Q#SUI6dV#p$NYEGyiowT>>d*or=Ps!H$-3={bB|An$GPkP5F1 zTnu=ktmF|6E*>ZQvk^~DX(k!N`tiLut*?3FZhs$NUEa4ccDw66-~P;x+0b|<!ZN7Z%A`>2tN#CdoG>((QR~IV_Gj^Yh%!HdA~4C3jOXaqb6Ou z21T~Wmi9F6(_K0@KR@JDTh3-4mv2=T7&ML<+$4;b9SAtv*Uu`0>;VVZHB{4?aIl3J zL(rMfk?1V@l)fy{J5DhVlj&cWKJCcrpOAad(7mC6#%|Sn$VwMjtx6RDx1zbQ|Ngg8N&B56DGhu;dYg$Z{=YmCNn+?ceDclp65c_RnKs4*vefnhudSlrCy6-96vSB4_sFAj# zftzECwmNEOtED^NUt{ZDjT7^g>k1w<=af>+0)%NA;IPq6qx&ya7+QAu=pk8t>KTm` zEBj9J*2t|-(h)xc>Us*jHs)w9qmA>8@u21UqzKk*Ei#0kCeW6o z-2Q+Tvt25IUkb}-_LgD1_FUJ!U8@8OC^9(~Kd*0#zr*8IQkD)6Keb(XFai5*DYf~` z@U?-{)9X&BTf!^&@^rjmvea#9OE~m(D>qfM?CFT9Q4RxqhO0sA7S)=--^*Q=kNh7Y zq%2mu_d_#23d`+v`Ol263CZ<;D%D8Njj6L4T`S*^{!lPL@pXSm>2;~Da- zBX97TS{}exvSva@J5FJVCM$j4WDQuME`vTw>PWS0!;J7R+Kq zVUy6%#n5f7EV(}J#FhDpts;>=d6ow!yhJj8j>MJ@Wr_?x30buuutIG97L1A*QFT$c ziC5rBS;#qj=~yP-yWm-p(?llTwDuhS^f&<(9vA9@UhMH2-Fe_YAG$NvK6X{!mvPK~ zuEA&PA}meylmaIbbJXDOzuIn8cJNCV{tUA<$Vb?57JyAM`*GpEfMmFq>)6$E(9e1@W`l|R%-&}38#bl~levA#fx2wiBk^)mPj?<=S&|gv zQO)4*91$n08@W%2b|QxEiO0KxABAZC{^4BX^6r>Jm?{!`ZId9jjz<%pl(G5l));*`UU3KfnuXSDj2aP>{ zRIB$9pm7lj3*Xg)c1eG!cb+XGt&#?7yJ@C)(Ik)^OZ5><4u$VLCqZ#q2NMCt5 z6$|VN(RWM;5!JV?-h<JkEZ(SZF zC(6J+>A6Am9H7OlOFq6S62-2&z^Np=#xXsOq0WUKr zY_+Ob|CQd1*!Hirj5rn*=_bM5_zKmq6lG zn*&_=x%?ATxZ8ZTzd%biKY_qyNC#ZQ1vX+vc48N>aJXEjs{Y*3Op`Q7-oz8jyAh>d zNt_qvn`>q9aO~7xm{z`ree%lJ3YHCyC`q`-jUVCn*&NIml!uuMNm|~u3#AV?6kC+B z?qrT?xu2^mobSlzb&m(8jttB^je0mx;TT8}`_w(F11IKz83NLj@OmYDpCU^u?fD{) z&=$ptwVw#uohPb2_PrFX;X^I=MVXPDpqTuYhRa>f-=wy$y3)40-;#EUDYB1~V9t%$ z^^<7Zbs0{eB93Pcy)96%XsAi2^k`Gmnypd-&x4v9rAq<>a(pG|J#+Q>E$FvMLmy7T z5_06W=*ASUyPRfgCeiPIe{b47Hjqpb`9Xyl@$6*ntH@SV^bgH&Fk3L9L=6VQb)Uqa z33u#>ecDo&bK(h1WqSH)b_Th#Tvk&%$NXC@_pg5f-Ma#7q;&0QgtsFO~`V&{1b zbSP*X)jgLtd@9XdZ#2_BX4{X~pS8okF7c1xUhEV9>PZco>W-qz7YMD`+kCGULdK|^ zE7VwQ-at{%&fv`a+b&h`TjzxsyQX05UB~a0cuU-}{*%jR48J+yGWyl3Kdz5}U>;lE zgkba*yI5>xqIPz*Y!-P$#_mhHB!0Fpnv{$k-$xxjLAc`XdmHd1k$V@2QlblfJPrly z*~-4HVCq+?9vha>&I6aRGyq2VUon^L1a)g`-Xm*@bl2|hi2b|UmVYW|b+Gy?!aS-p z86a}Jep6Mf>>}n^*Oca@Xz}kxh)Y&pX$^CFAmi#$YVf57X^}uQD!IQSN&int=D> zJ>_|au3Be?hmPKK)1^JQ(O29eTf`>-x^jF2xYK6j_9d_qFkWHIan5=7EmDvZoQWz5 zZGb<{szHc9Nf@om)K_<=FuLR<&?5RKo3LONFQZ@?dyjemAe4$yDrnD zglU#XYo6|~L+YpF#?deK6S{8A*Ou;9G`cdC4S0U74EW18bc5~4>)<*}?Z!1Y)j;Ot zosEP!pc$O^wud(={WG%hY07IE^SwS-fGbvpP?;l8>H$;}urY2JF$u#$q}E*ZG%fR# z`p{xslcvG)kBS~B*^z6zVT@e}imYcz_8PRzM4GS52#ms5Jg9z~ME+uke`(Tq1w3_6 zxUa{HerS7!Wq&y(<9yyN@P^PrQT+6ij_qW3^Q)I53iIFCJE?MVyGLID!f?QHUi1tq z0)RNIMGO$2>S%3MlBc09l!6_(ECxXTU>$KjWdZX^3R~@3!SB zah5Za2$63;#y!Y}(wg1#shMePQTzfQfXyJ-Tf`R05KYcyvo8UW9-IWGWnzxR6Vj8_la;*-z5vWuwUe7@sKr#Tr51d z2PWn5h@|?QU3>k=s{pZ9+(}oye zc*95N_iLmtmu}H-t$smi49Y&ovX}@mKYt2*?C-i3Lh4*#q5YDg1Mh`j9ovRDf9&& zp_UMQh`|pC!|=}1uWoMK5RAjdTg3pXPCsYmRkWW}^m&)u-*c_st~gcss(`haA)xVw zAf=;s>$`Gq_`A}^MjY_BnCjktBNHY1*gzh(i0BFZ{Vg^F?Pbf`8_clvdZ)5(J4EWzAP}Ba5zX=S(2{gDugTQ3`%!q`h7kYSnwC`zEWeuFlODKiityMaM9u{Z%E@@y1jmZA#ⅅ8MglG&ER{i5lN315cO?EdHNLrg? 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 z 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 Pe7HEdAEg|=c=LY&YVNkY diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png deleted file mode 100644 index 13b35eba55c6dabc3aac36f33d859266c18fa0d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5680 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 diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png deleted file mode 100644 index 0a3f5fa40fb3d1e0710331a48de5d256da3f275d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 520 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 diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png deleted file mode 100644 index 2f1632cfddf3d9dade342351e627a0a75609fb46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2218 zcmV;b2vzrqP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91K%fHv1ONa40RR91KmY&$07g+lumAuE6iGxuRCodHTWf3-RTMruyW6Fu zQYeUM04eX6D5c0FCjKKPrco1(K`<0SL=crI{PC3-^hZU0kQie$gh-5!7z6SH6Q0J% zqot*`H1q{R5fHFYS}dje@;kG=v$L0(yY0?wY2%*c?A&{2?!D*x?m71{of2gv!$5|C z3>qG_BW}7K_yUcT3A5C6QD<+{aq?x;MAUyAiJn#Jv8_zZtQ{P zTRzbL3U9!qVuZzS$xKU10KiW~Bgdcv1-!uAhQxf3a7q+dU6lj?yoO4Lq4TUN4}h{N z*fIM=SS8|C2$(T>w$`t@3Tka!(r!7W`x z-isCVgQD^mG-MJ;XtJuK3V{Vy72GQ83KRWsHU?e*wrhKk=ApIYeDqLi;JI1e zuvv}5^Dc=k7F7?nm3nIw$NVmU-+R>> zyqOR$-2SDpJ}Pt;^RkJytDVXNTsu|mI1`~G7yw`EJR?VkGfNdqK9^^8P`JdtTV&tX4CNcV4 z&N06nZa??Fw1AgQOUSE2AmPE@WO(Fvo`%m`cDgiv(fAeRA%3AGXUbsGw{7Q`cY;1BI#ac3iN$$Hw z0LT0;xc%=q)me?Y*$xI@GRAw?+}>=9D+KTk??-HJ4=A>`V&vKFS75@MKdSF1JTq{S zc1!^8?YA|t+uKigaq!sT;Z!&0F2=k7F0PIU;F$leJLaw2UI6FL^w}OG&!;+b%ya1c z1n+6-inU<0VM-Y_s5iTElq)ThyF?StVcebpGI znw#+zLx2@ah{$_2jn+@}(zJZ{+}_N9BM;z)0yr|gF-4=Iyu@hI*Lk=-A8f#bAzc9f z`Kd6K--x@t04swJVC3JK1cHY-Hq+=|PN-VO;?^_C#;coU6TDP7Bt`;{JTG;!+jj(` zw5cLQ-(Cz-Tlb`A^w7|R56Ce;Wmr0)$KWOUZ6ai0PhzPeHwdl0H(etP zUV`va_i0s-4#DkNM8lUlqI7>YQLf)(lz9Q3Uw`)nc(z3{m5ZE77Ul$V%m)E}3&8L0 z-XaU|eB~Is08eORPk;=<>!1w)Kf}FOVS2l&9~A+@R#koFJ$Czd%Y(ENTV&A~U(IPI z;UY+gf+&6ioZ=roly<0Yst8ck>(M=S?B-ys3mLdM&)ex!hbt+ol|T6CTS+Sc0jv(& z7ijdvFwBq;0a{%3GGwkDKTeG`b+lyj0jjS1OMkYnepCdoosNY`*zmBIo*981BU%%U z@~$z0V`OVtIbEx5pa|Tct|Lg#ZQf5OYMUMRD>Wdxm5SAqV2}3!ceE-M2 z@O~lQ0OiKQp}o9I;?uxCgYVV?FH|?Riri*U$Zi_`V2eiA>l zdSm6;SEm6#T+SpcE8Ro_f2AwxzI z44hfe^WE3!h@W3RDyA_H440cpmYkv*)6m1XazTqw%=E5Xv7^@^^T7Q2wxr+Z2kVYr - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/AppInfo.xcconfig b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/AppInfo.xcconfig deleted file mode 100644 index 3ef081b4..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/AppInfo.xcconfig +++ /dev/null @@ -1,14 +0,0 @@ -// Application-level settings for the Runner target. -// -// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the -// future. If not, the values below would default to using the project name when this becomes a -// 'flutter create' template. - -// The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = staff_app_mvp - -// The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.example.staffAppMvp - -// The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2025 com.example. All rights reserved. diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/Debug.xcconfig b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/Debug.xcconfig deleted file mode 100644 index 36b0fd94..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Debug.xcconfig" -#include "Warnings.xcconfig" diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/Release.xcconfig b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/Release.xcconfig deleted file mode 100644 index dff4f495..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Release.xcconfig" -#include "Warnings.xcconfig" diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/Warnings.xcconfig b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/Warnings.xcconfig deleted file mode 100644 index 42bcbf47..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Configs/Warnings.xcconfig +++ /dev/null @@ -1,13 +0,0 @@ -WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings -GCC_WARN_UNDECLARED_SELECTOR = YES -CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES -CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE -CLANG_WARN__DUPLICATE_METHOD_MATCH = YES -CLANG_WARN_PRAGMA_PACK = YES -CLANG_WARN_STRICT_PROTOTYPES = YES -CLANG_WARN_COMMA = YES -GCC_WARN_STRICT_SELECTOR_MATCH = YES -CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES -CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES -GCC_WARN_SHADOW = YES -CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/DebugProfile.entitlements b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/DebugProfile.entitlements deleted file mode 100644 index dddb8a30..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/DebugProfile.entitlements +++ /dev/null @@ -1,12 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.cs.allow-jit - - com.apple.security.network.server - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Info.plist b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Info.plist deleted file mode 100644 index 4789daa6..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Info.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - $(PRODUCT_COPYRIGHT) - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/MainFlutterWindow.swift b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/MainFlutterWindow.swift deleted file mode 100644 index 3cc05eb2..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/MainFlutterWindow.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Cocoa -import FlutterMacOS - -class MainFlutterWindow: NSWindow { - override func awakeFromNib() { - let flutterViewController = FlutterViewController() - let windowFrame = self.frame - self.contentViewController = flutterViewController - self.setFrame(windowFrame, display: true) - - RegisterGeneratedPlugins(registry: flutterViewController) - - super.awakeFromNib() - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Release.entitlements b/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Release.entitlements deleted file mode 100644 index 852fa1a4..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/Runner/Release.entitlements +++ /dev/null @@ -1,8 +0,0 @@ - - - - - com.apple.security.app-sandbox - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/macos/RunnerTests/RunnerTests.swift b/apps/mobile/prototypes/staff_mobile_application/macos/RunnerTests/RunnerTests.swift deleted file mode 100644 index 61f3bd1f..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/macos/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Cocoa -import FlutterMacOS -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} diff --git a/apps/mobile/prototypes/staff_mobile_application/mock_staff_app_v2.md b/apps/mobile/prototypes/staff_mobile_application/mock_staff_app_v2.md deleted file mode 100644 index ce8984dd..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/mock_staff_app_v2.md +++ /dev/null @@ -1,859 +0,0 @@ -lib/services/mock_service.dart - - En este archivo, el uso de Map se encuentra como un parámetro en una función. - - 1. Parámetro de Función: Future createWorkerProfile(Map data) - - * Propósito: Esta función simula la creación de un perfil de trabajador en el backend. Acepta un Map llamado data que contiene toda la información del perfil del nuevo trabajador. - * Estructura del `Map` esperado: Aunque la función en sí misma no revela la estructura, el lugar donde se la llama (profile_setup_screen.dart) nos muestra exactamente qué datos se envían: - - 1 { - 2 'full_name': String, - 3 'bio': String, - 4 'preferred_locations': List, - 5 'max_distance_miles': double, - 6 'skills': List, - 7 'industries': List, - 8 } - - --- - - A continuación, analizaré el siguiente archivo: lib/widgets/shift_card.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/widgets/shift_card.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Continuando el análisis: - - --- - - lib/widgets/shift_card.dart - - En este widget, el uso de Map se encuentra como el tipo de retorno de una función. - - 1. Tipo de Retorno de Función: Map _calculateDuration() - - * Propósito: Esta función calcula la duración de un turno en horas y devuelve también una cadena de texto para el tiempo de descanso. - * Estructura del `Map` devuelto: - 1 { - 2 'hours': int, // La duración calculada del turno en horas. - 3 'breakTime': String, // Una cadena de texto que representa el tiempo de descanso, ej: '1 hour'. - 4 } - - --- - - Siguiente archivo: lib/screens/auth/profile_setup_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../profile_setup_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ De acuerdo, aquí está el análisis del archivo. - - --- - - lib/screens/auth/profile_setup_screen.dart - - Este archivo contiene dos usos distintos de Map: - - 1. Variable: static const List> _steps - - * Propósito: Define los pasos en el asistente de creación de perfiles. - * Estructura de cada elemento: - 1 { - 2 'id': String, - 3 'title': String, - 4 'icon': IconData - 5 } - - 2. Argumento de Función: El Map anónimo pasado a mockService.createWorkerProfile({ ... }) - - * Propósito: Recopilar y enviar los datos del perfil del nuevo usuario al servicio (en este caso, un mock). - * Estructura: - - 1 { - 2 'full_name': String, - 3 'bio': String, - 4 'preferred_locations': List, - 5 'max_distance_miles': double, - 6 'skills': List, - 7 'industries': List - 8 } - - --- - - Siguiente archivo: lib/screens/worker/worker_profile_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../worker_profile_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Claro, aquí está el análisis del archivo. - - --- - - lib/screens/worker/worker_profile_screen.dart - - Este archivo contiene dos variables Map para datos de simulación (mock). - - 1. Variable: final Map _user - - * Propósito: Almacena los datos básicos de identificación del usuario para mostrarlos en la pantalla de perfil. - * Estructura: - 1 { - 2 'full_name': String, - 3 'email': String, - 4 } - - 2. Variable: final Map _profile - - * Propósito: Almacena estadísticas y atributos detallados del trabajador para mostrarlos en la pantalla de perfil. - * Estructura: - - 1 { - 2 'level': String, - 3 'photo_url': String?, - 4 'total_shifts': int, - 5 'average_rating': double, - 6 'on_time_rate': int, - 7 'no_show_count': int, - 8 'cancellation_count': int, - 9 'reliability_score': int, - 10 'phone': String, - 11 'skills': List, // Mockeado como una lista vacía - 12 } - - --- - - Siguiente archivo: lib/screens/worker/benefits_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../worker/benefits_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ De acuerdo, aquí está el análisis del siguiente archivo. - - --- - - lib/screens/worker/benefits_screen.dart - - Este archivo utiliza Map para gestionar los datos de los beneficios del trabajador. - - 1. Variable: final List> _benefitsData - - * Propósito: Contiene los datos de simulación (mock) para los diferentes beneficios del trabajador, como días de enfermedad y vacaciones. - * Estructura de cada elemento: - - 1 { - 2 'id': String, - 3 'title': String, - 4 'current': int, - 5 'total': int, - 6 'color': Color, - 7 'description': String, - 8 'history': List>, // <- Lista anidada - 9 'requestLabel': String, - 10 'notice': String?, // Opcional - 11 } - * Estructura anidada de `history`: - 1 { - 2 'date': String, - 3 'status': String - 4 } - - 2. Parámetro de Función: void _handleRequest(Map benefit) - - * Propósito: Maneja la acción cuando un usuario solicita un beneficio, tomando uno de los objetos Map de _benefitsData como entrada. - * Estructura: La misma que la de los elementos en _benefitsData. - - 3. Parámetro de Widget: final Map benefit (en _BenefitCard) - - * Propósito: El widget _BenefitCard utiliza un Map de _benefitsData para mostrar los detalles de un beneficio. - * Estructura: La misma que la de los elementos en _benefitsData. - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/compliance/documents_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../documents_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Sigamos. - - --- - - lib/screens/worker/worker_profile/compliance/documents_screen.dart - - Este archivo, similar a otros, usa Map para la gestión de datos de UI. - - 1. Variable: final List> _requiredDocs - - * Propósito: Almacena la lista de documentos de cumplimiento requeridos para el trabajador. - * Estructura de cada elemento: - - 1 { - 2 'id': String, - 3 'name': String, - 4 'description': String, - 5 'status': String // Ejemplo: 'verified', 'pending', 'missing' - 6 } - - 2. Parámetro de Función: Widget _buildDocumentCard(Map doc) - - * Propósito: Es una función de construcción que crea una tarjeta de UI para un solo documento, tomando como entrada un Map de la lista _requiredDocs. - * Estructura: La estructura del parámetro doc es la misma que la de los elementos en la lista _requiredDocs. - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/onboarding/emergency_contact_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile l/.../emergency_contact_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Sigamos. - - --- - - lib/screens/worker/worker_profile/onboarding/emergency_contact_screen.dart - - Este archivo gestiona los contactos de emergencia del trabajador. - - 1. Variable: final List> _contacts - - * Propósito: Almacena una lista de los contactos de emergencia del trabajador. - * Estructura de cada elemento: - - 1 { - 2 'name': String, - 3 'phone': String, - 4 'relationship': String // Ejemplo: 'family', 'spouse', 'friend', 'other' - 5 } - - 2. Parámetro de Función: Widget _buildContactForm(int index, Map contact) - - * Propósito: Es una función de construcción que toma un Map de un solo contacto de la lista _contacts para crear un formulario para ese contacto. - * Estructura: La estructura del parámetro contact es la misma que la de los elementos en la lista _contacts. - - 3. Parámetro de Función: void _updateContact(int index, String field, dynamic value) - - * Propósito: Esta función actualiza un campo dentro de un Map de contacto específico en la lista _contacts. El value es dynamic ya que puede ser un String de un TextField o de un - DropdownButton. - * Estructura: No tiene una estructura de mapa específica, pero opera sobre los mapas dentro de la lista _contacts. - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/compliance/certificates_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../certificates_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Okay, aquí está el análisis del archivo certificates_screen.dart. - - --- - - lib/screens/worker/worker_profile/compliance/certificates_screen.dart - - Este archivo maneja los certificados de cumplimiento del trabajador. - - 1. Variable: final List> _certificates - - * Propósito: Almacena una lista de los certificados de cumplimiento del trabajador (por ejemplo, verificación de antecedentes, manipulador de alimentos). - * Estructura de cada elemento: - - 1 { - 2 'id': String, - 3 'name': String, - 4 'icon': IconData, - 5 'color': Color, - 6 'description': String, - 7 'status': String, // Ejemplo: 'complete', 'expiring', 'not_started' - 8 'expiry': String?, // Cadena de fecha ISO 8601 que puede ser nula - 9 } - - 2. Parámetro de Función: Widget _buildCertificateCard(Map cert) - - * Propósito: Es una función de construcción que crea una tarjeta de UI para un solo certificado, tomando como entrada un Map de la lista _certificates. - * Estructura: La estructura del parámetro cert es la misma que la de los elementos en _certificates. - - 3. Parámetro de Función: void _showUploadModal(BuildContext context, Map? cert) - - * Propósito: Esta función muestra una hoja modal para subir un certificado. Acepta un Map opcional cert. Si se proporciona cert, el modal es para renovar o ver ese certificado específico. - Si es null, es para subir un nuevo certificado sin categoría. - * Estructura: La estructura del parámetro cert es la misma que la de los elementos en _certificates. - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/compliance/tax_forms_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../tax_forms_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Sigamos. - - --- - - lib/screens/worker/worker_profile/compliance/tax_forms_screen.dart - - Este archivo gestiona la lista de formularios de impuestos del trabajador. - - 1. Variable: final List> _forms - - * Propósito: Almacena una lista de los formularios de impuestos requeridos. - * Estructura de cada elemento: - - 1 { - 2 'id': String, - 3 'title': String, - 4 'subtitle': String, - 5 'description': String, - 6 'status': String, // Ejemplo: 'submitted', 'not_started' - 7 'icon': String, // Un emoji usado como icono - 8 } - - 2. Parámetro de Función: Widget _buildFormCard(Map form) - - * Propósito: Es una función de construcción que crea una tarjeta de UI para un solo formulario de impuestos, tomando como entrada un Map de la lista _forms. - * Estructura: La estructura del parámetro form es la misma que la de los elementos en la lista _forms. - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/onboarding/personal_info_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../personal_info_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Sigamos. - - --- - - lib/screens/worker/worker_profile/onboarding/personal_info_screen.dart - - Este archivo contiene los datos de simulación (mock) para el formulario de información personal. - - 1. Variable: final Map _user - - * Propósito: Almacena los datos básicos del usuario para mostrarlos en el formulario. - * Estructura: - - 1 { - 2 'full_name': String, - 3 'email': String, - 4 'photo_url': String?, // Admite valores nulos - 5 } - * Nota: Esta versión del mock _user es ligeramente diferente a la de worker_profile_screen.dart, ya que incluye el campo photo_url. - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/onboarding/attire_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../attire_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Sigamos. - - --- - - lib/screens/worker/worker_profile/onboarding/attire_screen.dart - - Este archivo maneja el "armario" o la vestimenta que posee el trabajador. - - 1. Variable: final List> _attireOptions - - * Propósito: Proporciona una lista de opciones de vestimenta seleccionables para el trabajador. - * Estructura de cada elemento: - - 1 { - 2 'id': String, - 3 'label': String, - 4 'icon': IconData, - 5 'imageUrl': String, - 6 } - - (Nota: Este archivo también contiene `Map` y `Map` para la gestión del estado, pero no coinciden con el tipo `Map`). - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/compliance/taxforms/form_i9_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../form_i9_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Sigamos. - - --- - - lib/screens/worker/worker_profile/compliance/taxforms/form_i9_screen.dart - - Este archivo contiene el formulario I-9 y utiliza mapas para gestionar los datos del formulario y los pasos del asistente. - - 1. Variable: final Map _formData - - * Propósito: Almacena el estado de los campos del formulario I-9 mientras el usuario los completa. - * Estructura: - - 1 { - 2 'lastName': String, - 3 'firstName': String, - 4 'middleInitial': String, - 5 'otherLastNames': String, - 6 'address': String, - 7 'aptNumber': String, - 8 'city': String, - 9 'state': String?, // Admite valores nulos - 10 'zipCode': String, - 11 'dateOfBirth': String, - 12 'ssn': String, - 13 'email': String, - 14 'phone': String, - 15 'citizenshipStatus': String, - 16 'uscisNumber': String, - 17 'i94Number': String, - 18 'foreignPassportNumber': String, - 19 'countryOfIssuance': String, - 20 'expirationDate': String, - 21 } - - 2. Variable: final List> _steps - - * Nota: Aunque este no es un Map, sigue un patrón similar. - * Propósito: Define los pasos del asistente del formulario I-9. - * Estructura de cada elemento: - 1 { - 2 'title': String, - 3 'subtitle': String, - 4 } - - 3. Parámetro de Función: void _updateField(String key, dynamic value) - - * Propósito: Esta función actualiza un campo en el mapa _formData. El value es dynamic porque puede ser un String de un TextField o de un DropdownButton. - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/compliance/taxforms/form_w4_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../form_w4_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Claro, aquí tienes el análisis. - - --- - - lib/screens/worker/worker_profile/compliance/taxforms/form_w4_screen.dart - - Este archivo contiene el formulario W-4 y, de manera similar al I-9, utiliza mapas para gestionar los datos. - - 1. Variable: final Map _formData - - * Propósito: Almacena el estado de los campos del formulario W-4 mientras el usuario los completa. - * Estructura: - - 1 { - 2 'firstName': String, - 3 'lastName': String, - 4 'address': String, - 5 'cityStateZip': String, - 6 'ssn': String, - 7 'filingStatus': String, - 8 'multipleJobs': bool, - 9 'qualifyingChildren': int, - 10 'otherDependents': int, - 11 'otherIncome': String, // Representa una cantidad en dólares - 12 'deductions': String, // Representa una cantidad en dólares - 13 'extraWithholding': String, // Representa una cantidad en dólares - 14 } - - 2. Variable: final List> _steps - - * Nota: Aunque este es un List>, sigue un patrón de uso de mapas para definir metadatos. - * Propósito: Define los pasos del asistente del formulario W-4. - * Estructura de cada elemento: - 1 { - 2 'title': String, - 3 'subtitle': String, - 4 } - - 3. Parámetro de Función: void _updateField(String key, dynamic value) - - * Propósito: Esta función actualiza un campo en el mapa _formData. El value es dynamic porque puede ser un String, bool, o int dependiendo del campo del formulario que se esté - actualizando. - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/level_up/trainings_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../trainings_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ De acuerdo. - - --- - - lib/screens/worker/worker_profile/level_up/trainings_screen.dart - - Este archivo contiene la lista de cursos de capacitación para los trabajadores. - - 1. Variable: final List> _courses - - * Propósito: Almacena una lista de los cursos de capacitación disponibles. - * Estructura de cada elemento: - - 1 { - 2 'id': String, - 3 'title': String, - 4 'description': String, - 5 'duration_minutes': int, - 6 'xp_reward': int, - 7 'thumbnail_url': String?, // Admite valores nulos - 8 'progress_percent': int, - 9 'completed': bool, - 10 } - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/finances/time_card_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../time_card_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Okay, analicemos este archivo. - - --- - - lib/screens/worker/worker_profile/finances/time_card_screen.dart - - Este archivo se utiliza para mostrar el historial de horas trabajadas del empleado. - - 1. Variable: final List> _timesheets - - * Propósito: Almacena una lista de registros de hojas de tiempo (timesheets) para los turnos trabajados. - * Estructura de cada elemento: - - 1 { - 2 'id': String, - 3 'shift_id': String, - 4 'date': String, // Cadena en formato ISO 8601 - 5 'actual_start': String, - 6 'actual_end': String, - 7 'total_hours': double, - 8 'hourly_rate': double, - 9 'total_pay': double, - 10 'status': String, // Ejemplo: 'pending', 'approved', 'paid' - 11 'shift_title': String, - 12 'client_name': String, - 13 'location': String, - 14 } - - 2. Parámetro de Función: Widget _buildShiftHistory(List> timesheets) - - * Propósito: Es una función de construcción que toma una lista de mapas de hojas de tiempo para renderizar la sección de historial. - * Estructura: La estructura del parámetro timesheets es una lista de mapas, donde cada mapa tiene la misma estructura que los elementos en _timesheets. - - 3. Parámetro de Función: Widget _buildTimesheetCard(Map timesheet) - - * Propósito: Es una función de construcción que crea una tarjeta de UI para un único registro de hoja de tiempo de la lista _timesheets. - * Estructura: La estructura del parámetro timesheet es la misma que la de los elementos en _timesheets. - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/support/faqs_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../support/faqs_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Sigamos. - - --- - - lib/screens/worker/worker_profile/support/faqs_screen.dart - - Este archivo contiene los datos para la pantalla de Preguntas Frecuentes (FAQs). - - 1. Variable: final List> _faqData - - * Propósito: Almacena los datos para las preguntas frecuentes, organizados por categoría. - * Estructura de cada elemento (categoría): - - 1 { - 2 'category': String, - 3 'questions': List>, // <- Lista anidada - 4 } - * Estructura anidada de `questions`: - 1 { - 2 'q': String, // La pregunta - 3 'a': String, // La respuesta - 4 } - - (Nota: Este archivo también contiene un `Map` llamado `_openItems` para gestionar el estado de la UI, pero no coincide con el tipo `Map`). - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/level_up/krow_university_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../krow_university_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Sigamos. - - --- - - lib/screens/worker/worker_profile/level_up/krow_university_screen.dart - - Este archivo es para la sección de "KROW University" y contiene varios usos de Map. - - 1. Variable: final Map _profile - - * Propósito: Almacena un subconjunto de los datos del perfil del trabajador que son relevantes para la sección de universidad/capacitación. - * Estructura: - - 1 { - 2 'level': String, - 3 'xp': int, - 4 'nextLevelXp': int, - 5 'completed_courses': int, - 6 } - * Nota: Este mapa _profile es inconsistente con el que se encuentra en worker_profile_screen.dart, lo que demuestra la necesidad de un modelo de datos unificado. - - 2. Variable: final List> _categories - - * Propósito: Define las categorías para los cursos de la universidad. - * Estructura de cada elemento: - - 1 { - 2 'id': String, - 3 'label': String, - 4 'icon': IconData, - 5 } - - 3. Variable: final List> _courses - - * Propósito: Almacena una lista de los cursos universitarios disponibles. - * Estructura de cada elemento: - - 1 { - 2 'id': String, - 3 'title': String, - 4 'description': String, - 5 'category': String, - 6 'duration_minutes': int, - 7 'xp_reward': int, - 8 'level_required': String, - 9 'is_certification': bool, - 10 'progress_percent': int, - 11 'completed': bool, - 12 } - - 4. Parámetro de Función: Widget _buildCoursesGrid(List> courses) - - * Propósito: Es una función de construcción que toma una lista de mapas de cursos (filtrados de _courses) para renderizarlos en una cuadrícula. - * Estructura: La estructura del parámetro courses es una lista de mapas, donde cada mapa tiene la misma estructura que los elementos en _courses. - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/level_up/leaderboard_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../leaderboard_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Sigamos con el siguiente archivo. - - --- - - lib/screens/worker/worker_profile/level_up/leaderboard_screen.dart - - Este archivo es para la pantalla de la tabla de clasificación (Leaderboard) y utiliza mapas extensivamente para manejar los datos de los perfiles. - - 1. Variable: final List> _profiles - - * Propósito: Almacena los datos de simulación (mock) para la tabla de clasificación, representando diferentes perfiles de trabajadores. - * Estructura de cada elemento: - - 1 { - 2 'id': String, - 3 'name': String, - 4 'photo_url': String?, // Admite valores nulos - 5 'xp': int, - 6 'level': String, - 7 'user_id': String, - 8 } - - 2. Variable: final sortedProfiles = List>.from(_profiles) - - * Propósito: Crea una copia mutable de la lista _profiles que puede ser ordenada por XP. - * Estructura: Los elementos tienen la misma estructura que en _profiles. - - 3. Parámetro de Función: Widget _buildPodium(List> topThree) - - * Propósito: Es una función de construcción que toma los tres perfiles principales para renderizar la sección del podio. - * Estructura: La lista topThree contiene mapas con la misma estructura que en _profiles. - - 4. Parámetro de Función: Widget _buildPodiumItem(Map profile, ...) - - * Propósito: Es una función de construcción para crear la UI de un solo perfil en el podio. - * Estructura: El parámetro profile tiene la misma estructura que un elemento en _profiles. - - 5. Parámetro de Función: Widget _buildRestList(List> rest, ...) - - * Propósito: Es una función de construcción que toma el resto de los perfiles (que no están en el top tres) para renderizarlos como una lista estándar. - * Estructura: La lista rest contiene mapas con la misma estructura que en _profiles. - - --- - - Siguiente archivo: lib/screens/worker/worker_profile/finances/bank_account_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../bank_account_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Sigamos. - - --- - - lib/screens/worker/worker_profile/finances/bank_account_screen.dart - - Este archivo maneja las cuentas bancarias del trabajador. - - 1. Variable: final List> _accounts - - * Propósito: Almacena una lista de las cuentas bancarias vinculadas del trabajador. - * Estructura de cada elemento: - - 1 { - 2 'id': int, - 3 'bank': String, - 4 'type': String, // Ejemplo: 'Checking', 'Savings' - 5 'last4': String, - 6 'isPrimary': bool, - 7 } - - 2. Parámetro de Función: Widget _buildAccountCard(Map account) - - * Propósito: Es una función de construcción que crea una tarjeta de UI para una sola cuenta bancaria, tomando como entrada un Map de la lista _accounts. - * Estructura: La estructura del parámetro account es la misma que la de los elementos en la lista _accounts. - - --- - - Siguiente archivo: lib/screens/worker/payments_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../worker/payments_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Sigamos. - - --- - - lib/screens/worker/payments_screen.dart - - Este archivo muestra el historial de pagos y ganancias del trabajador. - - 1. Variable: final List> _recentPayments - - * Propósito: Almacena los datos de simulación (mock) para una lista de registros de pagos recientes. - * Estructura de cada elemento: - - 1 { - 2 'date': String, - 3 'title': String, - 4 'location': String, - 5 'address': String, - 6 'workedTime': String, - 7 'amount': double, - 8 'status': String, // Ejemplo: 'paid' - 9 'hours': int, - 10 'rate': int, // Nota: Esto es un int en el mock, pero probablemente debería ser double como en otros lugares. - 11 } - * Nota: El widget PaymentHistoryItem que consume estos datos espera que rate sea un double, por lo que el int en los datos del mock es probablemente una pequeña inconsistencia. - - --- - - Siguiente archivo: lib/screens/worker/availability_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../availability_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Okay, aquí está el análisis del archivo de disponibilidad. - - --- - - lib/screens/worker/availability_screen.dart - - Este archivo maneja la configuración de la disponibilidad del trabajador. - - 1. Variable: final List> _timeSlots - - * Propósito: Define las propiedades de los diferentes rangos horarios (Mañana, Tarde, Noche) que el usuario puede seleccionar. - * Estructura de cada elemento: - - 1 { - 2 'id': String, - 3 'label': String, - 4 'time': String, // Ejemplo: '4:00 AM - 12:00 PM' - 5 'icon': IconData, - 6 'bg': Color, - 7 'iconColor': Color, - 8 } - - (Nota: Este archivo también utiliza `Map` y `Map>` para gestionar el estado de la disponibilidad, pero no coinciden con el tipo `Map`). - - --- - - Siguiente archivo: lib/screens/worker/clock_in_screen.dart. -╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ ✓ ReadFile lib/.../worker/clock_in_screen.dart │ -│ │ -╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -✦ Okay, aquí está el análisis del último archivo de la lista. - - --- - - lib/screens/worker/clock_in_screen.dart - - Este archivo gestiona la pantalla de fichaje (check-in/check-out) del trabajador. - - 1. Variable: final List> _recentActivity - - * Propósito: Almacena una lista de las actividades recientes de fichaje del trabajador. - * Estructura de cada elemento: - - 1 { - 2 'date': DateTime, - 3 'start': String, // Ejemplo: '09:00 AM' - 4 'end': String, // Ejemplo: '05:00 PM' - 5 'hours': String, // Ejemplo: '8h' - 6 } - - --- - - ✦ He analizado lib/screens/worker/worker_profile/support/messages_screen.dart. - - Este archivo contiene dos estructuras principales de List>: - - 1. Nombre de la variable: _conversations - * Propósito: Representa una lista de conversaciones de chat. - * Estructura de cada elemento `Map` (que representa una conversación individual): - - 1 { - 2 'sender_id': String, // ID del remitente/otra parte en la conversación - 3 'sender_name': String, // Nombre visible del remitente/otra parte - 4 'lastMessage': String, // Contenido del último mensaje en la conversación - 5 'lastTime': DateTime, // Marca de tiempo del último mensaje - 6 'unread': int, // Número de mensajes no leídos en la conversación - 7 'messages': List>, // Lista anidada de mensajes individuales dentro de la conversación - 8 } - * Estructura Anidada (`messages`): Cada elemento en la lista messages tiene: - - 1 { - 2 'content': String, // El contenido del mensaje - 3 'sender_id': String, // El ID del remitente de este mensaje específico - 4 } - - El siguiente archivo es: lib/screens/worker/worker_profile/onboarding/attire_screen.dart. - --- - - He finalizado el análisis de todos los archivos que contenían Map. Has podido ver que este tipo de mapa se usa de forma muy extendida en todo el proyecto para simular - datos, pasar parámetros y definir el estado de los widgets. - - La principal conclusión es la falta de modelos de datos formales (clases Dart), lo que lleva a la duplicación e inconsistencia de las estructuras de datos en diferentes pantallas. - - Mi recomendación principal, como ingeniero senior, sería refactorizar este código para usar clases de modelo fuertemente tipadas. Esto mejoraría enormemente la mantenibilidad, la - legibilidad y la seguridad del código, reduciendo errores a largo plazo. - - ¿Hay alguna de estas estructuras que te interese formalizar en una clase Dart ahora? O, ¿tienes alguna otra pregunta? - - Using: 1 GEMINI.md file diff --git a/apps/mobile/prototypes/staff_mobile_application/mock_staff_data_v3_update.md b/apps/mobile/prototypes/staff_mobile_application/mock_staff_data_v3_update.md deleted file mode 100644 index 33315037..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/mock_staff_data_v3_update.md +++ /dev/null @@ -1,594 +0,0 @@ -# Análisis Exhaustivo de `Map` en el Proyecto - -Este documento detalla todos los usos del tipo `Map` encontrados en los archivos `.dart` del proyecto, incluyendo variables, listas, parámetros y tipos de retorno de funciones. - ---- - -### `lib/widgets/shift_card.dart` - -#### 1. Tipo de Retorno de Función: `Map _calculateDuration()` -* **Propósito:** Calcula la duración de un turno en horas y devuelve también una cadena de texto para el tiempo de descanso. -* **Estructura del `Map` devuelto:** - ```dart - { - 'hours': int, - 'breakTime': String, - } - ``` - ---- - -### `lib/services/mock_service.dart` - -#### 1. Parámetro de Función: `Future createWorkerProfile(Map data)` -* **Propósito:** Simula la creación de un perfil de trabajador. Acepta un `Map` llamado `data` que contiene la información del perfil del nuevo trabajador. -* **Estructura Inferida (por su uso):** - ```dart - { - 'full_name': String, - 'bio': String, - 'preferred_locations': List, - 'max_distance_miles': double, - 'skills': List, - 'industries': List, - } - ``` - ---- - -### `lib/screens/auth/profile_setup_screen.dart` - -#### 1. Variable: `static const List> _steps` -* **Propósito:** Define los pasos en el asistente de creación de perfiles. -* **Estructura de cada elemento:** - ```dart - { - 'id': String, - 'title': String, - 'icon': IconData - } - ``` - -#### 2. Argumento de Función: (Anónimo) en `mockService.createWorkerProfile` -* **Propósito:** Recopila y envía los datos del perfil del nuevo usuario al servicio mock. -* **Estructura:** - ```dart - { - 'full_name': String, - 'bio': String, - 'preferred_locations': List, - 'max_distance_miles': double, - 'skills': List, - 'industries': List - } - ``` - ---- - -### `lib/screens/worker/benefits_screen.dart` - -#### 1. Variable: `final List> _benefitsData` -* **Propósito:** Contiene los datos de simulación (mock) para los diferentes beneficios del trabajador. -* **Estructura de cada elemento:** - ```dart - { - 'id': String, - 'title': String, - 'current': int, - 'total': int, - 'color': Color, - 'description': String, - 'history': List>, // <- Lista anidada - 'requestLabel': String, - 'notice': String?, - } - ``` - * **Estructura anidada de `history`:** - ```dart - { - 'date': String, - 'status': String - } - ``` - -#### 2. Parámetro de Función: `void _handleRequest(Map benefit)` -* **Propósito:** Maneja la acción cuando un usuario solicita un beneficio. -* **Estructura:** La misma que los elementos de `_benefitsData`. - -#### 3. Parámetro de Widget: `final Map benefit` -* **Propósito:** El widget `_BenefitCard` recibe un `Map` para mostrar los detalles de un beneficio. -* **Estructura:** La misma que los elementos de `_benefitsData`. - ---- - -### `lib/screens/worker/worker_profile_screen.dart` - -#### 1. Variable: `final Map _user` -* **Propósito:** Almacena datos básicos de identificación del usuario. -* **Estructura:** - ```dart - { - 'full_name': String, - 'email': String, - } - ``` - -#### 2. Variable: `final Map _profile` -* **Propósito:** Almacena estadísticas y atributos detallados del perfil del trabajador. -* **Estructura:** - ```dart - { - 'level': String, - 'photo_url': String?, - 'total_shifts': int, - 'average_rating': double, - 'on_time_rate': int, - 'no_show_count': int, - 'cancellation_count': int, - 'reliability_score': int, - 'phone': String, - 'skills': List, - } - ``` - ---- - -### `lib/screens/worker/worker_profile/onboarding/emergency_contact_screen.dart` - -#### 1. Variable: `final List> _contacts` -* **Propósito:** Almacena una lista de los contactos de emergencia. -* **Estructura de cada elemento:** - ```dart - { - 'name': String, - 'phone': String, - 'relationship': String - } - ``` - -#### 2. Parámetro de Función: `Widget _buildContactForm(int index, Map contact)` -* **Propósito:** Construye el widget del formulario para un contacto. -* **Estructura:** La misma que los elementos de `_contacts`. - ---- - -### `lib/screens/worker/worker_profile/onboarding/personal_info_screen.dart` - -#### 1. Variable: `final Map _user` -* **Propósito:** Almacena los datos básicos del usuario para el formulario. -* **Estructura:** - ```dart - { - 'full_name': String, - 'email': String, - 'photo_url': String?, - } - ``` - ---- - -### `lib/screens/worker/worker_profile/finances/time_card_screen.dart` - -#### 1. Variable: `final List> _timesheets` -* **Propósito:** Almacena una lista de registros de hojas de tiempo (timesheets). -* **Estructura de cada elemento:** - ```dart - { - 'id': String, - 'shift_id': String, - 'date': String, // ISO 8601 - 'actual_start': String, - 'actual_end': String, - 'total_hours': double, - 'hourly_rate': double, - 'total_pay': double, - 'status': String, - 'shift_title': String, - 'client_name': String, - 'location': String, - } - ``` - -#### 2. Parámetro de Función: `Widget _buildShiftHistory(List> timesheets)` -* **Propósito:** Construye la sección de historial de turnos. -* **Estructura:** Una lista donde cada elemento tiene la estructura de `_timesheets`. - -#### 3. Parámetro de Función: `Widget _buildTimesheetCard(Map timesheet)` -* **Propósito:** Construye la tarjeta para una sola hoja de tiempo. -* **Estructura:** La misma que los elementos de `_timesheets`. - ---- - -### `lib/screens/worker/worker_profile/finances/bank_account_screen.dart` - -#### 1. Variable: `final List> _accounts` -* **Propósito:** Almacena una lista de las cuentas bancarias vinculadas. -* **Estructura de cada elemento:** - ```dart - { - 'id': int, - 'bank': String, - 'type': String, - 'last4': String, - 'isPrimary': bool, - } - ``` - -#### 2. Parámetro de Función: `Widget _buildAccountCard(Map account)` -* **Propósito:** Construye la tarjeta para una sola cuenta bancaria. -* **Estructura:** La misma que los elementos de `_accounts`. - ---- - -### `lib/screens/worker/worker_profile/level_up/trainings_screen.dart` - -#### 1. Variable: `final List> _courses` -* **Propósito:** Almacena una lista de cursos de capacitación. -* **Estructura de cada elemento:** - ```dart - { - 'id': String, - 'title': String, - 'description': String, - 'duration_minutes': int, - 'xp_reward': int, - 'thumbnail_url': String?, - 'progress_percent': int, - 'completed': bool, - } - ``` - ---- - -### `lib/screens/worker/worker_profile/level_up/leaderboard_screen.dart` - -#### 1. Variable: `final List> _profiles` -* **Propósito:** Almacena los datos de los perfiles para la tabla de clasificación. -* **Estructura de cada elemento:** - ```dart - { - 'id': String, - 'name': String, - 'photo_url': String?, - 'xp': int, - 'level': String, - 'user_id': String, - } - ``` - -#### 2. Variable: `final sortedProfiles = List>.from(_profiles)` -* **Propósito:** Crea una copia mutable de la lista de perfiles para ordenarla. -* **Estructura:** Los elementos tienen la misma estructura que `_profiles`. - -#### 3. Parámetro de Función: `Widget _buildPodium(List> topThree)` -* **Propósito:** Construye la sección del podio con los 3 mejores perfiles. -* **Estructura:** Una lista donde cada mapa tiene la estructura de un elemento de `_profiles`. - -#### 4. Parámetro de Función: `Map profile` (en `_buildPodiumItem`) -* **Propósito:** Construye el item para un perfil en el podio. -* **Estructura:** La misma que un elemento de `_profiles`. - -#### 5. Parámetro de Función: `Widget _buildRestList(List> rest, ...)` -* **Propósito:** Construye la lista para el resto de los perfiles. -* **Estructura:** Una lista donde cada mapa tiene la estructura de un elemento de `_profiles`. - ---- - -### `lib/screens/worker/worker_profile/onboarding/attire_screen.dart` - -#### 1. Variable: `final List> _attireOptions` -* **Propósito:** Define las opciones de vestimenta que un trabajador puede seleccionar. -* **Estructura de cada elemento:** - ```dart - { - 'id': String, - 'label': String, - 'icon': IconData, - 'imageUrl': String, - } - ``` - ---- - -### `lib/screens/worker/worker_profile/support/faqs_screen.dart` - -#### 1. Variable: `final List> _faqData` -* **Propósito:** Almacena los datos de las preguntas frecuentes, organizados por categoría. -* **Estructura de cada elemento (categoría):** - ```dart - { - 'category': String, - 'questions': List>, // <- Lista anidada - } - ``` - * **Estructura anidada de `questions`:** - ```dart - { - 'q': String, // Pregunta - 'a': String, // Respuesta - } - ``` - ---- - -### `lib/screens/worker/worker_profile/support/messages_screen.dart` - -#### 1. Variable: `final List> _conversations` -* **Propósito:** Contiene los datos de simulación para las conversaciones de chat. -* **Estructura de cada elemento (conversación):** - ```dart - { - 'sender_id': String, - 'sender_name': String, - 'lastMessage': String, - 'lastTime': DateTime, - 'unread': int, - 'messages': List>, // <- Lista anidada - } - ``` - * **Estructura anidada de `messages`:** - ```dart - { - 'content': String, - 'sender_id': String, - } - ``` - -#### 2. Variable: `Map? _selectedChat` -* **Propósito:** Almacena la conversación que el usuario ha seleccionado para ver. -* **Estructura:** La misma que un elemento de `_conversations`. - ---- - -### `lib/screens/worker/payments_screen.dart` - -#### 1. Variable: `final List> _recentPayments` -* **Propósito:** Almacena registros detallados de pagos recientes. -* **Estructura de cada elemento:** - ```dart - { - 'date': String, - 'title': String, - 'location': String, - 'address': String, - 'workedTime': String, - 'amount': double, - 'status': String, - 'hours': int, - 'rate': int, // Debería ser double - } - ``` - ---- - -### `lib/screens/worker/worker_profile/compliance/documents_screen.dart` - -#### 1. Variable: `final List> _requiredDocs` -* **Propósito:** Almacena la lista de documentos de cumplimiento requeridos. -* **Estructura de cada elemento:** - ```dart - { - 'id': String, - 'name': String, - 'description': String, - 'status': String, - } - ``` - -#### 2. Parámetro de Función: `Widget _buildDocumentCard(Map doc)` -* **Propósito:** Construye la tarjeta de UI para un solo documento. -* **Estructura:** La misma que los elementos de `_requiredDocs`. - ---- - -### `lib/screens/worker/worker_profile/compliance/tax_forms_screen.dart` - -#### 1. Variable: `final List> _forms` -* **Propósito:** Almacena la lista de formularios de impuestos. -* **Estructura de cada elemento:** - ```dart - { - 'id': String, - 'title': String, - 'subtitle': String, - 'description': String, - 'status': String, - 'icon': String, // Emoji - } - ``` - -#### 2. Parámetro de Función: `Widget _buildFormCard(Map form)` -* **Propósito:** Construye la tarjeta de UI para un solo formulario. -* **Estructura:** La misma que los elementos de `_forms`. - ---- - -### `lib/screens/worker/availability_screen.dart` - -#### 1. Variable: `final List> _timeSlots` -* **Propósito:** Define las propiedades de los diferentes rangos horarios para la disponibilidad. -* **Estructura de cada elemento:** - ```dart - { - 'id': String, - 'label': String, - 'time': String, - 'icon': IconData, - 'bg': Color, - 'iconColor': Color, - } - ``` - ---- - -### `lib/screens/worker/worker_profile/compliance/certificates_screen.dart` - -#### 1. Variable: `final List> _certificates` -* **Propósito:** Almacena la lista de certificados de cumplimiento del trabajador. -* **Estructura de cada elemento:** - ```dart - { - 'id': String, - 'name': String, - 'icon': IconData, - 'color': Color, - 'description': String, - 'status': String, - 'expiry': String?, // ISO 8601 - } - ``` - -#### 2. Parámetro de Función: `Widget _buildCertificateCard(Map cert)` -* **Propósito:** Construye la tarjeta de UI para un solo certificado. -* **Estructura:** La misma que los elementos de `_certificates`. - -#### 3. Parámetro de Función: `void _showUploadModal(BuildContext context, Map? cert)` -* **Propósito:** Muestra un modal para subir un certificado. -* **Estructura:** La misma que los elementos de `_certificates`. - ---- - -### `lib/screens/worker/worker_profile/compliance/taxforms/form_i9_screen.dart` - -#### 1. Variable: `final Map _formData` -* **Propósito:** Almacena el estado de los campos del formulario I-9. -* **Estructura:** - ```dart - { - 'lastName': String, - 'firstName': String, - 'middleInitial': String, - 'otherLastNames': String, - 'address': String, - 'aptNumber': String, - 'city': String, - 'state': String?, - 'zipCode': String, - 'dateOfBirth': String, - 'ssn': String, - 'email': String, - 'phone': String, - 'citizenshipStatus': String, - 'uscisNumber': String, - 'i94Number': String, - 'foreignPassportNumber': String, - 'countryOfIssuance': String, - 'expirationDate': String, - } - ``` - ---- - -### `lib/screens/worker/worker_profile/compliance/taxforms/form_w4_screen.dart` - -#### 1. Variable: `final Map _formData` -* **Propósito:** Almacena el estado de los campos del formulario W-4. -* **Estructura:** - ```dart - { - 'firstName': String, - 'lastName': String, - 'address': String, - 'cityStateZip': String, - 'ssn': String, - 'filingStatus': String, - 'multipleJobs': bool, - 'qualifyingChildren': int, - 'otherDependents': int, - 'otherIncome': String, - 'deductions': String, - 'extraWithholding': String, - } - ``` - ---- - -### `lib/screens/worker/worker_profile/level_up/krow_university_screen.dart` - -#### 1. Variable: `final Map _profile` -* **Propósito:** Almacena un subconjunto de datos del perfil relevantes para la universidad. -* **Estructura:** - ```dart - { - 'level': String, - 'xp': int, - 'badges': List, - } - ``` - -#### 2. Variable: `final List> _levels` -* **Propósito:** Define los diferentes niveles de Krower y sus propiedades. -* **Estructura de cada elemento:** - ```dart - { - 'name': String, - 'xpRequired': int, - 'icon': IconData, - 'colors': List, - } - ``` - -#### 3. Variable: `final List> _categories` -* **Propósito:** Define las categorías para los cursos. -* **Estructura de cada elemento:** - ```dart - { - 'id': String, - 'label': String, - 'icon': IconData, - } - ``` - -#### 4. Variable: `final List> _courses` -* **Propósito:** Almacena la lista de cursos disponibles. -* **Estructura de cada elemento:** - ```dart - { - 'id': String, - 'title': String, - 'description': String, - 'category': String, - 'duration_minutes': int, - 'xp_reward': int, - 'level_required': String, - 'is_certification': bool, - 'progress_percent': int, - 'completed': bool, - } - ``` - -#### 5. Parámetro de Función: `Widget _buildCoursesList(List> courses)` -* **Propósito:** Construye la lista de widgets de cursos. -* **Estructura:** Una lista donde cada mapa tiene la estructura de un elemento de `_courses`. - ---- - -### `lib/screens/worker/earnings_screen.dart` - -#### 1. Variable: `final List> _recentPayments` -* **Propósito:** Almacena resúmenes de pagos recientes. -* **Estructura de cada elemento:** - ```dart - { - 'date': String, - 'amount': double, - 'shifts': int, - 'status': String, - } - ``` - ---- - -### `lib/screens/worker/clock_in_screen.dart` - -#### 1. Variable: `final List> _recentActivity` -* **Propósito:** Almacena una lista de actividades recientes de fichaje. -* **Estructura de cada elemento:** - ```dart - { - 'date': DateTime, - 'start': String, - 'end': String, - 'hours': String, - } - ``` diff --git a/apps/mobile/prototypes/staff_mobile_application/pubspec.lock b/apps/mobile/prototypes/staff_mobile_application/pubspec.lock deleted file mode 100644 index 754381ac..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/pubspec.lock +++ /dev/null @@ -1,786 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: c209688d9f5a5f26b2fb47a188131a6fb9e876ae9e47af3737c0b4f58a93470d - url: "https://pub.dev" - source: hosted - version: "91.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: f51c8499b35f9b26820cfe914828a6a98a94efd5cc78b37bb7d03debae3a1d08 - url: "https://pub.dev" - source: hosted - version: "8.4.1" - archive: - dependency: transitive - description: - name: archive - sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" - url: "https://pub.dev" - source: hosted - version: "4.0.7" - args: - dependency: transitive - description: - name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" - source: hosted - version: "2.7.0" - async: - dependency: transitive - description: - name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" - url: "https://pub.dev" - source: hosted - version: "2.13.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - characters: - dependency: transitive - description: - name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" - url: "https://pub.dev" - source: hosted - version: "2.0.4" - cli_config: - dependency: transitive - description: - name: cli_config - sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec - url: "https://pub.dev" - source: hosted - version: "0.2.0" - cli_util: - dependency: transitive - description: - name: cli_util - sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c - url: "https://pub.dev" - source: hosted - version: "0.4.2" - clock: - dependency: transitive - description: - name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" - source: hosted - version: "1.1.2" - collection: - dependency: transitive - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - convert: - dependency: transitive - description: - name: convert - sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 - url: "https://pub.dev" - source: hosted - version: "3.1.2" - coverage: - dependency: transitive - description: - name: coverage - sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" - url: "https://pub.dev" - source: hosted - version: "1.15.0" - crypto: - dependency: transitive - description: - name: crypto - sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf - url: "https://pub.dev" - source: hosted - version: "3.0.7" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.dev" - source: hosted - version: "1.0.8" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" - source: hosted - version: "1.3.3" - ffi: - dependency: transitive - description: - name: ffi - sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - file: - dependency: transitive - description: - name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" - source: hosted - version: "7.0.1" - firebase_core: - dependency: "direct main" - description: - name: firebase_core - sha256: "1f2dfd9f535d81f8b06d7a50ecda6eac1e6922191ed42e09ca2c84bd2288927c" - url: "https://pub.dev" - source: hosted - version: "4.2.1" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - sha256: cccb4f572325dc14904c02fcc7db6323ad62ba02536833dddb5c02cac7341c64 - url: "https://pub.dev" - source: hosted - version: "6.0.2" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - sha256: ff18fabb0ad0ed3595d2f2c85007ecc794aadecdff5b3bb1460b7ee47cded398 - url: "https://pub.dev" - source: hosted - version: "3.3.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_launcher_icons: - dependency: "direct dev" - description: - name: flutter_launcher_icons - sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7" - url: "https://pub.dev" - source: hosted - version: "0.14.4" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" - url: "https://pub.dev" - source: hosted - version: "6.0.0" - flutter_riverpod: - dependency: "direct main" - description: - name: flutter_riverpod - sha256: "9e2d6907f12cc7d23a846847615941bddee8709bf2bfd274acdf5e80bcf22fde" - url: "https://pub.dev" - source: hosted - version: "3.0.3" - flutter_svg: - dependency: "direct main" - description: - name: flutter_svg - sha256: "87fbd7c534435b6c5d9d98b01e1fd527812b82e68ddd8bd35fc45ed0fa8f0a95" - url: "https://pub.dev" - source: hosted - version: "2.2.3" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - font_awesome_flutter: - dependency: "direct main" - description: - name: font_awesome_flutter - sha256: b9011df3a1fa02993630b8fb83526368cf2206a711259830325bab2f1d2a4eb0 - url: "https://pub.dev" - source: hosted - version: "10.12.0" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.dev" - source: hosted - version: "4.0.0" - glob: - dependency: transitive - description: - name: glob - sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.dev" - source: hosted - version: "2.1.3" - go_router: - dependency: "direct main" - description: - name: go_router - sha256: c92d18e1fe994cb06d48aa786c46b142a5633067e8297cff6b5a3ac742620104 - url: "https://pub.dev" - source: hosted - version: "17.0.0" - google_fonts: - dependency: "direct main" - description: - name: google_fonts - sha256: ba03d03bcaa2f6cb7bd920e3b5027181db75ab524f8891c8bc3aa603885b8055 - url: "https://pub.dev" - source: hosted - version: "6.3.3" - http: - dependency: transitive - description: - name: http - sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" - url: "https://pub.dev" - source: hosted - version: "1.6.0" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 - url: "https://pub.dev" - source: hosted - version: "3.2.2" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" - source: hosted - version: "4.1.2" - image: - dependency: transitive - description: - name: image - sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" - url: "https://pub.dev" - source: hosted - version: "4.5.4" - intl: - dependency: "direct main" - description: - name: intl - sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" - url: "https://pub.dev" - source: hosted - version: "0.20.2" - io: - dependency: transitive - description: - name: io - sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b - url: "https://pub.dev" - source: hosted - version: "1.0.5" - js: - dependency: transitive - description: - name: js - sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" - url: "https://pub.dev" - source: hosted - version: "0.7.2" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://pub.dev" - source: hosted - version: "4.9.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.dev" - source: hosted - version: "11.0.2" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.dev" - source: hosted - version: "3.0.10" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - lints: - dependency: transitive - description: - name: lints - sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 - url: "https://pub.dev" - source: hosted - version: "6.0.0" - logging: - dependency: transitive - description: - name: logging - sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" - source: hosted - version: "1.3.0" - lucide_icons: - dependency: "direct main" - description: - name: lucide_icons - sha256: ad24d0fd65707e48add30bebada7d90bff2a1bba0a72d6e9b19d44246b0e83c4 - url: "https://pub.dev" - source: hosted - version: "0.257.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.dev" - source: hosted - version: "0.12.17" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" - source: hosted - version: "0.11.1" - meta: - dependency: transitive - description: - name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" - url: "https://pub.dev" - source: hosted - version: "1.17.0" - mime: - dependency: transitive - description: - name: mime - sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - node_preamble: - dependency: transitive - description: - name: node_preamble - sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" - url: "https://pub.dev" - source: hosted - version: "2.0.2" - package_config: - dependency: transitive - description: - name: package_config - sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc - url: "https://pub.dev" - source: hosted - version: "2.2.0" - path: - dependency: transitive - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - path_parsing: - dependency: transitive - description: - name: path_parsing - sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - path_provider: - dependency: transitive - description: - name: path_provider - sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e - url: "https://pub.dev" - source: hosted - version: "2.2.22" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: "6d13aece7b3f5c5a9731eaf553ff9dcbc2eff41087fd2df587fd0fed9a3eb0c4" - url: "https://pub.dev" - source: hosted - version: "2.5.1" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" - source: hosted - version: "2.3.0" - petitparser: - dependency: transitive - description: - name: petitparser - sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" - url: "https://pub.dev" - source: hosted - version: "7.0.1" - platform: - dependency: transitive - description: - name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" - source: hosted - version: "3.1.6" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" - pool: - dependency: transitive - description: - name: pool - sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" - url: "https://pub.dev" - source: hosted - version: "1.5.2" - posix: - dependency: transitive - description: - name: posix - sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" - url: "https://pub.dev" - source: hosted - version: "6.0.3" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - riverpod: - dependency: transitive - description: - name: riverpod - sha256: c406de02bff19d920b832bddfb8283548bfa05ce41c59afba57ce643e116aa59 - url: "https://pub.dev" - source: hosted - version: "3.0.3" - shelf: - dependency: transitive - description: - name: shelf - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 - url: "https://pub.dev" - source: hosted - version: "1.4.2" - shelf_packages_handler: - dependency: transitive - description: - name: shelf_packages_handler - sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - shelf_static: - dependency: transitive - description: - name: shelf_static - sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 - url: "https://pub.dev" - source: hosted - version: "1.1.3" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - source_map_stack_trace: - dependency: transitive - description: - name: source_map_stack_trace - sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b - url: "https://pub.dev" - source: hosted - version: "2.1.2" - source_maps: - dependency: transitive - description: - name: source_maps - sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" - url: "https://pub.dev" - source: hosted - version: "0.10.13" - source_span: - dependency: transitive - description: - name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.dev" - source: hosted - version: "1.10.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" - source: hosted - version: "1.12.1" - state_notifier: - dependency: transitive - description: - name: state_notifier - sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb - url: "https://pub.dev" - source: hosted - version: "1.0.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test: - dependency: transitive - description: - name: test - sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7" - url: "https://pub.dev" - source: hosted - version: "1.26.3" - test_api: - dependency: transitive - description: - name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 - url: "https://pub.dev" - source: hosted - version: "0.7.7" - test_core: - dependency: transitive - description: - name: test_core - sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0" - url: "https://pub.dev" - source: hosted - version: "0.6.12" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - vector_graphics: - dependency: transitive - description: - name: vector_graphics - sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6 - url: "https://pub.dev" - source: hosted - version: "1.1.19" - vector_graphics_codec: - dependency: transitive - description: - name: vector_graphics_codec - sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" - url: "https://pub.dev" - source: hosted - version: "1.1.13" - vector_graphics_compiler: - dependency: transitive - description: - name: vector_graphics_compiler - sha256: d354a7ec6931e6047785f4db12a1f61ec3d43b207fc0790f863818543f8ff0dc - url: "https://pub.dev" - source: hosted - version: "1.1.19" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.dev" - source: hosted - version: "2.2.0" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" - url: "https://pub.dev" - source: hosted - version: "15.0.2" - watcher: - dependency: transitive - description: - name: watcher - sha256: "592ab6e2892f67760543fb712ff0177f4ec76c031f02f5b4ff8d3fc5eb9fb61a" - url: "https://pub.dev" - source: hosted - version: "1.1.4" - web: - dependency: transitive - description: - name: web - sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - web_socket: - dependency: transitive - description: - name: web_socket - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 - url: "https://pub.dev" - source: hosted - version: "3.0.3" - webkit_inspection_protocol: - dependency: transitive - description: - name: webkit_inspection_protocol - sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" - url: "https://pub.dev" - source: hosted - version: "1.2.1" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - xml: - dependency: transitive - description: - name: xml - sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" - url: "https://pub.dev" - source: hosted - version: "6.6.1" - yaml: - dependency: transitive - description: - name: yaml - sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.dev" - source: hosted - version: "3.1.3" -sdks: - dart: ">=3.10.0 <4.0.0" - flutter: ">=3.35.0" diff --git a/apps/mobile/prototypes/staff_mobile_application/pubspec.yaml b/apps/mobile/prototypes/staff_mobile_application/pubspec.yaml deleted file mode 100644 index 0328bd47..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/pubspec.yaml +++ /dev/null @@ -1,105 +0,0 @@ -name: staff_app_mvp -description: "A new Flutter project." -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -# In Windows, build-name is used as the major, minor, and patch parts -# of the product and file versions while build-number is used as the build suffix. -version: 1.0.0+8 - -environment: - sdk: ^3.10.0 - -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. -dependencies: - flutter: - sdk: flutter - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.8 - go_router: ^17.0.0 - flutter_riverpod: ^3.0.3 - google_fonts: ^6.3.3 - intl: ^0.20.2 - lucide_icons: ^0.257.0 - flutter_svg: ^2.2.3 - firebase_core: ^4.2.1 - font_awesome_flutter: ^10.12.0 - -dev_dependencies: - flutter_test: - sdk: flutter - - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^6.0.0 - flutter_launcher_icons: ^0.14.4 - -flutter_launcher_icons: - android: true - ios: true - image_path: "assets/logo.png" - remove_alpha_ios: true - -# 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: - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - assets: - - assets/logo.png - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/to/asset-from-package - - # To add custom fonts to your application, 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 from package dependencies, - # see https://flutter.dev/to/font-from-package diff --git a/apps/mobile/prototypes/staff_mobile_application/test/widget_test.dart b/apps/mobile/prototypes/staff_mobile_application/test/widget_test.dart deleted file mode 100644 index eed566dc..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/test/widget_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility in the flutter_test package. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:staff_app_mvp/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} diff --git a/apps/mobile/prototypes/staff_mobile_application/web/favicon.png b/apps/mobile/prototypes/staff_mobile_application/web/favicon.png deleted file mode 100644 index 8aaa46ac1ae21512746f852a42ba87e4165dfdd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM diff --git a/apps/mobile/prototypes/staff_mobile_application/web/icons/Icon-192.png b/apps/mobile/prototypes/staff_mobile_application/web/icons/Icon-192.png deleted file mode 100644 index b749bfef07473333cf1dd31e9eed89862a5d52aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5292 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 diff --git a/apps/mobile/prototypes/staff_mobile_application/web/icons/Icon-512.png b/apps/mobile/prototypes/staff_mobile_application/web/icons/Icon-512.png deleted file mode 100644 index 88cfd48dff1169879ba46840804b412fe02fefd6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8252 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 diff --git a/apps/mobile/prototypes/staff_mobile_application/web/icons/Icon-maskable-192.png b/apps/mobile/prototypes/staff_mobile_application/web/icons/Icon-maskable-192.png deleted file mode 100644 index eb9b4d76e525556d5d89141648c724331630325d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5594 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 X>c!)3PgKfL&lX^$Z>Cpu&6)6jvi^Z! diff --git a/apps/mobile/prototypes/staff_mobile_application/web/icons/Icon-maskable-512.png b/apps/mobile/prototypes/staff_mobile_application/web/icons/Icon-maskable-512.png deleted file mode 100644 index d69c56691fbdb0b7efa65097c7cc1edac12a6d3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20998 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 MPgg&ebxsLQ025IeI{*Lx diff --git a/apps/mobile/prototypes/staff_mobile_application/web/index.html b/apps/mobile/prototypes/staff_mobile_application/web/index.html deleted file mode 100644 index e8e0cbe6..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/web/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - staff_app_mvp - - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/web/manifest.json b/apps/mobile/prototypes/staff_mobile_application/web/manifest.json deleted file mode 100644 index 731a5af0..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/web/manifest.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "staff_app_mvp", - "short_name": "staff_app_mvp", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "icons/Icon-maskable-192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "icons/Icon-maskable-512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - } - ] -} diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/.gitignore b/apps/mobile/prototypes/staff_mobile_application/windows/.gitignore deleted file mode 100644 index d492d0d9..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -flutter/ephemeral/ - -# Visual Studio user-specific files. -*.suo -*.user -*.userosscache -*.sln.docstates - -# Visual Studio build-related files. -x64/ -x86/ - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/CMakeLists.txt b/apps/mobile/prototypes/staff_mobile_application/windows/CMakeLists.txt deleted file mode 100644 index 3f897296..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/CMakeLists.txt +++ /dev/null @@ -1,108 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.14) -project(staff_app_mvp LANGUAGES CXX) - -# The name of the executable created for the application. Change this to change -# the on-disk name of your application. -set(BINARY_NAME "staff_app_mvp") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(VERSION 3.14...3.25) - -# Define build configuration option. -get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(IS_MULTICONFIG) - set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" - CACHE STRING "" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") - endif() -endif() -# Define settings for the Profile build mode. -set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") -set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") -set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") -set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") - -# Use Unicode for all projects. -add_definitions(-DUNICODE -D_UNICODE) - -# Compilation settings that should be applied to most targets. -# -# Be cautious about adding new options here, as plugins use this function by -# default. In most cases, you should add new options to specific targets instead -# of modifying this function. -function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_17) - target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") - target_compile_options(${TARGET} PRIVATE /EHsc) - target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") - target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") -endfunction() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# Application build; see runner/CMakeLists.txt. -add_subdirectory("runner") - - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# Support files are copied into place next to the executable, so that it can -# run in place. This is done instead of making a separate bundle (as on Linux) -# so that building and running from within Visual Studio will work. -set(BUILD_BUNDLE_DIR "$") -# Make the "install" step default, as it's required to run. -set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() - -set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") -set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") - -install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() - -# Copy the native assets provided by the build.dart from all packages. -set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") -install(DIRECTORY "${NATIVE_ASSETS_DIR}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -# Fully re-copy the assets directory on each build to avoid having stale files -# from a previous install. -set(FLUTTER_ASSET_DIR_NAME "flutter_assets") -install(CODE " - file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") - " COMPONENT Runtime) -install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) - -# Install the AOT library on non-Debug builds only. -install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - CONFIGURATIONS Profile;Release - COMPONENT Runtime) diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/flutter/CMakeLists.txt b/apps/mobile/prototypes/staff_mobile_application/windows/flutter/CMakeLists.txt deleted file mode 100644 index 903f4899..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/flutter/CMakeLists.txt +++ /dev/null @@ -1,109 +0,0 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.14) - -set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") - -# Configuration provided via flutter tool. -include(${EPHEMERAL_DIR}/generated_config.cmake) - -# TODO: Move the rest of this into files in ephemeral. See -# https://github.com/flutter/flutter/issues/57146. -set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") - -# Set fallback configurations for older versions of the flutter tool. -if (NOT DEFINED FLUTTER_TARGET_PLATFORM) - set(FLUTTER_TARGET_PLATFORM "windows-x64") -endif() - -# === Flutter Library === -set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") - -# Published to parent scope for install step. -set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) -set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) -set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) -set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) - -list(APPEND FLUTTER_LIBRARY_HEADERS - "flutter_export.h" - "flutter_windows.h" - "flutter_messenger.h" - "flutter_plugin_registrar.h" - "flutter_texture_registrar.h" -) -list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") -add_library(flutter INTERFACE) -target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" -) -target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") -add_dependencies(flutter flutter_assemble) - -# === Wrapper === -list(APPEND CPP_WRAPPER_SOURCES_CORE - "core_implementations.cc" - "standard_codec.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") -list(APPEND CPP_WRAPPER_SOURCES_PLUGIN - "plugin_registrar.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") -list(APPEND CPP_WRAPPER_SOURCES_APP - "flutter_engine.cc" - "flutter_view_controller.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") - -# Wrapper sources needed for a plugin. -add_library(flutter_wrapper_plugin STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} -) -apply_standard_settings(flutter_wrapper_plugin) -set_target_properties(flutter_wrapper_plugin PROPERTIES - POSITION_INDEPENDENT_CODE ON) -set_target_properties(flutter_wrapper_plugin PROPERTIES - CXX_VISIBILITY_PRESET hidden) -target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) -target_include_directories(flutter_wrapper_plugin PUBLIC - "${WRAPPER_ROOT}/include" -) -add_dependencies(flutter_wrapper_plugin flutter_assemble) - -# Wrapper sources needed for the runner. -add_library(flutter_wrapper_app STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_APP} -) -apply_standard_settings(flutter_wrapper_app) -target_link_libraries(flutter_wrapper_app PUBLIC flutter) -target_include_directories(flutter_wrapper_app PUBLIC - "${WRAPPER_ROOT}/include" -) -add_dependencies(flutter_wrapper_app flutter_assemble) - -# === Flutter tool backend === -# _phony_ is a non-existent file to force this command to run every time, -# since currently there's no way to get a full input/output list from the -# flutter tool. -set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") -set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) -add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} - ${PHONY_OUTPUT} - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - ${FLUTTER_TARGET_PLATFORM} $ - VERBATIM -) -add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} -) diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/flutter/generated_plugin_registrant.cc b/apps/mobile/prototypes/staff_mobile_application/windows/flutter/generated_plugin_registrant.cc deleted file mode 100644 index 1a82e7d0..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,14 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include - -void RegisterPlugins(flutter::PluginRegistry* registry) { - FirebaseCorePluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); -} diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/flutter/generated_plugin_registrant.h b/apps/mobile/prototypes/staff_mobile_application/windows/flutter/generated_plugin_registrant.h deleted file mode 100644 index dc139d85..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void RegisterPlugins(flutter::PluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/flutter/generated_plugins.cmake b/apps/mobile/prototypes/staff_mobile_application/windows/flutter/generated_plugins.cmake deleted file mode 100644 index fa8a39ba..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/flutter/generated_plugins.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - firebase_core -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/runner/CMakeLists.txt b/apps/mobile/prototypes/staff_mobile_application/windows/runner/CMakeLists.txt deleted file mode 100644 index 394917c0..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/runner/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -cmake_minimum_required(VERSION 3.14) -project(runner LANGUAGES CXX) - -# Define the application target. To change its name, change BINARY_NAME in the -# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer -# work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} WIN32 - "flutter_window.cpp" - "main.cpp" - "utils.cpp" - "win32_window.cpp" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" - "Runner.rc" - "runner.exe.manifest" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add preprocessor definitions for the build version. -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") - -# Disable Windows macros that collide with C++ standard library functions. -target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") - -# Add dependency libraries and include directories. Add any application-specific -# dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) -target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") -target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/runner/Runner.rc b/apps/mobile/prototypes/staff_mobile_application/windows/runner/Runner.rc deleted file mode 100644 index 7b8a37d8..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/runner/Runner.rc +++ /dev/null @@ -1,121 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#pragma code_page(65001) -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_APP_ICON ICON "resources\\app_icon.ico" - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) -#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD -#else -#define VERSION_AS_NUMBER 1,0,0,0 -#endif - -#if defined(FLUTTER_VERSION) -#define VERSION_AS_STRING FLUTTER_VERSION -#else -#define VERSION_AS_STRING "1.0.0" -#endif - -VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_AS_NUMBER - PRODUCTVERSION VERSION_AS_NUMBER - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "com.example" "\0" - VALUE "FileDescription", "staff_app_mvp" "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "staff_app_mvp" "\0" - VALUE "LegalCopyright", "Copyright (C) 2025 com.example. All rights reserved." "\0" - VALUE "OriginalFilename", "staff_app_mvp.exe" "\0" - VALUE "ProductName", "staff_app_mvp" "\0" - VALUE "ProductVersion", VERSION_AS_STRING "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END -END - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/runner/flutter_window.cpp b/apps/mobile/prototypes/staff_mobile_application/windows/runner/flutter_window.cpp deleted file mode 100644 index 955ee303..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/runner/flutter_window.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "flutter_window.h" - -#include - -#include "flutter/generated_plugin_registrant.h" - -FlutterWindow::FlutterWindow(const flutter::DartProject& project) - : project_(project) {} - -FlutterWindow::~FlutterWindow() {} - -bool FlutterWindow::OnCreate() { - if (!Win32Window::OnCreate()) { - return false; - } - - RECT frame = GetClientArea(); - - // The size here must match the window dimensions to avoid unnecessary surface - // creation / destruction in the startup path. - flutter_controller_ = std::make_unique( - frame.right - frame.left, frame.bottom - frame.top, project_); - // Ensure that basic setup of the controller was successful. - if (!flutter_controller_->engine() || !flutter_controller_->view()) { - return false; - } - RegisterPlugins(flutter_controller_->engine()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); - - flutter_controller_->engine()->SetNextFrameCallback([&]() { - this->Show(); - }); - - // Flutter can complete the first frame before the "show window" callback is - // registered. The following call ensures a frame is pending to ensure the - // window is shown. It is a no-op if the first frame hasn't completed yet. - flutter_controller_->ForceRedraw(); - - return true; -} - -void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - flutter_controller_ = nullptr; - } - - Win32Window::OnDestroy(); -} - -LRESULT -FlutterWindow::MessageHandler(HWND hwnd, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opportunity to handle window messages. - if (flutter_controller_) { - std::optional result = - flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, - lparam); - if (result) { - return *result; - } - } - - switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; - } - - return Win32Window::MessageHandler(hwnd, message, wparam, lparam); -} diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/runner/flutter_window.h b/apps/mobile/prototypes/staff_mobile_application/windows/runner/flutter_window.h deleted file mode 100644 index 6da0652f..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/runner/flutter_window.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef RUNNER_FLUTTER_WINDOW_H_ -#define RUNNER_FLUTTER_WINDOW_H_ - -#include -#include - -#include - -#include "win32_window.h" - -// A window that does nothing but host a Flutter view. -class FlutterWindow : public Win32Window { - public: - // Creates a new FlutterWindow hosting a Flutter view running |project|. - explicit FlutterWindow(const flutter::DartProject& project); - virtual ~FlutterWindow(); - - protected: - // Win32Window: - bool OnCreate() override; - void OnDestroy() override; - LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept override; - - private: - // The project to run. - flutter::DartProject project_; - - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; -}; - -#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/runner/main.cpp b/apps/mobile/prototypes/staff_mobile_application/windows/runner/main.cpp deleted file mode 100644 index e19fc556..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/runner/main.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -#include "flutter_window.h" -#include "utils.h" - -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } - - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - - flutter::DartProject project(L"data"); - - std::vector command_line_arguments = - GetCommandLineArguments(); - - project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); - - FlutterWindow window(project); - Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); - if (!window.Create(L"staff_app_mvp", origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); - - ::MSG msg; - while (::GetMessage(&msg, nullptr, 0, 0)) { - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - } - - ::CoUninitialize(); - return EXIT_SUCCESS; -} diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/runner/resource.h b/apps/mobile/prototypes/staff_mobile_application/windows/runner/resource.h deleted file mode 100644 index 66a65d1e..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/runner/resource.h +++ /dev/null @@ -1,16 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Runner.rc -// -#define IDI_APP_ICON 101 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/runner/resources/app_icon.ico b/apps/mobile/prototypes/staff_mobile_application/windows/runner/resources/app_icon.ico deleted file mode 100644 index c04e20caf6370ebb9253ad831cc31de4a9c965f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33772 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 diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/runner/runner.exe.manifest b/apps/mobile/prototypes/staff_mobile_application/windows/runner/runner.exe.manifest deleted file mode 100644 index 153653e8..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/runner/runner.exe.manifest +++ /dev/null @@ -1,14 +0,0 @@ - - - - - PerMonitorV2 - - - - - - - - - diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/runner/utils.cpp b/apps/mobile/prototypes/staff_mobile_application/windows/runner/utils.cpp deleted file mode 100644 index 3a0b4651..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/runner/utils.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "utils.h" - -#include -#include -#include -#include - -#include - -void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); - } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } -} - -std::vector GetCommandLineArguments() { - // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. - int argc; - wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - if (argv == nullptr) { - return std::vector(); - } - - std::vector command_line_arguments; - - // Skip the first argument as it's the binary name. - for (int i = 1; i < argc; i++) { - command_line_arguments.push_back(Utf8FromUtf16(argv[i])); - } - - ::LocalFree(argv); - - return command_line_arguments; -} - -std::string Utf8FromUtf16(const wchar_t* utf16_string) { - if (utf16_string == nullptr) { - return std::string(); - } - unsigned int target_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr) - -1; // remove the trailing null character - int input_length = (int)wcslen(utf16_string); - std::string utf8_string; - if (target_length == 0 || target_length > utf8_string.max_size()) { - return utf8_string; - } - utf8_string.resize(target_length); - int converted_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - input_length, utf8_string.data(), target_length, nullptr, nullptr); - if (converted_length == 0) { - return std::string(); - } - return utf8_string; -} diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/runner/utils.h b/apps/mobile/prototypes/staff_mobile_application/windows/runner/utils.h deleted file mode 100644 index 3879d547..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/runner/utils.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef RUNNER_UTILS_H_ -#define RUNNER_UTILS_H_ - -#include -#include - -// Creates a console for the process, and redirects stdout and stderr to -// it for both the runner and the Flutter library. -void CreateAndAttachConsole(); - -// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string -// encoded in UTF-8. Returns an empty std::string on failure. -std::string Utf8FromUtf16(const wchar_t* utf16_string); - -// Gets the command line arguments passed in as a std::vector, -// encoded in UTF-8. Returns an empty std::vector on failure. -std::vector GetCommandLineArguments(); - -#endif // RUNNER_UTILS_H_ diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/runner/win32_window.cpp b/apps/mobile/prototypes/staff_mobile_application/windows/runner/win32_window.cpp deleted file mode 100644 index 60608d0f..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/runner/win32_window.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include "win32_window.h" - -#include -#include - -#include "resource.h" - -namespace { - -/// Window attribute that enables dark mode window decorations. -/// -/// Redefined in case the developer's machine has a Windows SDK older than -/// version 10.0.22000.0. -/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute -#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE -#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 -#endif - -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; - -/// Registry key for app theme preference. -/// -/// A value of 0 indicates apps should use dark mode. A non-zero or missing -/// value indicates apps should use light mode. -constexpr const wchar_t kGetPreferredBrightnessRegKey[] = - L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; -constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; - -// The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; - -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); - -// Scale helper to convert logical scaler values to physical using passed in -// scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} - -// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. -// This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { - return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - } - FreeLibrary(user32_module); -} - -} // namespace - -// Manages the Win32Window's window class registration. -class WindowClassRegistrar { - public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registrar instance. - static WindowClassRegistrar* GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); - } - return instance_; - } - - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t* GetWindowClass(); - - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); - - private: - WindowClassRegistrar() = default; - - static WindowClassRegistrar* instance_; - - bool class_registered_ = false; -}; - -WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; - -const wchar_t* WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; -} - -void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; -} - -Win32Window::Win32Window() { - ++g_active_window_count; -} - -Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); -} - -bool Win32Window::Create(const std::wstring& title, - const Point& origin, - const Size& size) { - Destroy(); - - const wchar_t* window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); - - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; - - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); - - if (!window) { - return false; - } - - UpdateTheme(window); - - return OnCreate(); -} - -bool Win32Window::Show() { - return ShowWindow(window_handle_, SW_SHOWNORMAL); -} - -// static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window* that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } - - return DefWindowProc(window, message, wparam, lparam); -} - -LRESULT -Win32Window::MessageHandler(HWND hwnd, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: { - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; - } - - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - - case WM_DWMCOLORIZATIONCOLORCHANGED: - UpdateTheme(hwnd); - return 0; - } - - return DefWindowProc(window_handle_, message, wparam, lparam); -} - -void Win32Window::Destroy() { - OnDestroy(); - - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } -} - -Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); -} - -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame = GetClientArea(); - - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); - - SetFocus(child_content_); -} - -RECT Win32Window::GetClientArea() { - RECT frame; - GetClientRect(window_handle_, &frame); - return frame; -} - -HWND Win32Window::GetHandle() { - return window_handle_; -} - -void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; -} - -bool Win32Window::OnCreate() { - // No-op; provided for subclasses. - return true; -} - -void Win32Window::OnDestroy() { - // No-op; provided for subclasses. -} - -void Win32Window::UpdateTheme(HWND const window) { - DWORD light_mode; - DWORD light_mode_size = sizeof(light_mode); - LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, - RRF_RT_REG_DWORD, nullptr, &light_mode, - &light_mode_size); - - if (result == ERROR_SUCCESS) { - BOOL enable_dark_mode = light_mode == 0; - DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, - &enable_dark_mode, sizeof(enable_dark_mode)); - } -} diff --git a/apps/mobile/prototypes/staff_mobile_application/windows/runner/win32_window.h b/apps/mobile/prototypes/staff_mobile_application/windows/runner/win32_window.h deleted file mode 100644 index e901dde6..00000000 --- a/apps/mobile/prototypes/staff_mobile_application/windows/runner/win32_window.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef RUNNER_WIN32_WINDOW_H_ -#define RUNNER_WIN32_WINDOW_H_ - -#include - -#include -#include -#include - -// A class abstraction for a high DPI-aware Win32 Window. Intended to be -// inherited from by classes that wish to specialize with custom -// rendering and input handling -class Win32Window { - public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates a win32 window with |title| that is positioned and sized using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size this function will scale the inputted width and height as - // as appropriate for the default monitor. The window is invisible until - // |Show| is called. Returns true if the window was created successfully. - bool Create(const std::wstring& title, const Point& origin, const Size& size); - - // Show the current window. Returns true if the window was successfully shown. - bool Show(); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - // Return a RECT representing the bounds of the current client area. - RECT GetClientArea(); - - protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Called when CreateAndShow is called, allowing subclass window-related - // setup. Subclasses should return false if setup fails. - virtual bool OnCreate(); - - // Called when Destroy is called. - virtual void OnDestroy(); - - private: - friend class WindowClassRegistrar; - - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Retrieves a class instance pointer for |window| - static Win32Window* GetThisFromHandle(HWND const window) noexcept; - - // Update the window frame's theme to match the system theme. - static void UpdateTheme(HWND const window); - - bool quit_on_close_ = false; - - // window handle for top level window. - HWND window_handle_ = nullptr; - - // window handle for hosted content. - HWND child_content_ = nullptr; -}; - -#endif // RUNNER_WIN32_WINDOW_H_

*@ug6 zwWx~gr$dCS!!$Pa+Rv-EUl7XuT5QPi*0oRNR85z>-_mGQ85i4b3hbbdgXCRn6zRVDJ)H|irue{AKS z3;q2cZO0mE1NolIAliWxC0b!@=TmyH<62>ZZjy~q$&-qsnm{EJg!%)X1F6ze9jYE| zdotlnXzJi~BX$Y%*bgaA1uxggsmk4U-iZ#r1w0&PM_lNvYgrdM_Gz3jLaSIBRCnPL z%~+LP=iNj*JusbvMI>un-W6qlw8>py4Qa(hZ`TX`+mVE>0b)oYh;%#}neU2JtWYFl zQ!t5aIBm6=KHt)!f8KpF-1Au3F%7 z@N@o5*^jEeR?e;kvgYE#GBkCac>cqkW!gRT7t$tA43r`5lt_*)M?Q^MB6C;0?tVrR z$|W=k!F-lHCAP|a5uz+9eQV*FVXB+T;pTIW`A!$|OL60j?p3<1hP-37hiVW*e;A2y zC6ows7K3KcpA0+f(BDgrCv|1(U1MH-;eW=>-i|CzmLjEA5&=-PV(nH+@eI9;iiI7i>jdx6ej2>VaVOR}o zD?z3?VX0GkeJVQ-m~A;QX!6q(NYM@mv;_xWs_`~nFZ}^`C-9;-b3c^}hdA=JhLNVH zj=kDmFtZ1bn{KlErkJvjcxn>pX4;{KrNEWI+wyEy>ePq%B>+dBYA5|M8u(7Lj8 z?6IKI8Fo}x_a7+jSx~RqGx9!n)ZluxNcEcm1!+{cf4+IDi0|?@z8tkKJZR*qwf_MQ zcx0^!QB;CN;8T%{Y!)M%;Bfj@Y_uKe>@%l+?j(Kt&hvL)8~%Te^Z)r3q+V01o2Z@F U%Z$Qrei}r&Km*NM4cn;y03V-sXaE2J diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json deleted file mode 100644 index 0bedcf2f..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725b..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Base.lproj/LaunchScreen.storyboard b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f2e259c7..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Base.lproj/Main.storyboard b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c28516..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Info.plist b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Info.plist deleted file mode 100644 index cf25321e..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Client App Mvp - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - client_app_mvp - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - - - diff --git a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Runner-Bridging-Header.h b/apps/mobile/prototypes/client_mobile_application/ios/Runner/Runner-Bridging-Header.h deleted file mode 100644 index 308a2a56..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/Runner/Runner-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import "GeneratedPluginRegistrant.h" diff --git a/apps/mobile/prototypes/client_mobile_application/ios/RunnerTests/RunnerTests.swift b/apps/mobile/prototypes/client_mobile_application/ios/RunnerTests/RunnerTests.swift deleted file mode 100644 index 86a7c3b1..00000000 --- a/apps/mobile/prototypes/client_mobile_application/ios/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Flutter -import UIKit -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/.guides/config.json b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/.guides/config.json deleted file mode 100644 index e37ed06f..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/.guides/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "description": "A set of guides for interacting with the generated firebase dataconnect sdk", - "mcpServers": { - "firebase": { - "command": "npx", - "args": ["-y", "firebase-tools@latest", "experimental:mcp"] - } - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/.guides/setup.md b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/.guides/setup.md deleted file mode 100644 index 4a3737fe..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/.guides/setup.md +++ /dev/null @@ -1,15 +0,0 @@ -# Setup - -This guide will walk you through setting up your environment to use the Firebase Data Connect SDK. Mostly using -documentation listed [here](https://firebase.google.com/docs/flutter/setup?platform=ios#install-cli-tools). - -1. Make sure you have the latest Firebase CLI tools installed. Follow the instructions [here](https://firebase.google.com/docs/cli#setup_update_cli) to install. -2. Log into your Firebase account: -```sh -firebase login -``` -3. Install the FlutterFire CLI by running the following command from any directory: -```sh -dart pub global activate flutterfire_cli -``` -4. Make sure the user has initialized Firebase already based on the instructions [here](https://firebase.google.com/docs/flutter/setup?platform=ios#initialize-firebase). diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/.guides/usage.md b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/.guides/usage.md deleted file mode 100644 index 28407bc2..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/.guides/usage.md +++ /dev/null @@ -1,31 +0,0 @@ -# Basic Usage - -```dart -ExampleConnector.instance.CreateMovie(createMovieVariables).execute(); -ExampleConnector.instance.UpsertUser(upsertUserVariables).execute(); -ExampleConnector.instance.AddReview(addReviewVariables).execute(); -ExampleConnector.instance.DeleteReview(deleteReviewVariables).execute(); -ExampleConnector.instance.ListMovies().execute(); -ExampleConnector.instance.ListUsers().execute(); -ExampleConnector.instance.ListUserReviews().execute(); -ExampleConnector.instance.GetMovieById(getMovieByIdVariables).execute(); -ExampleConnector.instance.SearchMovie(searchMovieVariables).execute(); - -``` - -## Optional Fields - -Some operations may have optional fields. In these cases, the Flutter SDK exposes a builder method, and will have to be set separately. - -Optional fields can be discovered based on classes that have `Optional` object types. - -This is an example of a mutation with an optional field: - -```dart -await ExampleConnector.instance.SearchMovie({ ... }) -.titleInput(...) -.execute(); -``` - -Note: the above example is a mutation, but the same logic applies to query operations as well. Additionally, `createMovie` is an example, and may not be available to the user. - diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/README.md b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/README.md deleted file mode 100644 index 2104decc..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/README.md +++ /dev/null @@ -1,446 +0,0 @@ -# dataconnect_generated SDK - -## Installation -```sh -flutter pub get firebase_data_connect -flutterfire configure -``` -For more information, see [Flutter for Firebase installation documentation](https://firebase.google.com/docs/data-connect/flutter-sdk#use-core). - -## Data Connect instance -Each connector creates a static class, with an instance of the `DataConnect` class that can be used to connect to your Data Connect backend and call operations. - -### Connecting to the emulator - -```dart -String host = 'localhost'; // or your host name -int port = 9399; // or your port number -ExampleConnector.instance.dataConnect.useDataConnectEmulator(host, port); -``` - -You can also call queries and mutations by using the connector class. -## Queries - -### ListMovies -#### Required Arguments -```dart -// No required arguments -ExampleConnector.instance.listMovies().execute(); -``` - - - -#### Return Type -`execute()` returns a `QueryResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -/// Result of a query request. Created to hold extra variables in the future. -class QueryResult extends OperationResult { - QueryResult(super.dataConnect, super.data, super.ref); -} - -final result = await ExampleConnector.instance.listMovies(); -ListMoviesData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -final ref = ExampleConnector.instance.listMovies().ref(); -ref.execute(); - -ref.subscribe(...); -``` - - -### ListUsers -#### Required Arguments -```dart -// No required arguments -ExampleConnector.instance.listUsers().execute(); -``` - - - -#### Return Type -`execute()` returns a `QueryResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -/// Result of a query request. Created to hold extra variables in the future. -class QueryResult extends OperationResult { - QueryResult(super.dataConnect, super.data, super.ref); -} - -final result = await ExampleConnector.instance.listUsers(); -ListUsersData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -final ref = ExampleConnector.instance.listUsers().ref(); -ref.execute(); - -ref.subscribe(...); -``` - - -### ListUserReviews -#### Required Arguments -```dart -// No required arguments -ExampleConnector.instance.listUserReviews().execute(); -``` - - - -#### Return Type -`execute()` returns a `QueryResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -/// Result of a query request. Created to hold extra variables in the future. -class QueryResult extends OperationResult { - QueryResult(super.dataConnect, super.data, super.ref); -} - -final result = await ExampleConnector.instance.listUserReviews(); -ListUserReviewsData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -final ref = ExampleConnector.instance.listUserReviews().ref(); -ref.execute(); - -ref.subscribe(...); -``` - - -### GetMovieById -#### Required Arguments -```dart -String id = ...; -ExampleConnector.instance.getMovieById( - id: id, -).execute(); -``` - - - -#### Return Type -`execute()` returns a `QueryResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -/// Result of a query request. Created to hold extra variables in the future. -class QueryResult extends OperationResult { - QueryResult(super.dataConnect, super.data, super.ref); -} - -final result = await ExampleConnector.instance.getMovieById( - id: id, -); -GetMovieByIdData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -String id = ...; - -final ref = ExampleConnector.instance.getMovieById( - id: id, -).ref(); -ref.execute(); - -ref.subscribe(...); -``` - - -### SearchMovie -#### Required Arguments -```dart -// No required arguments -ExampleConnector.instance.searchMovie().execute(); -``` - -#### Optional Arguments -We return a builder for each query. For SearchMovie, we created `SearchMovieBuilder`. For queries and mutations with optional parameters, we return a builder class. -The builder pattern allows Data Connect to distinguish between fields that haven't been set and fields that have been set to null. A field can be set by calling its respective setter method like below: -```dart -class SearchMovieVariablesBuilder { - ... - - SearchMovieVariablesBuilder titleInput(String? t) { - _titleInput.value = t; - return this; - } - SearchMovieVariablesBuilder genre(String? t) { - _genre.value = t; - return this; - } - - ... -} -ExampleConnector.instance.searchMovie() -.titleInput(titleInput) -.genre(genre) -.execute(); -``` - -#### Return Type -`execute()` returns a `QueryResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -/// Result of a query request. Created to hold extra variables in the future. -class QueryResult extends OperationResult { - QueryResult(super.dataConnect, super.data, super.ref); -} - -final result = await ExampleConnector.instance.searchMovie(); -SearchMovieData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -final ref = ExampleConnector.instance.searchMovie().ref(); -ref.execute(); - -ref.subscribe(...); -``` - -## Mutations - -### CreateMovie -#### Required Arguments -```dart -String title = ...; -String genre = ...; -String imageUrl = ...; -ExampleConnector.instance.createMovie( - title: title, - genre: genre, - imageUrl: imageUrl, -).execute(); -``` - - - -#### Return Type -`execute()` returns a `OperationResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -final result = await ExampleConnector.instance.createMovie( - title: title, - genre: genre, - imageUrl: imageUrl, -); -CreateMovieData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -String title = ...; -String genre = ...; -String imageUrl = ...; - -final ref = ExampleConnector.instance.createMovie( - title: title, - genre: genre, - imageUrl: imageUrl, -).ref(); -ref.execute(); -``` - - -### UpsertUser -#### Required Arguments -```dart -String username = ...; -ExampleConnector.instance.upsertUser( - username: username, -).execute(); -``` - - - -#### Return Type -`execute()` returns a `OperationResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -final result = await ExampleConnector.instance.upsertUser( - username: username, -); -UpsertUserData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -String username = ...; - -final ref = ExampleConnector.instance.upsertUser( - username: username, -).ref(); -ref.execute(); -``` - - -### AddReview -#### Required Arguments -```dart -String movieId = ...; -int rating = ...; -String reviewText = ...; -ExampleConnector.instance.addReview( - movieId: movieId, - rating: rating, - reviewText: reviewText, -).execute(); -``` - - - -#### Return Type -`execute()` returns a `OperationResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -final result = await ExampleConnector.instance.addReview( - movieId: movieId, - rating: rating, - reviewText: reviewText, -); -AddReviewData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -String movieId = ...; -int rating = ...; -String reviewText = ...; - -final ref = ExampleConnector.instance.addReview( - movieId: movieId, - rating: rating, - reviewText: reviewText, -).ref(); -ref.execute(); -``` - - -### DeleteReview -#### Required Arguments -```dart -String movieId = ...; -ExampleConnector.instance.deleteReview( - movieId: movieId, -).execute(); -``` - - - -#### Return Type -`execute()` returns a `OperationResult` -```dart -/// Result of an Operation Request (query/mutation). -class OperationResult { - OperationResult(this.dataConnect, this.data, this.ref); - Data data; - OperationRef ref; - FirebaseDataConnect dataConnect; -} - -final result = await ExampleConnector.instance.deleteReview( - movieId: movieId, -); -DeleteReviewData data = result.data; -final ref = result.ref; -``` - -#### Getting the Ref -Each builder returns an `execute` function, which is a helper function that creates a `Ref` object, and executes the underlying operation. -An example of how to use the `Ref` object is shown below: -```dart -String movieId = ...; - -final ref = ExampleConnector.instance.deleteReview( - movieId: movieId, -).ref(); -ref.execute(); -``` - diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/add_review.dart b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/add_review.dart deleted file mode 100644 index fc78c415..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/add_review.dart +++ /dev/null @@ -1,139 +0,0 @@ -part of 'generated.dart'; - -class AddReviewVariablesBuilder { - String movieId; - int rating; - String reviewText; - - final FirebaseDataConnect _dataConnect; - AddReviewVariablesBuilder(this._dataConnect, {required this.movieId,required this.rating,required this.reviewText,}); - Deserializer dataDeserializer = (dynamic json) => AddReviewData.fromJson(jsonDecode(json)); - Serializer varsSerializer = (AddReviewVariables vars) => jsonEncode(vars.toJson()); - Future> execute() { - return ref().execute(); - } - - MutationRef ref() { - AddReviewVariables vars= AddReviewVariables(movieId: movieId,rating: rating,reviewText: reviewText,); - return _dataConnect.mutation("AddReview", dataDeserializer, varsSerializer, vars); - } -} - -@immutable -class AddReviewReviewUpsert { - final String userId; - final String movieId; - AddReviewReviewUpsert.fromJson(dynamic json): - - userId = nativeFromJson(json['userId']), - movieId = nativeFromJson(json['movieId']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final AddReviewReviewUpsert otherTyped = other as AddReviewReviewUpsert; - return userId == otherTyped.userId && - movieId == otherTyped.movieId; - - } - @override - int get hashCode => Object.hashAll([userId.hashCode, movieId.hashCode]); - - - Map toJson() { - Map json = {}; - json['userId'] = nativeToJson(userId); - json['movieId'] = nativeToJson(movieId); - return json; - } - - AddReviewReviewUpsert({ - required this.userId, - required this.movieId, - }); -} - -@immutable -class AddReviewData { - final AddReviewReviewUpsert review_upsert; - AddReviewData.fromJson(dynamic json): - - review_upsert = AddReviewReviewUpsert.fromJson(json['review_upsert']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final AddReviewData otherTyped = other as AddReviewData; - return review_upsert == otherTyped.review_upsert; - - } - @override - int get hashCode => review_upsert.hashCode; - - - Map toJson() { - Map json = {}; - json['review_upsert'] = review_upsert.toJson(); - return json; - } - - AddReviewData({ - required this.review_upsert, - }); -} - -@immutable -class AddReviewVariables { - final String movieId; - final int rating; - final String reviewText; - @Deprecated('fromJson is deprecated for Variable classes as they are no longer required for deserialization.') - AddReviewVariables.fromJson(Map json): - - movieId = nativeFromJson(json['movieId']), - rating = nativeFromJson(json['rating']), - reviewText = nativeFromJson(json['reviewText']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final AddReviewVariables otherTyped = other as AddReviewVariables; - return movieId == otherTyped.movieId && - rating == otherTyped.rating && - reviewText == otherTyped.reviewText; - - } - @override - int get hashCode => Object.hashAll([movieId.hashCode, rating.hashCode, reviewText.hashCode]); - - - Map toJson() { - Map json = {}; - json['movieId'] = nativeToJson(movieId); - json['rating'] = nativeToJson(rating); - json['reviewText'] = nativeToJson(reviewText); - return json; - } - - AddReviewVariables({ - required this.movieId, - required this.rating, - required this.reviewText, - }); -} - diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/create_movie.dart b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/create_movie.dart deleted file mode 100644 index abdd637c..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/create_movie.dart +++ /dev/null @@ -1,134 +0,0 @@ -part of 'generated.dart'; - -class CreateMovieVariablesBuilder { - String title; - String genre; - String imageUrl; - - final FirebaseDataConnect _dataConnect; - CreateMovieVariablesBuilder(this._dataConnect, {required this.title,required this.genre,required this.imageUrl,}); - Deserializer dataDeserializer = (dynamic json) => CreateMovieData.fromJson(jsonDecode(json)); - Serializer varsSerializer = (CreateMovieVariables vars) => jsonEncode(vars.toJson()); - Future> execute() { - return ref().execute(); - } - - MutationRef ref() { - CreateMovieVariables vars= CreateMovieVariables(title: title,genre: genre,imageUrl: imageUrl,); - return _dataConnect.mutation("CreateMovie", dataDeserializer, varsSerializer, vars); - } -} - -@immutable -class CreateMovieMovieInsert { - final String id; - CreateMovieMovieInsert.fromJson(dynamic json): - - id = nativeFromJson(json['id']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final CreateMovieMovieInsert otherTyped = other as CreateMovieMovieInsert; - return id == otherTyped.id; - - } - @override - int get hashCode => id.hashCode; - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - return json; - } - - CreateMovieMovieInsert({ - required this.id, - }); -} - -@immutable -class CreateMovieData { - final CreateMovieMovieInsert movie_insert; - CreateMovieData.fromJson(dynamic json): - - movie_insert = CreateMovieMovieInsert.fromJson(json['movie_insert']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final CreateMovieData otherTyped = other as CreateMovieData; - return movie_insert == otherTyped.movie_insert; - - } - @override - int get hashCode => movie_insert.hashCode; - - - Map toJson() { - Map json = {}; - json['movie_insert'] = movie_insert.toJson(); - return json; - } - - CreateMovieData({ - required this.movie_insert, - }); -} - -@immutable -class CreateMovieVariables { - final String title; - final String genre; - final String imageUrl; - @Deprecated('fromJson is deprecated for Variable classes as they are no longer required for deserialization.') - CreateMovieVariables.fromJson(Map json): - - title = nativeFromJson(json['title']), - genre = nativeFromJson(json['genre']), - imageUrl = nativeFromJson(json['imageUrl']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final CreateMovieVariables otherTyped = other as CreateMovieVariables; - return title == otherTyped.title && - genre == otherTyped.genre && - imageUrl == otherTyped.imageUrl; - - } - @override - int get hashCode => Object.hashAll([title.hashCode, genre.hashCode, imageUrl.hashCode]); - - - Map toJson() { - Map json = {}; - json['title'] = nativeToJson(title); - json['genre'] = nativeToJson(genre); - json['imageUrl'] = nativeToJson(imageUrl); - return json; - } - - CreateMovieVariables({ - required this.title, - required this.genre, - required this.imageUrl, - }); -} - diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/delete_review.dart b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/delete_review.dart deleted file mode 100644 index e62dd741..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/delete_review.dart +++ /dev/null @@ -1,129 +0,0 @@ -part of 'generated.dart'; - -class DeleteReviewVariablesBuilder { - String movieId; - - final FirebaseDataConnect _dataConnect; - DeleteReviewVariablesBuilder(this._dataConnect, {required this.movieId,}); - Deserializer dataDeserializer = (dynamic json) => DeleteReviewData.fromJson(jsonDecode(json)); - Serializer varsSerializer = (DeleteReviewVariables vars) => jsonEncode(vars.toJson()); - Future> execute() { - return ref().execute(); - } - - MutationRef ref() { - DeleteReviewVariables vars= DeleteReviewVariables(movieId: movieId,); - return _dataConnect.mutation("DeleteReview", dataDeserializer, varsSerializer, vars); - } -} - -@immutable -class DeleteReviewReviewDelete { - final String userId; - final String movieId; - DeleteReviewReviewDelete.fromJson(dynamic json): - - userId = nativeFromJson(json['userId']), - movieId = nativeFromJson(json['movieId']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final DeleteReviewReviewDelete otherTyped = other as DeleteReviewReviewDelete; - return userId == otherTyped.userId && - movieId == otherTyped.movieId; - - } - @override - int get hashCode => Object.hashAll([userId.hashCode, movieId.hashCode]); - - - Map toJson() { - Map json = {}; - json['userId'] = nativeToJson(userId); - json['movieId'] = nativeToJson(movieId); - return json; - } - - DeleteReviewReviewDelete({ - required this.userId, - required this.movieId, - }); -} - -@immutable -class DeleteReviewData { - final DeleteReviewReviewDelete? review_delete; - DeleteReviewData.fromJson(dynamic json): - - review_delete = json['review_delete'] == null ? null : DeleteReviewReviewDelete.fromJson(json['review_delete']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final DeleteReviewData otherTyped = other as DeleteReviewData; - return review_delete == otherTyped.review_delete; - - } - @override - int get hashCode => review_delete.hashCode; - - - Map toJson() { - Map json = {}; - if (review_delete != null) { - json['review_delete'] = review_delete!.toJson(); - } - return json; - } - - DeleteReviewData({ - this.review_delete, - }); -} - -@immutable -class DeleteReviewVariables { - final String movieId; - @Deprecated('fromJson is deprecated for Variable classes as they are no longer required for deserialization.') - DeleteReviewVariables.fromJson(Map json): - - movieId = nativeFromJson(json['movieId']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final DeleteReviewVariables otherTyped = other as DeleteReviewVariables; - return movieId == otherTyped.movieId; - - } - @override - int get hashCode => movieId.hashCode; - - - Map toJson() { - Map json = {}; - json['movieId'] = nativeToJson(movieId); - return json; - } - - DeleteReviewVariables({ - required this.movieId, - }); -} - diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/generated.dart b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/generated.dart deleted file mode 100644 index 580adbb3..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/generated.dart +++ /dev/null @@ -1,93 +0,0 @@ -library dataconnect_generated; -import 'package:firebase_data_connect/firebase_data_connect.dart'; -import 'package:flutter/foundation.dart'; -import 'dart:convert'; - -part 'create_movie.dart'; - -part 'upsert_user.dart'; - -part 'add_review.dart'; - -part 'delete_review.dart'; - -part 'list_movies.dart'; - -part 'list_users.dart'; - -part 'list_user_reviews.dart'; - -part 'get_movie_by_id.dart'; - -part 'search_movie.dart'; - - - - - - - -class ExampleConnector { - - - CreateMovieVariablesBuilder createMovie ({required String title, required String genre, required String imageUrl, }) { - return CreateMovieVariablesBuilder(dataConnect, title: title,genre: genre,imageUrl: imageUrl,); - } - - - UpsertUserVariablesBuilder upsertUser ({required String username, }) { - return UpsertUserVariablesBuilder(dataConnect, username: username,); - } - - - AddReviewVariablesBuilder addReview ({required String movieId, required int rating, required String reviewText, }) { - return AddReviewVariablesBuilder(dataConnect, movieId: movieId,rating: rating,reviewText: reviewText,); - } - - - DeleteReviewVariablesBuilder deleteReview ({required String movieId, }) { - return DeleteReviewVariablesBuilder(dataConnect, movieId: movieId,); - } - - - ListMoviesVariablesBuilder listMovies () { - return ListMoviesVariablesBuilder(dataConnect, ); - } - - - ListUsersVariablesBuilder listUsers () { - return ListUsersVariablesBuilder(dataConnect, ); - } - - - ListUserReviewsVariablesBuilder listUserReviews () { - return ListUserReviewsVariablesBuilder(dataConnect, ); - } - - - GetMovieByIdVariablesBuilder getMovieById ({required String id, }) { - return GetMovieByIdVariablesBuilder(dataConnect, id: id,); - } - - - SearchMovieVariablesBuilder searchMovie () { - return SearchMovieVariablesBuilder(dataConnect, ); - } - - - static ConnectorConfig connectorConfig = ConnectorConfig( - 'us-central1', - 'example', - 'client-krow-poc', - ); - - ExampleConnector({required this.dataConnect}); - static ExampleConnector get instance { - return ExampleConnector( - dataConnect: FirebaseDataConnect.instanceFor( - connectorConfig: connectorConfig, - sdkType: CallerSDKType.generated)); - } - - FirebaseDataConnect dataConnect; -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/get_movie_by_id.dart b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/get_movie_by_id.dart deleted file mode 100644 index 154704ac..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/get_movie_by_id.dart +++ /dev/null @@ -1,297 +0,0 @@ -part of 'generated.dart'; - -class GetMovieByIdVariablesBuilder { - String id; - - final FirebaseDataConnect _dataConnect; - GetMovieByIdVariablesBuilder(this._dataConnect, {required this.id,}); - Deserializer dataDeserializer = (dynamic json) => GetMovieByIdData.fromJson(jsonDecode(json)); - Serializer varsSerializer = (GetMovieByIdVariables vars) => jsonEncode(vars.toJson()); - Future> execute() { - return ref().execute(); - } - - QueryRef ref() { - GetMovieByIdVariables vars= GetMovieByIdVariables(id: id,); - return _dataConnect.query("GetMovieById", dataDeserializer, varsSerializer, vars); - } -} - -@immutable -class GetMovieByIdMovie { - final String id; - final String title; - final String imageUrl; - final String? genre; - final GetMovieByIdMovieMetadata? metadata; - final List reviews; - GetMovieByIdMovie.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - title = nativeFromJson(json['title']), - imageUrl = nativeFromJson(json['imageUrl']), - genre = json['genre'] == null ? null : nativeFromJson(json['genre']), - metadata = json['metadata'] == null ? null : GetMovieByIdMovieMetadata.fromJson(json['metadata']), - reviews = (json['reviews'] as List) - .map((e) => GetMovieByIdMovieReviews.fromJson(e)) - .toList(); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final GetMovieByIdMovie otherTyped = other as GetMovieByIdMovie; - return id == otherTyped.id && - title == otherTyped.title && - imageUrl == otherTyped.imageUrl && - genre == otherTyped.genre && - metadata == otherTyped.metadata && - reviews == otherTyped.reviews; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, title.hashCode, imageUrl.hashCode, genre.hashCode, metadata.hashCode, reviews.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['title'] = nativeToJson(title); - json['imageUrl'] = nativeToJson(imageUrl); - if (genre != null) { - json['genre'] = nativeToJson(genre); - } - if (metadata != null) { - json['metadata'] = metadata!.toJson(); - } - json['reviews'] = reviews.map((e) => e.toJson()).toList(); - return json; - } - - GetMovieByIdMovie({ - required this.id, - required this.title, - required this.imageUrl, - this.genre, - this.metadata, - required this.reviews, - }); -} - -@immutable -class GetMovieByIdMovieMetadata { - final double? rating; - final int? releaseYear; - final String? description; - GetMovieByIdMovieMetadata.fromJson(dynamic json): - - rating = json['rating'] == null ? null : nativeFromJson(json['rating']), - releaseYear = json['releaseYear'] == null ? null : nativeFromJson(json['releaseYear']), - description = json['description'] == null ? null : nativeFromJson(json['description']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final GetMovieByIdMovieMetadata otherTyped = other as GetMovieByIdMovieMetadata; - return rating == otherTyped.rating && - releaseYear == otherTyped.releaseYear && - description == otherTyped.description; - - } - @override - int get hashCode => Object.hashAll([rating.hashCode, releaseYear.hashCode, description.hashCode]); - - - Map toJson() { - Map json = {}; - if (rating != null) { - json['rating'] = nativeToJson(rating); - } - if (releaseYear != null) { - json['releaseYear'] = nativeToJson(releaseYear); - } - if (description != null) { - json['description'] = nativeToJson(description); - } - return json; - } - - GetMovieByIdMovieMetadata({ - this.rating, - this.releaseYear, - this.description, - }); -} - -@immutable -class GetMovieByIdMovieReviews { - final String? reviewText; - final DateTime reviewDate; - final int? rating; - final GetMovieByIdMovieReviewsUser user; - GetMovieByIdMovieReviews.fromJson(dynamic json): - - reviewText = json['reviewText'] == null ? null : nativeFromJson(json['reviewText']), - reviewDate = nativeFromJson(json['reviewDate']), - rating = json['rating'] == null ? null : nativeFromJson(json['rating']), - user = GetMovieByIdMovieReviewsUser.fromJson(json['user']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final GetMovieByIdMovieReviews otherTyped = other as GetMovieByIdMovieReviews; - return reviewText == otherTyped.reviewText && - reviewDate == otherTyped.reviewDate && - rating == otherTyped.rating && - user == otherTyped.user; - - } - @override - int get hashCode => Object.hashAll([reviewText.hashCode, reviewDate.hashCode, rating.hashCode, user.hashCode]); - - - Map toJson() { - Map json = {}; - if (reviewText != null) { - json['reviewText'] = nativeToJson(reviewText); - } - json['reviewDate'] = nativeToJson(reviewDate); - if (rating != null) { - json['rating'] = nativeToJson(rating); - } - json['user'] = user.toJson(); - return json; - } - - GetMovieByIdMovieReviews({ - this.reviewText, - required this.reviewDate, - this.rating, - required this.user, - }); -} - -@immutable -class GetMovieByIdMovieReviewsUser { - final String id; - final String username; - GetMovieByIdMovieReviewsUser.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - username = nativeFromJson(json['username']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final GetMovieByIdMovieReviewsUser otherTyped = other as GetMovieByIdMovieReviewsUser; - return id == otherTyped.id && - username == otherTyped.username; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, username.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['username'] = nativeToJson(username); - return json; - } - - GetMovieByIdMovieReviewsUser({ - required this.id, - required this.username, - }); -} - -@immutable -class GetMovieByIdData { - final GetMovieByIdMovie? movie; - GetMovieByIdData.fromJson(dynamic json): - - movie = json['movie'] == null ? null : GetMovieByIdMovie.fromJson(json['movie']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final GetMovieByIdData otherTyped = other as GetMovieByIdData; - return movie == otherTyped.movie; - - } - @override - int get hashCode => movie.hashCode; - - - Map toJson() { - Map json = {}; - if (movie != null) { - json['movie'] = movie!.toJson(); - } - return json; - } - - GetMovieByIdData({ - this.movie, - }); -} - -@immutable -class GetMovieByIdVariables { - final String id; - @Deprecated('fromJson is deprecated for Variable classes as they are no longer required for deserialization.') - GetMovieByIdVariables.fromJson(Map json): - - id = nativeFromJson(json['id']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final GetMovieByIdVariables otherTyped = other as GetMovieByIdVariables; - return id == otherTyped.id; - - } - @override - int get hashCode => id.hashCode; - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - return json; - } - - GetMovieByIdVariables({ - required this.id, - }); -} - diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/list_movies.dart b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/list_movies.dart deleted file mode 100644 index 4a67d768..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/list_movies.dart +++ /dev/null @@ -1,105 +0,0 @@ -part of 'generated.dart'; - -class ListMoviesVariablesBuilder { - - final FirebaseDataConnect _dataConnect; - ListMoviesVariablesBuilder(this._dataConnect, ); - Deserializer dataDeserializer = (dynamic json) => ListMoviesData.fromJson(jsonDecode(json)); - - Future> execute() { - return ref().execute(); - } - - QueryRef ref() { - - return _dataConnect.query("ListMovies", dataDeserializer, emptySerializer, null); - } -} - -@immutable -class ListMoviesMovies { - final String id; - final String title; - final String imageUrl; - final String? genre; - ListMoviesMovies.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - title = nativeFromJson(json['title']), - imageUrl = nativeFromJson(json['imageUrl']), - genre = json['genre'] == null ? null : nativeFromJson(json['genre']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListMoviesMovies otherTyped = other as ListMoviesMovies; - return id == otherTyped.id && - title == otherTyped.title && - imageUrl == otherTyped.imageUrl && - genre == otherTyped.genre; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, title.hashCode, imageUrl.hashCode, genre.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['title'] = nativeToJson(title); - json['imageUrl'] = nativeToJson(imageUrl); - if (genre != null) { - json['genre'] = nativeToJson(genre); - } - return json; - } - - ListMoviesMovies({ - required this.id, - required this.title, - required this.imageUrl, - this.genre, - }); -} - -@immutable -class ListMoviesData { - final List movies; - ListMoviesData.fromJson(dynamic json): - - movies = (json['movies'] as List) - .map((e) => ListMoviesMovies.fromJson(e)) - .toList(); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListMoviesData otherTyped = other as ListMoviesData; - return movies == otherTyped.movies; - - } - @override - int get hashCode => movies.hashCode; - - - Map toJson() { - Map json = {}; - json['movies'] = movies.map((e) => e.toJson()).toList(); - return json; - } - - ListMoviesData({ - required this.movies, - }); -} - diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/list_user_reviews.dart b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/list_user_reviews.dart deleted file mode 100644 index d6053f58..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/list_user_reviews.dart +++ /dev/null @@ -1,192 +0,0 @@ -part of 'generated.dart'; - -class ListUserReviewsVariablesBuilder { - - final FirebaseDataConnect _dataConnect; - ListUserReviewsVariablesBuilder(this._dataConnect, ); - Deserializer dataDeserializer = (dynamic json) => ListUserReviewsData.fromJson(jsonDecode(json)); - - Future> execute() { - return ref().execute(); - } - - QueryRef ref() { - - return _dataConnect.query("ListUserReviews", dataDeserializer, emptySerializer, null); - } -} - -@immutable -class ListUserReviewsUser { - final String id; - final String username; - final List reviews; - ListUserReviewsUser.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - username = nativeFromJson(json['username']), - reviews = (json['reviews'] as List) - .map((e) => ListUserReviewsUserReviews.fromJson(e)) - .toList(); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListUserReviewsUser otherTyped = other as ListUserReviewsUser; - return id == otherTyped.id && - username == otherTyped.username && - reviews == otherTyped.reviews; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, username.hashCode, reviews.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['username'] = nativeToJson(username); - json['reviews'] = reviews.map((e) => e.toJson()).toList(); - return json; - } - - ListUserReviewsUser({ - required this.id, - required this.username, - required this.reviews, - }); -} - -@immutable -class ListUserReviewsUserReviews { - final int? rating; - final DateTime reviewDate; - final String? reviewText; - final ListUserReviewsUserReviewsMovie movie; - ListUserReviewsUserReviews.fromJson(dynamic json): - - rating = json['rating'] == null ? null : nativeFromJson(json['rating']), - reviewDate = nativeFromJson(json['reviewDate']), - reviewText = json['reviewText'] == null ? null : nativeFromJson(json['reviewText']), - movie = ListUserReviewsUserReviewsMovie.fromJson(json['movie']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListUserReviewsUserReviews otherTyped = other as ListUserReviewsUserReviews; - return rating == otherTyped.rating && - reviewDate == otherTyped.reviewDate && - reviewText == otherTyped.reviewText && - movie == otherTyped.movie; - - } - @override - int get hashCode => Object.hashAll([rating.hashCode, reviewDate.hashCode, reviewText.hashCode, movie.hashCode]); - - - Map toJson() { - Map json = {}; - if (rating != null) { - json['rating'] = nativeToJson(rating); - } - json['reviewDate'] = nativeToJson(reviewDate); - if (reviewText != null) { - json['reviewText'] = nativeToJson(reviewText); - } - json['movie'] = movie.toJson(); - return json; - } - - ListUserReviewsUserReviews({ - this.rating, - required this.reviewDate, - this.reviewText, - required this.movie, - }); -} - -@immutable -class ListUserReviewsUserReviewsMovie { - final String id; - final String title; - ListUserReviewsUserReviewsMovie.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - title = nativeFromJson(json['title']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListUserReviewsUserReviewsMovie otherTyped = other as ListUserReviewsUserReviewsMovie; - return id == otherTyped.id && - title == otherTyped.title; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, title.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['title'] = nativeToJson(title); - return json; - } - - ListUserReviewsUserReviewsMovie({ - required this.id, - required this.title, - }); -} - -@immutable -class ListUserReviewsData { - final ListUserReviewsUser? user; - ListUserReviewsData.fromJson(dynamic json): - - user = json['user'] == null ? null : ListUserReviewsUser.fromJson(json['user']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListUserReviewsData otherTyped = other as ListUserReviewsData; - return user == otherTyped.user; - - } - @override - int get hashCode => user.hashCode; - - - Map toJson() { - Map json = {}; - if (user != null) { - json['user'] = user!.toJson(); - } - return json; - } - - ListUserReviewsData({ - this.user, - }); -} - diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/list_users.dart b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/list_users.dart deleted file mode 100644 index 5fead7eb..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/list_users.dart +++ /dev/null @@ -1,93 +0,0 @@ -part of 'generated.dart'; - -class ListUsersVariablesBuilder { - - final FirebaseDataConnect _dataConnect; - ListUsersVariablesBuilder(this._dataConnect, ); - Deserializer dataDeserializer = (dynamic json) => ListUsersData.fromJson(jsonDecode(json)); - - Future> execute() { - return ref().execute(); - } - - QueryRef ref() { - - return _dataConnect.query("ListUsers", dataDeserializer, emptySerializer, null); - } -} - -@immutable -class ListUsersUsers { - final String id; - final String username; - ListUsersUsers.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - username = nativeFromJson(json['username']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListUsersUsers otherTyped = other as ListUsersUsers; - return id == otherTyped.id && - username == otherTyped.username; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, username.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['username'] = nativeToJson(username); - return json; - } - - ListUsersUsers({ - required this.id, - required this.username, - }); -} - -@immutable -class ListUsersData { - final List users; - ListUsersData.fromJson(dynamic json): - - users = (json['users'] as List) - .map((e) => ListUsersUsers.fromJson(e)) - .toList(); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final ListUsersData otherTyped = other as ListUsersData; - return users == otherTyped.users; - - } - @override - int get hashCode => users.hashCode; - - - Map toJson() { - Map json = {}; - json['users'] = users.map((e) => e.toJson()).toList(); - return json; - } - - ListUsersData({ - required this.users, - }); -} - diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/search_movie.dart b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/search_movie.dart deleted file mode 100644 index 19e5f2d7..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/search_movie.dart +++ /dev/null @@ -1,167 +0,0 @@ -part of 'generated.dart'; - -class SearchMovieVariablesBuilder { - Optional _titleInput = Optional.optional(nativeFromJson, nativeToJson); - Optional _genre = Optional.optional(nativeFromJson, nativeToJson); - - final FirebaseDataConnect _dataConnect; - SearchMovieVariablesBuilder titleInput(String? t) { - _titleInput.value = t; - return this; - } - SearchMovieVariablesBuilder genre(String? t) { - _genre.value = t; - return this; - } - - SearchMovieVariablesBuilder(this._dataConnect, ); - Deserializer dataDeserializer = (dynamic json) => SearchMovieData.fromJson(jsonDecode(json)); - Serializer varsSerializer = (SearchMovieVariables vars) => jsonEncode(vars.toJson()); - Future> execute() { - return ref().execute(); - } - - QueryRef ref() { - SearchMovieVariables vars= SearchMovieVariables(titleInput: _titleInput,genre: _genre,); - return _dataConnect.query("SearchMovie", dataDeserializer, varsSerializer, vars); - } -} - -@immutable -class SearchMovieMovies { - final String id; - final String title; - final String? genre; - final String imageUrl; - SearchMovieMovies.fromJson(dynamic json): - - id = nativeFromJson(json['id']), - title = nativeFromJson(json['title']), - genre = json['genre'] == null ? null : nativeFromJson(json['genre']), - imageUrl = nativeFromJson(json['imageUrl']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final SearchMovieMovies otherTyped = other as SearchMovieMovies; - return id == otherTyped.id && - title == otherTyped.title && - genre == otherTyped.genre && - imageUrl == otherTyped.imageUrl; - - } - @override - int get hashCode => Object.hashAll([id.hashCode, title.hashCode, genre.hashCode, imageUrl.hashCode]); - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - json['title'] = nativeToJson(title); - if (genre != null) { - json['genre'] = nativeToJson(genre); - } - json['imageUrl'] = nativeToJson(imageUrl); - return json; - } - - SearchMovieMovies({ - required this.id, - required this.title, - this.genre, - required this.imageUrl, - }); -} - -@immutable -class SearchMovieData { - final List movies; - SearchMovieData.fromJson(dynamic json): - - movies = (json['movies'] as List) - .map((e) => SearchMovieMovies.fromJson(e)) - .toList(); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final SearchMovieData otherTyped = other as SearchMovieData; - return movies == otherTyped.movies; - - } - @override - int get hashCode => movies.hashCode; - - - Map toJson() { - Map json = {}; - json['movies'] = movies.map((e) => e.toJson()).toList(); - return json; - } - - SearchMovieData({ - required this.movies, - }); -} - -@immutable -class SearchMovieVariables { - late final OptionaltitleInput; - late final Optionalgenre; - @Deprecated('fromJson is deprecated for Variable classes as they are no longer required for deserialization.') - SearchMovieVariables.fromJson(Map json) { - - - titleInput = Optional.optional(nativeFromJson, nativeToJson); - titleInput.value = json['titleInput'] == null ? null : nativeFromJson(json['titleInput']); - - - genre = Optional.optional(nativeFromJson, nativeToJson); - genre.value = json['genre'] == null ? null : nativeFromJson(json['genre']); - - } - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final SearchMovieVariables otherTyped = other as SearchMovieVariables; - return titleInput == otherTyped.titleInput && - genre == otherTyped.genre; - - } - @override - int get hashCode => Object.hashAll([titleInput.hashCode, genre.hashCode]); - - - Map toJson() { - Map json = {}; - if(titleInput.state == OptionalState.set) { - json['titleInput'] = titleInput.toJson(); - } - if(genre.state == OptionalState.set) { - json['genre'] = genre.toJson(); - } - return json; - } - - SearchMovieVariables({ - required this.titleInput, - required this.genre, - }); -} - diff --git a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/upsert_user.dart b/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/upsert_user.dart deleted file mode 100644 index f797b726..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/dataconnect_generated/upsert_user.dart +++ /dev/null @@ -1,122 +0,0 @@ -part of 'generated.dart'; - -class UpsertUserVariablesBuilder { - String username; - - final FirebaseDataConnect _dataConnect; - UpsertUserVariablesBuilder(this._dataConnect, {required this.username,}); - Deserializer dataDeserializer = (dynamic json) => UpsertUserData.fromJson(jsonDecode(json)); - Serializer varsSerializer = (UpsertUserVariables vars) => jsonEncode(vars.toJson()); - Future> execute() { - return ref().execute(); - } - - MutationRef ref() { - UpsertUserVariables vars= UpsertUserVariables(username: username,); - return _dataConnect.mutation("UpsertUser", dataDeserializer, varsSerializer, vars); - } -} - -@immutable -class UpsertUserUserUpsert { - final String id; - UpsertUserUserUpsert.fromJson(dynamic json): - - id = nativeFromJson(json['id']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final UpsertUserUserUpsert otherTyped = other as UpsertUserUserUpsert; - return id == otherTyped.id; - - } - @override - int get hashCode => id.hashCode; - - - Map toJson() { - Map json = {}; - json['id'] = nativeToJson(id); - return json; - } - - UpsertUserUserUpsert({ - required this.id, - }); -} - -@immutable -class UpsertUserData { - final UpsertUserUserUpsert user_upsert; - UpsertUserData.fromJson(dynamic json): - - user_upsert = UpsertUserUserUpsert.fromJson(json['user_upsert']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final UpsertUserData otherTyped = other as UpsertUserData; - return user_upsert == otherTyped.user_upsert; - - } - @override - int get hashCode => user_upsert.hashCode; - - - Map toJson() { - Map json = {}; - json['user_upsert'] = user_upsert.toJson(); - return json; - } - - UpsertUserData({ - required this.user_upsert, - }); -} - -@immutable -class UpsertUserVariables { - final String username; - @Deprecated('fromJson is deprecated for Variable classes as they are no longer required for deserialization.') - UpsertUserVariables.fromJson(Map json): - - username = nativeFromJson(json['username']); - @override - bool operator ==(Object other) { - if(identical(this, other)) { - return true; - } - if(other.runtimeType != runtimeType) { - return false; - } - - final UpsertUserVariables otherTyped = other as UpsertUserVariables; - return username == otherTyped.username; - - } - @override - int get hashCode => username.hashCode; - - - Map toJson() { - Map json = {}; - json['username'] = nativeToJson(username); - return json; - } - - UpsertUserVariables({ - required this.username, - }); -} - diff --git a/apps/mobile/prototypes/client_mobile_application/lib/main.dart b/apps/mobile/prototypes/client_mobile_application/lib/main.dart deleted file mode 100644 index 336a9677..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/main.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter/foundation.dart' show kIsWeb; -import 'theme.dart'; -import 'router.dart'; -import 'widgets/web_mobile_frame.dart'; - -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - - const app = AppRoot(); - - runApp(ProviderScope(child: kIsWeb ? const WebMobileFrame(child: app) : app)); -} - -class AppRoot extends ConsumerWidget { - const AppRoot({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return MaterialApp.router( - title: 'Krow Client App', - theme: AppTheme.lightTheme, - routerConfig: router, - debugShowCheckedModeBanner: false, - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/router.dart b/apps/mobile/prototypes/client_mobile_application/lib/router.dart deleted file mode 100644 index 47109000..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/router.dart +++ /dev/null @@ -1,165 +0,0 @@ -import 'package:go_router/go_router.dart'; -import 'screens/auth/client_get_started_screen.dart'; -import 'screens/auth/client_sign_in_screen.dart'; -import 'screens/auth/client_sign_up_screen.dart'; -import 'screens/client/client_home_screen.dart'; -import 'screens/client/client_workers_screen.dart'; -import 'screens/client/client_timesheets_screen.dart'; -import 'screens/client/client_shifts_screen.dart'; -import 'screens/client/client_reports_screen.dart'; -import 'screens/client/create_order_screen.dart'; -import 'screens/client/client_settings_screen.dart'; -import 'screens/client/client_billing_screen.dart'; -import 'screens/client/client_coverage_screen.dart'; -import 'screens/client/client_hubs_screen.dart'; -import 'screens/client/verify_worker_attire_screen.dart'; -import 'screens/client/reports/daily_ops_report_screen.dart'; -import 'screens/client/reports/spend_report_screen.dart'; -import 'screens/client/reports/forecast_report_screen.dart'; -import 'screens/client/reports/performance_report_screen.dart'; -import 'screens/client/reports/no_show_report_screen.dart'; -import 'screens/client/reports/coverage_report_screen.dart'; -import 'screens/client/create_order_pages/rapid_order_flow_page.dart'; -import 'screens/client/create_order_pages/one_time_order_flow_page.dart'; -import 'screens/client/create_order_pages/recurring_order_flow_page.dart'; -import 'screens/client/create_order_pages/permanent_order_flow_page.dart'; -import 'widgets/scaffold_with_nav_bar.dart'; - -final router = GoRouter( - initialLocation: '/client-get-started', - routes: [ - GoRoute( - path: '/client-get-started', - builder: (context, state) => const ClientGetStartedScreen(), - ), - GoRoute( - path: '/client-sign-in', - builder: (context, state) => const ClientSignInScreen(), - ), - GoRoute( - path: '/client-sign-up', - builder: (context, state) => const ClientSignUpScreen(), - ), - GoRoute( - path: '/create-order', - builder: (context, state) => const CreateOrderScreen(), - routes: [ - GoRoute( - path: 'rapid', - builder: (context, state) => const RapidOrderFlowPage(), - ), - GoRoute( - path: 'one-time', - builder: (context, state) => const OneTimeOrderFlowPage(), - ), - GoRoute( - path: 'recurring', - builder: (context, state) => const RecurringOrderFlowPage(), - ), - GoRoute( - path: 'permanent', - builder: (context, state) => const PermanentOrderFlowPage(), - ), - ], - ), - GoRoute( - path: '/client-settings', - builder: (context, state) => const ClientSettingsScreen(), - ), - GoRoute( - path: '/client-hubs', - builder: (context, state) => const ClientHubsScreen(), - ), - GoRoute( - path: '/verify-worker-attire', - builder: (context, state) => const VerifyWorkerAttireScreen(), - ), - // Report Routes - GoRoute( - path: '/daily-ops-report', - builder: (context, state) => const DailyOpsReportScreen(), - ), - GoRoute( - path: '/spend-report', - builder: (context, state) => const SpendReportScreen(), - ), - GoRoute( - path: '/forecast-report', - builder: (context, state) => const ForecastReportScreen(), - ), - GoRoute( - path: '/performance-report', - builder: (context, state) => const PerformanceReportScreen(), - ), - GoRoute( - path: '/no-show-report', - builder: (context, state) => const NoShowReportScreen(), - ), - GoRoute( - path: '/coverage-report-detail', - builder: (context, state) => const CoverageReportScreen(), - ), - // Moved Workers and Timesheets out of bottom nav, accessible as standalone routes - GoRoute( - path: '/client-workers', - builder: (context, state) => const ClientWorkersScreen(), - ), - GoRoute( - path: '/client-timesheets', - builder: (context, state) => const ClientTimesheetsScreen(), - ), - - StatefulShellRoute.indexedStack( - builder: (context, state, navigationShell) { - return ScaffoldWithNavBar(navigationShell: navigationShell); - }, - branches: [ - // Index 0: Coverage - StatefulShellBranch( - routes: [ - GoRoute( - path: '/client-coverage', - builder: (context, state) => const ClientCoverageScreen(), - ), - ], - ), - // Index 1: Billing - StatefulShellBranch( - routes: [ - GoRoute( - path: '/client-billing', - builder: (context, state) => const ClientBillingScreen(), - ), - ], - ), - // Index 2: Home - StatefulShellBranch( - routes: [ - GoRoute( - path: '/client-home', - builder: (context, state) => const ClientHomeScreen(), - ), - ], - ), - // Index 3: Orders (Shifts) - StatefulShellBranch( - routes: [ - GoRoute( - path: '/client-shifts', - builder: (context, state) => const ClientShiftsScreen(), - ), - ], - ), - // Index 4: Reports - StatefulShellBranch( - routes: [ - GoRoute( - path: '/client-reports', - builder: (context, state) => const ClientReportsScreen(), - ), - ], - ), - ], - ), - ], -); diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/auth/client_get_started_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/auth/client_get_started_screen.dart deleted file mode 100644 index 77f20b1e..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/auth/client_get_started_screen.dart +++ /dev/null @@ -1,392 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; - -class ClientGetStartedScreen extends StatelessWidget { - const ClientGetStartedScreen({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.krowBlue, - body: SafeArea( - child: Column( - children: [ - const SizedBox(height: 12), - // Logo - Image.network( - 'https://qtrypzzcjebvfcihiynt.supabase.co/storage/v1/object/public/base44-prod/public/692e9622b387da7cdcd95980/29a493751_PNG3Krow.png', - height: 40, - fit: BoxFit.contain, - ), - - // Floating Cards Area - const Expanded( - child: Stack( - alignment: Alignment.center, - clipBehavior: Clip.none, - children: [ - // Card 1 - Shift Order - Positioned(left: 24, top: 32, child: _ShiftOrderCard()), - - // Card 2 - Worker Profile - Positioned(right: 24, top: 16, child: _WorkerProfileCard()), - - // Card 3 - Calendar - Positioned(top: 112, child: _CalendarCard()), - ], - ), - ), - - // Bottom Content - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 40), - child: Column( - children: [ - const Text( - 'Take Control of Your\nShifts and Events', - textAlign: TextAlign.center, - style: TextStyle( - color: Colors.white, - fontSize: 30, - fontWeight: FontWeight.bold, - height: 1.1, - ), - ), - const SizedBox(height: 12), - const Text( - 'Streamline your operations with powerful tools to manage schedules, track performance, and keep your team on the same page—all in one place', - textAlign: TextAlign.center, - style: TextStyle( - color: Colors.white70, - fontSize: 14, - height: 1.4, - ), - ), - const SizedBox(height: 32), - - // Sign In Button - SizedBox( - width: double.infinity, - height: 56, - child: ElevatedButton( - onPressed: () => context.push('/client-sign-in'), - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowYellow, - foregroundColor: AppColors.krowCharcoal, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28), - ), - elevation: 0, - ), - child: const Text( - 'Sign In', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - ), - ), - - const SizedBox(height: 12), - - // Create Account Button - SizedBox( - width: double.infinity, - height: 56, - child: ElevatedButton( - onPressed: () => context.push('/client-sign-up'), - style: ElevatedButton.styleFrom( - backgroundColor: Colors.white, - foregroundColor: AppColors.krowCharcoal, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28), - ), - elevation: 0, - ), - child: const Text( - 'Create Account', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - ), - ), - ], - ), - ), - ], - ), - ), - ); - } -} - -class _ShiftOrderCard extends StatelessWidget { - const _ShiftOrderCard(); - - @override - Widget build(BuildContext context) { - return Transform.rotate( - angle: -12 * 3.14159 / 180, - child: Container( - width: 160, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Row( - children: [ - Container( - width: 20, - height: 20, - decoration: BoxDecoration( - color: Colors.green.shade100, - borderRadius: BorderRadius.circular(4), - ), - child: const Center( - child: Icon(Icons.check, size: 14, color: Colors.green), - ), - ), - const SizedBox(width: 8), - const Text( - 'Confirmed', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w600, - color: Colors.green, - ), - ), - ], - ), - const SizedBox(height: 8), - const Text( - 'Taste of the Town', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const Text( - 'Event Catering', - style: TextStyle(fontSize: 10, color: Colors.grey), - ), - const SizedBox(height: 8), - const Row( - children: [ - Icon(LucideIcons.calendar, size: 12, color: Colors.grey), - SizedBox(width: 4), - Text( - '01.21.2025, 06:30 pm', - style: TextStyle(fontSize: 10, color: Colors.grey), - ), - ], - ), - ], - ), - ), - ); - } -} - -class _WorkerProfileCard extends StatelessWidget { - const _WorkerProfileCard(); - - @override - Widget build(BuildContext context) { - return Transform.rotate( - angle: 8 * 3.14159 / 180, - child: Container( - width: 144, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 48, - height: 48, - decoration: const BoxDecoration( - shape: BoxShape.circle, - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [Colors.orangeAccent, Colors.deepOrange], - ), - ), - ), - const SizedBox(height: 8), - const Text( - '★ Verified', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w600, - color: Colors.green, - ), - ), - const SizedBox(height: 2), - const Text( - 'Jane Johnson', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const Text( - 'Server • 4.9 ★', - style: TextStyle(fontSize: 10, color: Colors.grey), - ), - ], - ), - ), - ); - } -} - -class _CalendarCard extends StatelessWidget { - const _CalendarCard(); - - @override - Widget build(BuildContext context) { - return Container( - width: 192, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'January 2025', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Icon(LucideIcons.clipboardList, size: 16, color: Colors.grey), - ], - ), - const SizedBox(height: 8), - GridView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 7, - mainAxisSpacing: 2, - crossAxisSpacing: 2, - childAspectRatio: 1, - ), - itemCount: 7 + 31, - itemBuilder: (context, index) { - if (index < 7) { - final days = ['S', 'M', 'T', 'W', 'T', 'F', 'S']; - return Center( - child: Text( - days[index], - style: const TextStyle(fontSize: 8, color: Colors.grey), - ), - ); - } - final day = index - 7 + 1; - Color? bg; - Color? text; - - if (day == 21) { - bg = Colors.blue.shade600; - text = Colors.white; - } else if (day == 15) { - // Adjusted to match visual roughly - bg = Colors.green.shade100; - text = Colors.green.shade600; - } - - return Container( - decoration: BoxDecoration( - color: bg, - borderRadius: BorderRadius.circular(4), - ), - child: Center( - child: Text( - '$day', - style: TextStyle( - fontSize: 8, - color: text ?? Colors.grey.shade600, - ), - ), - ), - ); - }, - ), - const SizedBox(height: 8), - Row( - children: [ - Container( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - decoration: BoxDecoration( - color: Colors.green.shade100, - borderRadius: BorderRadius.circular(4), - ), - child: const Text( - 'Active Event', - style: TextStyle(fontSize: 8, color: Colors.green), - ), - ), - const SizedBox(width: 4), - Container( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - decoration: BoxDecoration( - color: Colors.amber.shade100, - borderRadius: BorderRadius.circular(4), - ), - child: const Text( - 'Assigned Event', - style: TextStyle(fontSize: 8, color: Colors.amber), - ), - ), - ], - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/auth/client_sign_in_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/auth/client_sign_in_screen.dart deleted file mode 100644 index f0a287be..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/auth/client_sign_in_screen.dart +++ /dev/null @@ -1,384 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; - -class ClientSignInScreen extends StatefulWidget { - const ClientSignInScreen({super.key}); - - @override - State createState() => _ClientSignInScreenState(); -} - -class _ClientSignInScreenState extends State { - final _emailController = TextEditingController(); - final _passwordController = TextEditingController(); - bool _obscurePassword = true; - bool _isLoading = false; - - void _handleSignIn() async { - setState(() => _isLoading = true); - // Simulate sign in - await Future.delayed(const Duration(seconds: 1)); - if (mounted) { - setState(() => _isLoading = false); - context.go('/client-home'); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.krowBlue, - body: SafeArea( - bottom: false, - child: Column( - children: [ - // Header - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.1), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.chevronLeft, - color: Colors.white, - ), - ), - ), - ], - ), - ), - - Padding( - padding: const EdgeInsets.only(bottom: 32), - child: Image.network( - 'https://qtrypzzcjebvfcihiynt.supabase.co/storage/v1/object/public/base44-prod/public/692e9622b387da7cdcd95980/29a493751_PNG3Krow.png', - height: 40, - fit: BoxFit.contain, - ), - ), - - // Form Card - Expanded( - child: Container( - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(32), - topRight: Radius.circular(32), - ), - ), - padding: const EdgeInsets.fromLTRB(24, 32, 24, 0), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Text( - 'Welcome Back', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - const Text( - 'Sign in to manage your shifts and workers', - style: TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 32), - - // Email Field - const Text( - 'Email', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - TextField( - controller: _emailController, - decoration: InputDecoration( - hintText: 'Enter your email', - prefixIcon: const Icon( - LucideIcons.mail, - color: AppColors.krowMuted, - size: 20, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBlue, - ), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - ), - ), - const SizedBox(height: 20), - - // Password Field - const Text( - 'Password', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - TextField( - controller: _passwordController, - obscureText: _obscurePassword, - decoration: InputDecoration( - hintText: 'Enter your password', - prefixIcon: const Icon( - LucideIcons.lock, - color: AppColors.krowMuted, - size: 20, - ), - suffixIcon: IconButton( - icon: Icon( - _obscurePassword - ? LucideIcons.eyeOff - : LucideIcons.eye, - color: AppColors.krowMuted, - size: 20, - ), - onPressed: () => setState( - () => _obscurePassword = !_obscurePassword, - ), - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBlue, - ), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - ), - ), - - // Forgot Password - Align( - alignment: Alignment.centerRight, - child: TextButton( - onPressed: () {}, - child: const Text( - 'Forgot Password?', - style: TextStyle( - color: AppColors.krowBlue, - fontWeight: FontWeight.w500, - fontSize: 14, - ), - ), - ), - ), - - const SizedBox(height: 8), - - // Sign In Button - SizedBox( - height: 56, - child: ElevatedButton( - onPressed: _isLoading ? null : _handleSignIn, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: _isLoading - ? const CircularProgressIndicator( - color: Colors.white, - ) - : const Text( - 'Sign In', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.white, - ), - ), - ), - ), - - const SizedBox(height: 24), - - // Divider - const Row( - children: [ - Expanded(child: Divider(color: AppColors.krowBorder)), - Padding( - padding: EdgeInsets.symmetric(horizontal: 16), - child: Text( - 'or', - style: TextStyle( - color: AppColors.krowMuted, - fontSize: 14, - ), - ), - ), - Expanded(child: Divider(color: AppColors.krowBorder)), - ], - ), - - const SizedBox(height: 24), - - // Social Buttons - _SocialButton( - text: 'Sign In with Apple', - icon: Icons.apple, - onPressed: _handleSignIn, - ), - const SizedBox(height: 12), - _SocialButton( - text: 'Sign In with Google', - icon: Icons - .flutter_dash, // Custom Google icon logic if needed - isGoogle: true, - onPressed: _handleSignIn, - ), - - const SizedBox(height: 32), - - // Sign Up Link - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - "Don't have an account? ", - style: TextStyle( - color: AppColors.krowMuted, - fontSize: 14, - ), - ), - GestureDetector( - onTap: () => context.push('/client-sign-up'), - child: const Text( - 'Sign Up', - style: TextStyle( - color: AppColors.krowBlue, - fontWeight: FontWeight.w600, - fontSize: 14, - ), - ), - ), - ], - ), - const SizedBox(height: 40), - ], - ), - ), - ), - ), - ], - ), - ), - ); - } -} - -class _SocialButton extends StatelessWidget { - final String text; - final IconData? icon; - final bool isGoogle; - final VoidCallback onPressed; - - const _SocialButton({ - required this.text, - this.icon, - this.isGoogle = false, - required this.onPressed, - }); - - @override - Widget build(BuildContext context) { - return SizedBox( - height: 56, - child: OutlinedButton( - onPressed: onPressed, - style: OutlinedButton.styleFrom( - side: const BorderSide(color: AppColors.krowBorder), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - foregroundColor: AppColors.krowCharcoal, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (text.contains('Apple')) - const FaIcon( - FontAwesomeIcons.apple, - color: Colors.black, - size: 20, - ) - else if (isGoogle) - const FaIcon( - FontAwesomeIcons.google, - color: Colors.black, - size: 20, - ) - else - Icon(icon, color: AppColors.krowCharcoal, size: 20), - const SizedBox(width: 12), - Text( - text, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/auth/client_sign_up_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/auth/client_sign_up_screen.dart deleted file mode 100644 index f0ae3771..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/auth/client_sign_up_screen.dart +++ /dev/null @@ -1,463 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; - -class ClientSignUpScreen extends StatefulWidget { - const ClientSignUpScreen({super.key}); - - @override - State createState() => _ClientSignUpScreenState(); -} - -class _ClientSignUpScreenState extends State { - final _companyController = TextEditingController(); - final _emailController = TextEditingController(); - final _passwordController = TextEditingController(); - final _confirmPasswordController = TextEditingController(); - bool _obscurePassword = true; - bool _isLoading = false; - - void _handleSignUp() async { - setState(() => _isLoading = true); - // Simulate sign up - await Future.delayed(const Duration(seconds: 1)); - if (mounted) { - setState(() => _isLoading = false); - context.go('/client-home'); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.krowBlue, - body: SafeArea( - bottom: false, - child: Column( - children: [ - // Header - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.1), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.chevronLeft, - color: Colors.white, - ), - ), - ), - ], - ), - ), - - Padding( - padding: const EdgeInsets.only(bottom: 24), - child: Image.network( - 'https://qtrypzzcjebvfcihiynt.supabase.co/storage/v1/object/public/base44-prod/public/692e9622b387da7cdcd95980/29a493751_PNG3Krow.png', - height: 40, - fit: BoxFit.contain, - ), - ), - - // Form Card - Expanded( - child: Container( - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(32), - topRight: Radius.circular(32), - ), - ), - padding: const EdgeInsets.fromLTRB(24, 32, 24, 0), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Text( - 'Create Account', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - const Text( - 'Get started with Krow for your business', - style: TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 24), - - // Company Name Field - const Text( - 'Company Name', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - TextField( - controller: _companyController, - decoration: InputDecoration( - hintText: 'Enter company name', - prefixIcon: const Icon( - LucideIcons.building2, - color: AppColors.krowMuted, - size: 20, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBlue, - ), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - ), - ), - const SizedBox(height: 20), - - // Email Field - const Text( - 'Email', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - TextField( - controller: _emailController, - decoration: InputDecoration( - hintText: 'Enter your email', - prefixIcon: const Icon( - LucideIcons.mail, - color: AppColors.krowMuted, - size: 20, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBlue, - ), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - ), - ), - const SizedBox(height: 20), - - // Password Field - const Text( - 'Password', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - TextField( - controller: _passwordController, - obscureText: _obscurePassword, - decoration: InputDecoration( - hintText: 'Create a password', - prefixIcon: const Icon( - LucideIcons.lock, - color: AppColors.krowMuted, - size: 20, - ), - suffixIcon: IconButton( - icon: Icon( - _obscurePassword - ? LucideIcons.eyeOff - : LucideIcons.eye, - color: AppColors.krowMuted, - size: 20, - ), - onPressed: () => setState( - () => _obscurePassword = !_obscurePassword, - ), - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBlue, - ), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - ), - ), - const SizedBox(height: 20), - - // Confirm Password Field - const Text( - 'Confirm Password', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - TextField( - controller: _confirmPasswordController, - obscureText: _obscurePassword, - decoration: InputDecoration( - hintText: 'Confirm your password', - prefixIcon: const Icon( - LucideIcons.lock, - color: AppColors.krowMuted, - size: 20, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBlue, - ), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - ), - ), - - const SizedBox(height: 32), - - // Create Account Button - SizedBox( - height: 56, - child: ElevatedButton( - onPressed: _isLoading ? null : _handleSignUp, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: _isLoading - ? const CircularProgressIndicator( - color: Colors.white, - ) - : const Text( - 'Create Account', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.white, - ), - ), - ), - ), - - const SizedBox(height: 24), - - // Divider - const Row( - children: [ - Expanded(child: Divider(color: AppColors.krowBorder)), - Padding( - padding: EdgeInsets.symmetric(horizontal: 16), - child: Text( - 'or', - style: TextStyle( - color: AppColors.krowMuted, - fontSize: 14, - ), - ), - ), - Expanded(child: Divider(color: AppColors.krowBorder)), - ], - ), - - const SizedBox(height: 24), - - // Social Buttons - _SocialButton( - text: 'Sign Up with Apple', - icon: Icons.apple, - onPressed: () {}, - ), - const SizedBox(height: 12), - _SocialButton( - text: 'Sign Up with Google', - icon: null, - isGoogle: true, - onPressed: () {}, - ), - - const SizedBox(height: 32), - - // Sign In Link - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - "Already have an account? ", - style: TextStyle( - color: AppColors.krowMuted, - fontSize: 14, - ), - ), - GestureDetector( - onTap: () => context.push('/client-sign-in'), - child: const Text( - 'Sign In', - style: TextStyle( - color: AppColors.krowBlue, - fontWeight: FontWeight.w600, - fontSize: 14, - ), - ), - ), - ], - ), - const SizedBox(height: 40), - ], - ), - ), - ), - ), - ], - ), - ), - ); - } -} - -class _SocialButton extends StatelessWidget { - final String text; - final IconData? icon; - final bool isGoogle; - final VoidCallback onPressed; - - const _SocialButton({ - required this.text, - this.icon, - this.isGoogle = false, - required this.onPressed, - }); - - @override - Widget build(BuildContext context) { - return SizedBox( - height: 56, - child: OutlinedButton( - onPressed: onPressed, - style: OutlinedButton.styleFrom( - side: const BorderSide(color: AppColors.krowBorder), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - foregroundColor: AppColors.krowCharcoal, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (isGoogle) - Container( - width: 20, - height: 20, - decoration: const BoxDecoration(shape: BoxShape.circle), - child: Image.network( - 'https://www.gstatic.com/images/branding/product/1x/gsa_512dp.png', - width: 20, - height: 20, - ), - ) - else if (text.contains('Apple')) - Image.network( - 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Apple_logo_black.svg/480px-Apple_logo_black.svg.png', - height: 24, - ) - else - Icon(icon, color: AppColors.krowCharcoal, size: 20), - const SizedBox(width: 12), - Text( - text, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_billing_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_billing_screen.dart deleted file mode 100644 index 633a21e1..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_billing_screen.dart +++ /dev/null @@ -1,990 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; - -class ClientBillingScreen extends StatefulWidget { - const ClientBillingScreen({super.key}); - - @override - State createState() => _ClientBillingScreenState(); -} - -class _ClientBillingScreenState extends State - with SingleTickerProviderStateMixin { - late TabController _periodTabController; - - // Mock Data - final double currentBill = 4250.00; - final double savings = 320.00; - - final List> pendingInvoices = [ - { - 'id': 'INV-PEND-001', - 'title': 'Server Staff - Downtown Event', - 'location_address': '123 Main St, City Center', - 'client_name': 'TechCorp Inc.', - 'date': '2024-01-24', // Use a recent date - 'invoiceTotal': 840.00, - 'workers_count': 3, - 'total_hours': 24.0, - }, - { - 'id': 'INV-PEND-002', - 'title': 'Bartenders - Private Party', - 'location_address': '456 High St, West End', - 'client_name': 'TechCorp Inc.', - 'date': '2024-01-23', - 'invoiceTotal': 620.00, - 'workers_count': 2, - 'total_hours': 16.0, - } - ]; - - final List> breakdown = [ - {'category': 'Server Staff', 'hours': 120, 'amount': 2160.00}, - {'category': 'Bartenders', 'hours': 80, 'amount': 1520.00}, - {'category': 'Kitchen Staff', 'hours': 40, 'amount': 640.00}, - {'category': 'Event Staff', 'hours': 25, 'amount': 425.00}, - ]; - - final List> invoices = [ - { - 'id': 'INV-2024-012', - 'date': '2024-12-15', - 'amount': 5280.00, - 'status': 'paid' - }, - { - 'id': 'INV-2024-011', - 'date': '2024-12-08', - 'amount': 4850.00, - 'status': 'paid' - }, - { - 'id': 'INV-2024-010', - 'date': '2024-12-01', - 'amount': 4120.00, - 'status': 'paid' - }, - ]; - - @override - void initState() { - super.initState(); - _periodTabController = TabController(length: 2, vsync: this); - } - - @override - void dispose() { - _periodTabController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - // Colors matching React - const krowBlue = Color(0xFF0A39DF); - const krowYellow = Color(0xFFFFED4A); - const krowCharcoal = Color(0xFF121826); - // const krowMuted = Color(0xFF6A7382); // Already in theme? Using AppColors.krowMuted - - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: Column( - children: [ - // Header - Container( - padding: const EdgeInsets.fromLTRB(20, 60, 20, 20), - color: krowBlue, - child: Column( - children: [ - // Top Bar - Row( - children: [ - GestureDetector( - onTap: () => context.go('/client-home'), - child: Container( - width: 36, - height: 36, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 16, - ), - ), - ), - const SizedBox(width: 12), - const Text( - 'Billing', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ], - ), - const SizedBox(height: 20), - // Current Bill - Column( - children: [ - Text( - 'Current Period', - style: TextStyle( - color: Colors.white.withOpacity(0.7), - fontSize: 12, - ), - ), - const SizedBox(height: 4), - Text( - '\$${currentBill.toStringAsFixed(2)}', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - const SizedBox(height: 8), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), - decoration: BoxDecoration( - color: krowYellow, - borderRadius: BorderRadius.circular(100), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon( - LucideIcons.trendingDown, - size: 12, - color: krowCharcoal, - ), - const SizedBox(width: 4), - Text( - '\$${savings.toStringAsFixed(0)} saved', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: krowCharcoal, - ), - ), - ], - ), - ), - ], - ), - ], - ), - ), - - // Content - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Pending Invoices - if (pendingInvoices.isNotEmpty) ...[ - Row( - children: [ - Container( - width: 6, - height: 6, - decoration: const BoxDecoration( - color: Colors.orange, - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 8), - const Text( - 'Awaiting Approval', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - const SizedBox(width: 8), - Container( - width: 24, - height: 24, - decoration: const BoxDecoration( - color: krowYellow, - shape: BoxShape.circle, - ), - child: Center( - child: Text( - '${pendingInvoices.length}', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - ), - ), - ], - ), - const SizedBox(height: 12), - ...pendingInvoices.map( - (invoice) => Padding( - padding: const EdgeInsets.only(bottom: 8), - child: _buildPendingInvoiceCard(invoice), - ), - ), - const SizedBox(height: 16), - ], - - // Payment Method - _buildPaymentMethodCard(krowBlue, krowYellow, krowCharcoal), - const SizedBox(height: 16), - - // Spending Breakdown - _buildBreakdownCard(krowCharcoal), - const SizedBox(height: 16), - - // Savings Card - _buildSavingsCard(krowBlue, krowYellow, krowCharcoal), - const SizedBox(height: 24), - - // Invoice History - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Invoice History', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - TextButton( - onPressed: () {}, - style: TextButton.styleFrom( - padding: EdgeInsets.zero, - minimumSize: Size.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - child: Row( - children: [ - Text( - 'View all', - style: TextStyle( - fontSize: 12, - color: krowBlue, - fontWeight: FontWeight.w500, - ), - ), - Icon( - LucideIcons.chevronRight, - size: 16, - color: krowBlue, - ), - ], - ), - ), - ], - ), - const SizedBox(height: 8), - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: const Color(0xFFE3E6E9)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - children: invoices.asMap().entries.map((entry) { - final index = entry.key; - final invoice = entry.value; - return Column( - children: [ - if (index > 0) - const Divider( - height: 1, - color: Color(0xFFF1F5F9), - ), - _buildInvoiceItem(invoice), - ], - ); - }).toList(), - ), - ), - - const SizedBox(height: 24), - - // Export Button - OutlinedButton.icon( - onPressed: () {}, - style: OutlinedButton.styleFrom( - minimumSize: const Size(double.infinity, 44), - side: const BorderSide(color: Color(0xFFE3E6E9)), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - foregroundColor: krowCharcoal, - ), - icon: const Icon(LucideIcons.download, size: 16), - label: const Text( - 'Export All Invoices', - style: TextStyle(fontSize: 14), - ), - ), - const SizedBox(height: 24), - ], - ), - ), - ), - ], - ), - ); - } - - Widget _buildPendingInvoiceCard(Map invoice) { - const krowBlue = Color(0xFF0A39DF); - const krowCharcoal = Color(0xFF121826); - - return Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: const Color(0xFFE3E6E9)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Padding( - padding: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Address - Row( - children: [ - const Icon( - LucideIcons.mapPin, - size: 14, - color: Color(0xFF475569), - ), - const SizedBox(width: 4), - Expanded( - child: Text( - invoice['location_address'], - style: const TextStyle( - fontSize: 12, - color: Color(0xFF475569), - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - const SizedBox(height: 4), - // Title - Text( - invoice['title'], - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - const SizedBox(height: 4), - // Client & Date - Row( - children: [ - Text( - invoice['client_name'], - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), - ), - ), - const SizedBox(width: 6), - const Text( - '•', - style: TextStyle(fontSize: 12, color: Color(0xFF94A3B8)), - ), - const SizedBox(width: 6), - Text( - invoice['date'], // Should ideally format date - style: const TextStyle( - fontSize: 12, - color: Color(0xFF475569), - ), - ), - ], - ), - const SizedBox(height: 8), - // Status - Row( - children: [ - Container( - width: 6, - height: 6, - decoration: const BoxDecoration( - color: Colors.orange, - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 6), - const Text( - 'PENDING APPROVAL', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: Colors.orange, - letterSpacing: 0.5, - ), - ), - ], - ), - const SizedBox(height: 12), - // Grid Stats - Container( - padding: const EdgeInsets.symmetric(vertical: 10), - decoration: const BoxDecoration( - border: Border.symmetric( - horizontal: BorderSide(color: Color(0xFFF1F5F9)), - ), - ), - child: Row( - children: [ - Expanded( - child: Column( - children: [ - const Icon( - LucideIcons.dollarSign, - size: 14, - color: Color(0xFF94A3B8), - ), - const SizedBox(height: 2), - Text( - '\$${invoice['invoiceTotal'].toStringAsFixed(2)}', - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - const Text( - 'Total', - style: TextStyle( - fontSize: 10, - color: Color(0xFF64748B), - ), - ), - ], - ), - ), - Container(width: 1, height: 30, color: const Color(0xFFF1F5F9)), - Expanded( - child: Column( - children: [ - const Icon( - LucideIcons.users, - size: 14, - color: Color(0xFF94A3B8), - ), - const SizedBox(height: 2), - Text( - '${invoice['workers_count']}', - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - const Text( - 'workers', - style: TextStyle( - fontSize: 10, - color: Color(0xFF64748B), - ), - ), - ], - ), - ), - Container(width: 1, height: 30, color: const Color(0xFFF1F5F9)), - Expanded( - child: Column( - children: [ - const Icon( - LucideIcons.clock, - size: 14, - color: Color(0xFF94A3B8), - ), - const SizedBox(height: 2), - Text( - '${invoice['total_hours'].toStringAsFixed(1)}', - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - const Text( - 'HRS', - style: TextStyle( - fontSize: 10, - color: Color(0xFF64748B), - ), - ), - ], - ), - ), - ], - ), - ), - const SizedBox(height: 12), - // Approve Button - ElevatedButton( - onPressed: () {}, - style: ElevatedButton.styleFrom( - backgroundColor: krowBlue, - foregroundColor: Colors.white, - minimumSize: const Size(double.infinity, 36), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - elevation: 0, - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(LucideIcons.checkCircle, size: 16), - SizedBox(width: 6), - Text( - 'Review & Approve', - style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600), - ), - ], - ), - ), - ], - ), - ), - ); - } - - Widget _buildPaymentMethodCard( - Color krowBlue, - Color krowYellow, - Color krowCharcoal, - ) { - return Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: const Color(0xFFE3E6E9)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Payment Method', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - TextButton.icon( - onPressed: () {}, - icon: Icon(LucideIcons.plus, size: 14, color: krowBlue), - label: Text( - 'Add', - style: TextStyle(fontSize: 12, color: krowBlue), - ), - style: TextButton.styleFrom( - padding: EdgeInsets.zero, - minimumSize: Size.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - ), - ], - ), - const SizedBox(height: 8), - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: const Color(0xFFF8FAFC), - borderRadius: BorderRadius.circular(8), - ), - child: Row( - children: [ - Container( - width: 40, - height: 28, - decoration: BoxDecoration( - color: krowBlue, - borderRadius: BorderRadius.circular(4), - ), - child: const Center( - child: Text( - 'VISA', - style: TextStyle( - color: Colors.white, - fontSize: 10, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - const SizedBox(width: 8), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - '•••• 4242', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - const Text( - 'Expires 12/25', - style: TextStyle( - fontSize: 10, - color: Color(0xFF64748B), - ), - ), - ], - ), - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 6, - vertical: 2, - ), - decoration: BoxDecoration( - color: krowYellow, - borderRadius: BorderRadius.circular(4), - ), - child: Text( - 'Default', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildBreakdownCard(Color krowCharcoal) { - return Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: const Color(0xFFE3E6E9)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'This Period Breakdown', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - Container( - height: 24, - decoration: BoxDecoration( - color: const Color(0xFFF1F5F9), - borderRadius: BorderRadius.circular(6), - ), - child: TabBar( - controller: _periodTabController, - isScrollable: true, - indicator: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(4), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 1, - ), - ], - ), - labelColor: krowCharcoal, - unselectedLabelColor: const Color(0xFF64748B), - labelStyle: const TextStyle( - fontSize: 10, - fontWeight: FontWeight.w600, - ), - padding: const EdgeInsets.all(2), - indicatorSize: TabBarIndicatorSize.tab, - labelPadding: const EdgeInsets.symmetric(horizontal: 8), - dividerColor: Colors.transparent, - tabs: const [Tab(text: 'Week'), Tab(text: 'Month')], - ), - ), - ], - ), - const SizedBox(height: 8), - ...breakdown.map((item) => _buildBreakdownRow(item, krowCharcoal)), - const Padding( - padding: EdgeInsets.symmetric(vertical: 8), - child: Divider(height: 1, color: Color(0xFFE2E8F0)), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Total', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - Text( - '\$${breakdown.fold(0.0, (sum, item) => sum + (item['amount'] as double)).toStringAsFixed(2)}', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - ], - ), - ], - ), - ); - } - - Widget _buildBreakdownRow(Map item, Color krowCharcoal) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 6), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - item['category'], - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: krowCharcoal, - ), - ), - Text( - '${item['hours']} hours', - style: const TextStyle(fontSize: 10, color: Color(0xFF64748B)), - ), - ], - ), - Text( - '\$${(item['amount'] as double).toStringAsFixed(2)}', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: krowCharcoal, - ), - ), - ], - ), - ); - } - - Widget _buildSavingsCard( - Color krowBlue, - Color krowYellow, - Color krowCharcoal, - ) { - return Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: krowYellow.withOpacity(0.2), - borderRadius: BorderRadius.circular(12), - border: Border.all(color: krowYellow), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: krowYellow, - borderRadius: BorderRadius.circular(8), - ), - child: Icon(LucideIcons.trendingDown, size: 16, color: krowCharcoal), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Rate Optimization', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - const SizedBox(height: 4), - const Text( - 'Save \$180/month by switching 3 shifts', - style: TextStyle(fontSize: 12, color: Color(0xFF475569)), - ), - const SizedBox(height: 8), - SizedBox( - height: 28, - child: ElevatedButton( - onPressed: () {}, - style: ElevatedButton.styleFrom( - backgroundColor: krowBlue, - foregroundColor: Colors.white, - elevation: 0, - padding: const EdgeInsets.symmetric(horizontal: 12), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - child: const Text( - 'View Details', - style: TextStyle(fontSize: 10), - ), - ), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildInvoiceItem(Map invoice) { - const krowCharcoal = Color(0xFF121826); - const krowBlue = Color(0xFF0A39DF); - - return Padding( - padding: const EdgeInsets.all(12), - child: Row( - children: [ - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: const Color(0xFFF1F5F9), - borderRadius: BorderRadius.circular(8), - ), - child: const Icon( - LucideIcons.fileText, - size: 16, - color: Color(0xFF64748B), - ), - ), - const SizedBox(width: 8), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - invoice['id'], - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: krowCharcoal, - ), - ), - Text( - invoice['date'], // Should format date - style: const TextStyle( - fontSize: 10, - color: Color(0xFF64748B), - ), - ), - ], - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - '\$${(invoice['amount'] as double).toStringAsFixed(2)}', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: krowCharcoal, - ), - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - decoration: BoxDecoration( - color: krowBlue.withOpacity(0.1), - borderRadius: BorderRadius.circular(4), - ), - child: Text( - invoice['status'].toString().toUpperCase(), - style: const TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: krowBlue, - ), - ), - ), - ], - ), - const SizedBox(width: 8), - const Icon(LucideIcons.download, size: 16, color: Color(0xFF94A3B8)), - ], - ), - ); - } -} \ No newline at end of file diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_coverage_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_coverage_screen.dart deleted file mode 100644 index c64398f6..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_coverage_screen.dart +++ /dev/null @@ -1,967 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:intl/intl.dart'; -import 'package:lucide_icons/lucide_icons.dart'; - -class ClientCoverageScreen extends StatefulWidget { - const ClientCoverageScreen({super.key}); - - @override - State createState() => _ClientCoverageScreenState(); -} - -class _ClientCoverageScreenState extends State { - DateTime _selectedDate = DateTime.now(); - late DateTime _today; - - // Mock Data - final List> _shifts = [ - { - 'id': '1', - 'title': 'Banquet Server', - 'location': 'Grand Ballroom', - 'startTime': '16:00', // 4:00 PM - 'workersNeeded': 10, - 'date': DateTime.now().toIso8601String().split('T')[0], - 'workers': [ - { - 'name': 'Sarah Wilson', - 'status': 'confirmed', - 'checkInTime': '15:55', - }, - {'name': 'Mike Ross', 'status': 'confirmed', 'checkInTime': '16:00'}, - { - 'name': 'Jane Doe', - 'status': 'confirmed', - 'checkInTime': null, - }, // En route - {'name': 'John Smith', 'status': 'late', 'checkInTime': null}, - ], - }, - { - 'id': '2', - 'title': 'Bartender', - 'location': 'Lobby Bar', - 'startTime': '17:00', // 5:00 PM - 'workersNeeded': 4, - 'date': DateTime.now().toIso8601String().split('T')[0], - 'workers': [ - { - 'name': 'Emily Blunt', - 'status': 'confirmed', - 'checkInTime': '16:45', - }, - { - 'name': 'Chris Evans', - 'status': 'confirmed', - 'checkInTime': '16:50', - }, - { - 'name': 'Tom Holland', - 'status': 'confirmed', - 'checkInTime': null, - }, // En route - ], - }, - ]; - - @override - void initState() { - super.initState(); - _today = DateTime.now(); - _today = DateTime(_today.year, _today.month, _today.day); - } - - List _getCalendarDays() { - final List days = []; - final startDate = _selectedDate.subtract(const Duration(days: 3)); - for (int i = 0; i < 7; i++) { - days.add(startDate.add(Duration(days: i))); - } - return days; - } - - String _formatTime(String? time) { - if (time == null) return ''; - final parts = time.split(':'); - final dt = DateTime(2022, 1, 1, int.parse(parts[0]), int.parse(parts[1])); - return DateFormat('h:mm a').format(dt); - } - - @override - Widget build(BuildContext context) { - // Process mock data for stats - final shiftsToday = _shifts; // In a real app, filter by date - final allApps = shiftsToday - .expand( - (s) => (s['workers'] as List).map((w) => {...w, 'shift_id': s['id']}), - ) - .toList(); - - final totalNeeded = shiftsToday.fold( - 0, - (sum, s) => sum + (s['workersNeeded'] as int), - ); - final confirmedApps = allApps - .where((a) => a['status'] == 'confirmed') - .toList(); - final totalConfirmed = confirmedApps.length; - final coveragePercent = totalNeeded > 0 - ? ((totalConfirmed / totalNeeded) * 100).round() - : 100; - - final lateWorkers = allApps.where((a) => a['status'] == 'late').toList(); - final onTimeWorkers = confirmedApps - .where((a) => a['checkInTime'] != null) - .toList(); - final enRouteWorkers = confirmedApps - .where((a) => a['checkInTime'] == null) - .toList(); - - final calendarDays = _getCalendarDays(); - - return Scaffold( - backgroundColor: const Color(0xFFF8FAFC), // slate-50 - body: SingleChildScrollView( - child: Column( - children: [ - // Header - Container( - padding: const EdgeInsets.only( - top: 60, - left: 20, - right: 20, - bottom: 24, - ), - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [ - Color(0xFF2563EB), // blue-600 - Color(0xFF0891B2), // cyan-600 - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.go('/client-home'), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - const Text( - 'Daily Coverage', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ], - ), - Container( - width: 36, - height: 36, - decoration: BoxDecoration( - color: Colors.transparent, - borderRadius: BorderRadius.circular(8), - ), - child: IconButton( - onPressed: () { - setState(() { - // refresh logic - }); - }, - icon: const Icon( - LucideIcons.refreshCw, - color: Colors.white, - size: 16, - ), - padding: EdgeInsets.zero, - constraints: const BoxConstraints(), - style: IconButton.styleFrom( - hoverColor: Colors.white.withOpacity(0.2), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - ), - ), - ], - ), - - const SizedBox(height: 16), - - // Calendar Selector - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _NavButton( - text: '← Prev Week', - onTap: () { - setState(() { - _selectedDate = _selectedDate.subtract( - const Duration(days: 7), - ); - }); - }, - ), - _NavButton( - text: 'Today', - onTap: () { - setState(() { - final now = DateTime.now(); - _selectedDate = DateTime( - now.year, - now.month, - now.day, - ); - }); - }, - ), - _NavButton( - text: 'Next Week →', - onTap: () { - setState(() { - _selectedDate = _selectedDate.add( - const Duration(days: 7), - ); - }); - }, - ), - ], - ), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: calendarDays.map((date) { - final isSelected = - date.year == _selectedDate.year && - date.month == _selectedDate.month && - date.day == _selectedDate.day; - final isToday = - date.year == _today.year && - date.month == _today.month && - date.day == _today.day; - - return GestureDetector( - onTap: () { - setState(() { - _selectedDate = date; - }); - }, - child: Container( - width: 44, // roughly grid-cols-7 spacing - height: 60, - decoration: BoxDecoration( - color: isSelected - ? Colors.white - : Colors.white.withOpacity(0.1), - borderRadius: BorderRadius.circular(12), - border: isToday && !isSelected - ? Border.all(color: Colors.white, width: 2) - : null, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - date.day.toString().padLeft(2, '0'), - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: isSelected - ? const Color(0xFF0A39DF) - : Colors.white, - ), - ), - Text( - DateFormat('E').format(date), - style: TextStyle( - fontSize: 9, - fontWeight: FontWeight.w500, - color: isSelected - ? const Color(0xFF6A7382) - : Colors.white.withOpacity(0.7), - ), - ), - ], - ), - ), - ); - }).toList(), - ), - ], - ), - - const SizedBox(height: 16), - - // Compact Coverage Summary - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.1), - borderRadius: BorderRadius.circular(16), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Coverage Status', - style: TextStyle( - fontSize: 12, - color: Colors.white.withOpacity(0.7), - ), - ), - Text( - '$coveragePercent%', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - 'Workers', - style: TextStyle( - fontSize: 12, - color: Colors.white.withOpacity(0.7), - ), - ), - Text( - '$totalConfirmed/$totalNeeded', - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Colors.white, - ), - ), - ], - ), - ], - ), - ), - ], - ), - ), - - // Content Body - Transform.translate( - offset: const Offset(0, -16), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - children: [ - // Quick Stats - Row( - children: [ - Expanded( - child: _QuickStatCard( - value: '${onTimeWorkers.length}', - label: 'Checked In', - valueColor: const Color(0xFF059669), // emerald-600 - ), - ), - const SizedBox(width: 12), - Expanded( - child: _QuickStatCard( - value: '${enRouteWorkers.length}', - label: 'En Route', - valueColor: const Color(0xFFD97706), // amber-600 - ), - ), - const SizedBox(width: 12), - Expanded( - child: _QuickStatCard( - value: '${lateWorkers.length}', - label: 'Late', - valueColor: const Color(0xFFDC2626), // red-600 - ), - ), - ], - ), - - // Alerts - if (lateWorkers.isNotEmpty) ...[ - const SizedBox(height: 20), - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [ - Color(0xFFFEF2F2), // red-50 - Color(0xFFFFF1F2), // rose-50 - ], - begin: Alignment.centerLeft, - end: Alignment.centerRight, - ), - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: const Color(0xFFFEE2E2), - ), // red-100 - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.02), - blurRadius: 2, - ), - ], - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Icon( - LucideIcons.alertTriangle, - color: Color(0xFFEF4444), // red-500 - size: 20, - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - '${lateWorkers.length} worker(s) running late', - style: const TextStyle( - fontWeight: FontWeight.w500, - color: Color(0xFFB91C1C), // red-700 - fontSize: 14, - ), - ), - const SizedBox(height: 4), - const Text( - 'Auto-backup system activated - finding replacements', - style: TextStyle( - fontSize: 14, - color: Color(0xFFDC2626), // red-600 - ), - ), - ], - ), - ), - ], - ), - ), - ], - - const SizedBox(height: 20), - - // Live Activity Header - const Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - 'Live Activity', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - ], - ), - const SizedBox(height: 12), - - // Shifts List - if (shiftsToday.isEmpty) - Container( - padding: const EdgeInsets.all(32), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.02), - blurRadius: 2, - ), - ], - ), - child: const Column( - children: [ - Icon( - LucideIcons.users, - size: 48, - color: Color(0xFFCBD5E1), - ), // slate-300 - SizedBox(height: 12), - Text( - 'No shifts scheduled for this day', - style: TextStyle( - color: Color(0xFF64748B), // slate-500 - ), - ), - ], - ), - ) - else - ...shiftsToday.map((shift) { - final shiftApps = (shift['workers'] as List); - final workersNeeded = shift['workersNeeded'] as int; - final coverage = workersNeeded > 0 - ? ((shiftApps.length / workersNeeded) * 100).round() - : 100; - - return Container( - margin: const EdgeInsets.only(bottom: 12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.02), - blurRadius: 2, - ), - ], - ), - clipBehavior: Clip.antiAlias, - child: Column( - children: [ - // Shift Header - Container( - padding: const EdgeInsets.all(16), - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [ - Color(0xFFEFF6FF), // blue-50 - Color(0xFFECFEFF), // cyan-50 - ], - begin: Alignment.centerLeft, - end: Alignment.centerRight, - ), - border: Border( - bottom: BorderSide( - color: Color(0xFFE2E8F0), - ), // slate-200 - ), - ), - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( - children: [ - Container( - width: 8, - height: 8, - decoration: const BoxDecoration( - color: Color( - 0xFF3B82F6, - ), // blue-500 - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 8), - Text( - shift['title'], - style: const TextStyle( - fontWeight: FontWeight.bold, - color: Color( - 0xFF0F172A, - ), // slate-900 - fontSize: 16, - ), - ), - ], - ), - const SizedBox(height: 8), - Row( - children: [ - const Icon( - LucideIcons.mapPin, - size: 12, - color: Color(0xFF475569), - ), // slate-600 - const SizedBox(width: 4), - Text( - shift['location'], - style: const TextStyle( - fontSize: 12, - color: Color( - 0xFF475569, - ), // slate-600 - ), - ), - const SizedBox(width: 12), - const Icon( - LucideIcons.clock, - size: 12, - color: Color(0xFF475569), - ), - const SizedBox(width: 4), - Text( - _formatTime( - shift['startTime'], - ), - style: const TextStyle( - fontSize: 12, - color: Color(0xFF475569), - ), - ), - ], - ), - ], - ), - ), - _CoverageBadge( - current: shiftApps.length, - total: workersNeeded, - coveragePercent: coverage, - ), - ], - ), - ), - - // Workers List - if (shiftApps.isNotEmpty) - Padding( - padding: const EdgeInsets.all(12), - child: Column( - children: shiftApps.map((worker) { - final isLast = worker == shiftApps.last; - return Padding( - padding: EdgeInsets.only( - bottom: isLast ? 0 : 8, - ), - child: _WorkerRow( - name: worker['name'], - status: worker['status'], - checkInTime: worker['checkInTime'], - formatTime: _formatTime, - shiftStartTime: _formatTime( - shift['startTime'], - ), - ), - ); - }).toList(), - ), - ) - else - const Padding( - padding: EdgeInsets.all(16), - child: Text( - 'No workers assigned yet', - style: TextStyle( - color: Color(0xFF64748B), // slate-500 - fontSize: 14, - ), - ), - ), - ], - ), - ); - }), - - const SizedBox(height: 80), // Bottom padding - ], - ), - ), - ), - ], - ), - ), - ); - } -} - -class _NavButton extends StatelessWidget { - final String text; - final VoidCallback onTap; - - const _NavButton({required this.text, required this.onTap}); - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: onTap, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(8), - ), - child: Text( - text, - style: const TextStyle(color: Colors.white, fontSize: 14), - ), - ), - ); - } -} - -class _QuickStatCard extends StatelessWidget { - final String value; - final String label; - final Color valueColor; - - const _QuickStatCard({ - required this.value, - required this.label, - required this.valueColor, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular( - 12, - ), // rounded-xl check? React uses default which is usually 0.5rem(8px) or 0.75rem(12px) for Card - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.06), // shadow-md - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - children: [ - Text( - value, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: valueColor, - ), - ), - Text( - label, - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), // slate-500 - ), - ), - ], - ), - ); - } -} - -class _CoverageBadge extends StatelessWidget { - final int current; - final int total; - final int coveragePercent; - - const _CoverageBadge({ - required this.current, - required this.total, - required this.coveragePercent, - }); - - @override - Widget build(BuildContext context) { - Color bg; - Color text; - - if (coveragePercent >= 100) { - bg = const Color(0xFF10B981); // emerald-500 - text = Colors.white; - } else if (coveragePercent >= 80) { - bg = const Color(0xFFF59E0B); // amber-500 - text = Colors.white; - } else { - bg = const Color(0xFFEF4444); // red-500 - text = Colors.white; - } - - return Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 2), - decoration: BoxDecoration( - color: bg, - borderRadius: BorderRadius.circular(100), // rounded-full - ), - child: Text( - '$current/$total', - style: TextStyle( - color: text, - fontSize: 12, - fontWeight: FontWeight.w500, - ), - ), - ); - } -} - -class _WorkerRow extends StatelessWidget { - final String name; - final String status; - final String? checkInTime; - final String Function(String?) formatTime; - final String shiftStartTime; - - const _WorkerRow({ - required this.name, - required this.status, - required this.checkInTime, - required this.formatTime, - required this.shiftStartTime, - }); - - @override - Widget build(BuildContext context) { - Color bg; - Color border; - Color textBg; - Color textColor; - IconData icon; - String statusText; - Color badgeBg; - Color badgeText; - String badgeLabel; - - if (status == 'confirmed' && checkInTime != null) { - // Checked In - bg = const Color(0xFFECFDF5); // emerald-50 - border = const Color(0xFF10B981); // emerald-500 - textBg = const Color(0xFFD1FAE5); // emerald-100 - textColor = const Color(0xFF047857); // emerald-700 - icon = LucideIcons.checkCircle; - statusText = '✓ Checked In at ${formatTime(checkInTime)}'; - badgeBg = const Color(0xFF10B981); // emerald-500 - badgeText = Colors.white; - badgeLabel = 'On Site'; - } else if (status == 'confirmed' && checkInTime == null) { - // En Route - bg = const Color(0xFFFFFBEB); // amber-50 - border = const Color(0xFFF59E0B); // amber-500 - textBg = const Color(0xFFFEF3C7); // amber-100 - textColor = const Color(0xFFB45309); // amber-700 - icon = LucideIcons.clock; - statusText = 'En Route - Expected $shiftStartTime'; - badgeBg = const Color(0xFFF59E0B); // amber-500 - badgeText = Colors.white; - badgeLabel = 'En Route'; - } else { - // Late - bg = const Color(0xFFFEF2F2); // red-50 - border = const Color(0xFFEF4444); // red-500 - textBg = const Color(0xFFFEE2E2); // red-100 - textColor = const Color(0xFFB91C1C); // red-700 - icon = LucideIcons.alertTriangle; - statusText = '⚠ Running Late'; - badgeBg = const Color(0xFFEF4444); // red-500 - badgeText = Colors.white; - badgeLabel = 'Late'; - } - - return Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: bg, - borderRadius: BorderRadius.circular(8), - ), - child: Row( - children: [ - Stack( - clipBehavior: Clip.none, - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all(color: border, width: 2), - ), - child: CircleAvatar( - backgroundColor: textBg, - child: Text( - name.isNotEmpty ? name[0] : 'W', - style: TextStyle( - color: textColor, - fontWeight: FontWeight.w600, - fontSize: 16, - ), - ), - ), - ), - Positioned( - bottom: -2, - right: -2, - child: Container( - width: 16, - height: 16, - decoration: BoxDecoration( - color: border, - shape: BoxShape.circle, - ), - child: Icon(icon, size: 10, color: Colors.white), - ), - ), - ], - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - Text( - statusText, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: textColor, - ), - ), - ], - ), - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), - decoration: BoxDecoration( - color: badgeBg, - borderRadius: BorderRadius.circular(100), // rounded-full - ), - child: Text( - badgeLabel, - style: TextStyle( - color: badgeText, - fontSize: 10, // xs - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_home_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_home_screen.dart deleted file mode 100644 index d4dc8486..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_home_screen.dart +++ /dev/null @@ -1,1958 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; -import 'coverage_dashboard.dart'; - -class ClientHomeScreen extends StatefulWidget { - const ClientHomeScreen({super.key}); - - @override - State createState() => _ClientHomeScreenState(); -} - -class _ClientHomeScreenState extends State { - bool _editMode = false; - bool _showOrderFormSheet = false; - Map? _reorderShiftData; - - // Default widget order - Matched to React DEFAULT_WIDGETS - List _widgetOrder = [ - 'actions', - 'reorder', - 'coverage', - 'spending', - 'liveActivity', - ]; - - // Widget visibility state - final Map _widgetVisibility = { - 'actions': true, - 'reorder': true, - 'coverage': true, - 'spending': true, - 'liveActivity': true, - }; - - final Map _widgetTitles = { - 'actions': 'Quick Actions', - 'reorder': 'Reorder', - 'coverage': 'Today\'s Coverage', - 'spending': 'Spending Insights', - 'liveActivity': 'Live Activity', - }; - - void _toggleWidget(String id) { - setState(() { - _widgetVisibility[id] = !(_widgetVisibility[id] ?? true); - }); - } - - void _resetLayout() { - setState(() { - _widgetOrder = ['actions', 'coverage', 'spending', 'liveActivity']; - for (var key in _widgetVisibility.keys) { - _widgetVisibility[key] = true; - } - }); - } - - void _openOrderFormSheet(Map shiftData) { - setState(() { - _reorderShiftData = shiftData; - _showOrderFormSheet = true; - }); - - showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) { - return _ShiftOrderFormSheet( - initialData: _reorderShiftData, - onSubmit: (data) { - // TODO: Handle form submission (create new shift) - Navigator.pop(context); // Close the sheet - setState(() { - _showOrderFormSheet = false; - _reorderShiftData = null; - }); - // Show a success message or refresh data - }, - ); - }, - ).whenComplete(() { - // This is called when the sheet is dismissed (e.g., by swiping down) - setState(() { - _showOrderFormSheet = false; - _reorderShiftData = null; - }); - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: SafeArea( - child: Column( - children: [ - // Header - _buildHeader(), - - // Edit Mode Banner - AnimatedContainer( - duration: const Duration(milliseconds: 300), - height: _editMode ? 76 : 0, // Adjusted height for correct padding - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: _editMode - ? Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: AppColors.krowBlue.withOpacity(0.1), - border: Border.all( - color: AppColors.krowBlue.withOpacity(0.3), - ), - borderRadius: BorderRadius.circular(12), // rounded-xl - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - const Icon( - LucideIcons.edit3, - size: 16, - color: AppColors.krowBlue, - ), - const SizedBox(width: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'Edit Mode Active', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: AppColors.krowBlue, - ), - ), - Text( - 'Drag to reorder, toggle visibility', - style: TextStyle( - fontSize: 10, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - ), - TextButton( - onPressed: _resetLayout, - style: TextButton.styleFrom( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 4, - ), - minimumSize: Size.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - backgroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - 12, - ), // rounded-xl - side: BorderSide(color: AppColors.krowBorder), - ), - ), - child: const Text( - 'Reset', - style: TextStyle( - fontSize: 12, - color: AppColors.krowCharcoal, - ), - ), - ), - ], - ), - ) - : const SizedBox.shrink(), - ), - - // Scrollable Content - Expanded( - child: _editMode - ? ReorderableListView( - padding: const EdgeInsets.only( - bottom: 100, - left: 16, - right: 16, - ), - onReorder: (oldIndex, newIndex) { - setState(() { - if (oldIndex < newIndex) { - newIndex -= 1; - } - final String item = _widgetOrder.removeAt(oldIndex); - _widgetOrder.insert(newIndex, item); - }); - }, - children: _widgetOrder.map((id) { - return Container( - key: ValueKey(id), - margin: const EdgeInsets.only(bottom: 16), - child: _buildDraggableWidgetWrapper(id), - ); - }).toList(), - ) - : ListView( - padding: const EdgeInsets.only( - bottom: 100, - left: 16, - right: 16, - ), - children: _widgetOrder.map((id) { - if (!(_widgetVisibility[id] ?? true)) { - return const SizedBox.shrink(); - } - return Padding( - padding: const EdgeInsets.only(bottom: 16), - child: _buildWidgetContent(id), - ); - }).toList(), - ), - ), - ], - ), - ), - ); - } - - Widget _buildHeader() { - return Padding( - padding: const EdgeInsets.fromLTRB(16, 16, 16, 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: AppColors.krowBlue.withOpacity(0.2), - width: 2, - ), - ), - child: CircleAvatar( - backgroundColor: AppColors.krowBlue.withOpacity(0.1), - child: const Text( - 'C', - style: TextStyle( - color: AppColors.krowBlue, - fontWeight: FontWeight.bold, - fontSize: 14, - ), - ), - ), - ), - const SizedBox(width: 10), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Welcome back', - style: TextStyle(color: AppColors.krowMuted, fontSize: 10), - ), - Text( - 'Your Company', - style: TextStyle( - color: AppColors.krowCharcoal, - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ], - ), - Row( - children: [ - GestureDetector( - onTap: () { - setState(() { - _editMode = !_editMode; - }); - }, - child: Container( - width: 32, - height: 32, - decoration: BoxDecoration( - color: _editMode ? AppColors.krowBlue : Colors.white, - borderRadius: BorderRadius.circular(8), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - ), - ], - ), - child: Icon( - LucideIcons.edit3, - color: _editMode ? Colors.white : AppColors.krowMuted, - size: 16, - ), - ), - ), - const SizedBox(width: 6), - Stack( - children: [ - Container( - width: 32, - height: 32, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - ), - ], - ), - child: const Icon( - LucideIcons.bell, - color: AppColors.krowMuted, - size: 16, - ), - ), - Positioned( - top: -2, - right: -2, - child: Container( - width: 16, - height: 16, - decoration: const BoxDecoration( - color: Color(0xFFF04444), - shape: BoxShape.circle, - ), - child: const Center( - child: Text( - '3', - style: TextStyle( - color: Colors.white, - fontSize: 9, - fontWeight: FontWeight - .w500, // Changed from FontWeight.bold to FontWeight.w500 - ), - ), - ), - ), - ), - ], - ), - const SizedBox(width: 6), - GestureDetector( - onTap: () => context.push('/client-settings'), - child: Container( - width: 32, - height: 32, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - ), - ], - ), - child: const Icon( - LucideIcons.settings, - color: AppColors.krowMuted, - size: 16, - ), - ), - ), - ], - ), - ], - ), - ); - } - - Widget _buildDraggableWidgetWrapper(String id) { - bool isVisible = _widgetVisibility[id] ?? true; - return Column( - children: [ - // Control Header - Row( - children: [ - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - ), - child: Row( - children: [ - const Icon( - LucideIcons.gripVertical, - size: 14, - color: AppColors.krowMuted, - ), - const SizedBox(width: 6), - Text( - _widgetTitles[id] ?? '', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - ), - const SizedBox(width: 8), - GestureDetector( - onTap: () => _toggleWidget(id), - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - ), - child: Icon( - isVisible ? LucideIcons.eye : LucideIcons.eyeOff, - size: 14, - color: isVisible ? AppColors.krowBlue : AppColors.krowMuted, - ), - ), - ), - ], - ), - const SizedBox(height: 8), - // Widget Content (Dimmed if hidden) - Opacity( - opacity: isVisible ? 1.0 : 0.4, - child: IgnorePointer( - ignoring: !isVisible, - child: _buildWidgetContent(id), - ), - ), - ], - ); - } - - Widget _buildWidgetContent(String id) { - switch (id) { - case 'actions': - return const _ActionsWidget(); - case 'reorder': - return _ReorderWidget(onReorderPressed: _openOrderFormSheet); - case 'spending': - return const _SpendingWidget(); - case 'coverage': - return const _CoverageWidget(); - case 'liveActivity': - return const _LiveActivityWidget(); - default: - return const SizedBox.shrink(); - } - } -} - -// --- WIDGET IMPLEMENTATIONS --- - -class _ActionsWidget extends StatelessWidget { - const _ActionsWidget(); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - child: GestureDetector( - onTap: () => context.push('/create-order/rapid'), - child: Container( - height: 100, - padding: const EdgeInsets.all(10), // p-2.5 in React is 10px - decoration: BoxDecoration( - color: const Color(0xFFFEF2F2), // red-50 - borderRadius: BorderRadius.circular(12), // rounded-xl - border: Border.all(color: const Color(0xFFFECACA)), // red-200 - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.02), - blurRadius: 4, - ), - ], - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 36, - height: 36, - decoration: BoxDecoration( - color: const Color(0xFFFEE2E2), // red-100 - borderRadius: BorderRadius.circular(12), // rounded-xl - ), - child: const Icon( - LucideIcons.zap, // Zap - color: Color(0xFFDC2626), // text-red-600 - size: 16, // w-4 h-4 - ), - ), - const SizedBox(height: 6), // gap-1.5 in React is 6px - const Text( - 'RAPID', - style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.bold, - color: Color(0xFF7F1D1D), // red-900 - ), - ), - const Text( - 'Urgent same-day', - style: TextStyle( - fontSize: 8, - color: Color(0xFFB91C1C), // red-700 - ), - ), - ], - ), - ), - ), - ), - const SizedBox(width: 8), - Expanded( - child: GestureDetector( - onTap: () => context.push('/create-order'), - child: Container( - height: 100, - padding: const EdgeInsets.all(10), // p-2.5 in React is 10px - decoration: BoxDecoration( - color: Colors.white, // bg-white - borderRadius: BorderRadius.circular(12), // rounded-xl - border: Border.all( - color: const Color(0xFFE2E8F0), - ), // border border-slate-200 - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.02), - blurRadius: 4, - ), - ], - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 36, - height: 36, - decoration: BoxDecoration( - color: const Color(0xFFEFF6FF), // bg-blue-50 - borderRadius: BorderRadius.circular(12), // rounded-xl - ), - child: const Icon( - LucideIcons.plus, // Plus - color: Color(0xFF2563EB), // text-blue-600 - size: 16, - ), - ), - const SizedBox(height: 6), // gap-1.5 in React is 6px - const Text( - 'Create Order', - style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), // slate-900 - ), - ), - const Text( - 'Schedule shifts', - style: TextStyle( - fontSize: 8, - color: Color(0xFF475569), // slate-600 - ), - ), - ], - ), - ), - ), - ), - ], - ); - } -} - -class _ReorderWidget extends StatelessWidget { - final Function(Map shiftData) onReorderPressed; - - const _ReorderWidget({required this.onReorderPressed}); - - @override - Widget build(BuildContext context) { - // Mock recent orders - final recentOrders = [ - { - 'title': 'Server', - 'location': 'Downtown Restaurant', - 'hourlyRate': 18.0, - 'hours': 6, - 'workers': 3, - 'type': 'One Day', - 'startTime': '17:00', - 'endTime': '23:00', - 'locationAddress': '123 Main St, City', - }, - { - 'title': 'Bartender', - 'location': 'Rooftop Bar', - 'hourlyRate': 22.0, - 'hours': 7, - 'workers': 2, - 'type': 'One Day', - 'startTime': '19:00', - 'endTime': '02:00', - 'locationAddress': '456 High St, City', - }, - { - 'title': 'Event Staff', - 'location': 'Convention Center', - 'hourlyRate': 20.0, - 'hours': 10, - 'workers': 5, - 'type': 'Multi-Day', - 'startTime': '08:00', - 'endTime': '18:00', - 'locationAddress': '789 Event Blvd, City', - }, - ]; - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'REORDER', - style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - letterSpacing: 0.5, - ), - ), - const SizedBox(height: 8), - SizedBox( - height: 140, - child: ListView.separated( - scrollDirection: Axis.horizontal, - itemCount: recentOrders.length, - separatorBuilder: (context, index) => const SizedBox(width: 12), - itemBuilder: (context, index) { - final order = recentOrders[index]; - final totalCost = - (order['hourlyRate'] as double) * - (order['hours'] as int) * - (order['workers'] as int); - - return Container( - width: 260, - padding: const EdgeInsets.all(10), // p-2.5 in React is 10px - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.02), - blurRadius: 4, - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Row( - children: [ - Container( - width: 36, - height: 36, - decoration: BoxDecoration( - color: AppColors.krowBlue.withOpacity(0.1), - borderRadius: BorderRadius.circular( - 12, - ), // rounded-xl - ), - child: const Icon( - LucideIcons.briefcase, - size: 16, - color: AppColors.krowBlue, - ), - ), - const SizedBox(width: 8), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - order['title'] as String, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - overflow: TextOverflow.ellipsis, - ), - Text( - order['location'] as String, - style: const TextStyle( - fontSize: 10, - color: AppColors.krowMuted, - ), - overflow: TextOverflow.ellipsis, - ), - ], - ), - ), - ], - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - '\$${totalCost.toStringAsFixed(0)}', - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Text( - '\$${order['hourlyRate']}/hr · ${order['hours']}h', - style: const TextStyle( - fontSize: 9, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - ), - const SizedBox(height: 10), - Row( - children: [ - _Badge( - icon: LucideIcons.calendar, - text: order['type'] as String, - color: const Color(0xFF2563EB), // blue-600 - bg: const Color(0xFF2563EB), - textColor: Colors.white, - ), - const SizedBox(width: 6), - _Badge( - icon: LucideIcons.users, - text: '${order['workers']}', - color: const Color(0xFF334155), // slate-700 - bg: const Color(0xFFF1F5F9), // slate-100 - textColor: const Color(0xFF334155), - ), - ], - ), - const Spacer(), - SizedBox( - height: 28, - width: double.infinity, - child: ElevatedButton.icon( - onPressed: () { - onReorderPressed(order); - }, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - padding: EdgeInsets.zero, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - elevation: 0, - ), - icon: const Icon(LucideIcons.rotateCcw, size: 12), - label: const Text( - 'Reorder', - style: TextStyle(fontSize: 12), - ), - ), - ), - ], - ), - ); - }, - ), - ), - ], - ); - } -} - -class _Badge extends StatelessWidget { - final IconData icon; - final String text; - final Color color; - final Color bg; - final Color textColor; - - const _Badge({ - required this.icon, - required this.text, - required this.color, - required this.bg, - required this.textColor, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - decoration: BoxDecoration( - color: bg == textColor ? bg : bg, - borderRadius: BorderRadius.circular(4), - ), - child: Row( - children: [ - Icon(icon, size: 10, color: bg == textColor ? Colors.white : color), - const SizedBox(width: 4), - Text( - text, - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: textColor, - ), - ), - ], - ), - ); - } -} - -class _SpendingWidget extends StatelessWidget { - const _SpendingWidget(); - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'SPENDING INSIGHTS', - style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - letterSpacing: 0.5, - ), - ), - const SizedBox(height: 8), - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [AppColors.krowBlue, Color(0xFF0830B8)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: AppColors.krowBlue.withOpacity(0.3), - blurRadius: 4, // shadow-md -> 4 - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - children: [ - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'This Week', - style: TextStyle(color: Colors.white70, fontSize: 9), - ), - const SizedBox(height: 4), // mb-1 -> 4 - const Text( - '\$4,250', - style: TextStyle( - color: Colors.white, - fontSize: 24, // text-2xl (24) - fontWeight: FontWeight.bold, - ), - ), - Text( - '12 shifts', - style: TextStyle( - color: Colors.white.withOpacity(0.6), - fontSize: 9, - ), - ), - ], - ), - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - const Text( - 'Next 7 Days', - style: TextStyle(color: Colors.white70, fontSize: 9), - ), - const SizedBox(height: 4), // mb-1 -> 4 - const Text( - '\$6,100', - style: TextStyle( - color: Colors.white, - fontSize: 20, // text-xl (20) - fontWeight: FontWeight.bold, - ), - ), - Text( - '18 scheduled', - style: TextStyle( - color: Colors.white.withOpacity(0.6), - fontSize: 9, - ), - ), - ], - ), - ), - ], - ), - const SizedBox(height: 12), - Container( - padding: const EdgeInsets.only(top: 12), - decoration: const BoxDecoration( - border: Border(top: BorderSide(color: Colors.white24)), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 24, - height: 24, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Center( - child: Icon( - LucideIcons.trendingDown, - color: Colors.white, - size: 14, - ), - ), - ), - const SizedBox(width: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - '💡 Save \$180/month', - style: TextStyle( - color: Colors.white, - fontSize: 10, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 2), // mb-0.5 -> 2 - Text( - 'Book 48hrs ahead for better rates', - style: TextStyle( - color: Colors.white.withOpacity(0.8), - fontSize: 9, - ), - ), - ], - ), - ], - ), - ), - ], - ), - ), - ], - ); - } -} - -class _CoverageWidget extends StatelessWidget { - const _CoverageWidget(); - - @override - Widget build(BuildContext context) { - const totalNeeded = 10; - const totalConfirmed = 8; - const coveragePercent = 80; - - return Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'TODAY\'S COVERAGE', - style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - letterSpacing: 0.5, - ), - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), - decoration: BoxDecoration( - color: const Color(0xFFD1FAE5), // emerald-100 - borderRadius: BorderRadius.circular(12), // rounded-xl - ), - child: const Text( - '$coveragePercent% Covered', - style: TextStyle( - fontSize: 9, - fontWeight: FontWeight.bold, - color: Color(0xFF047857), // emerald-700 - ), - ), - ), - ], - ), - const SizedBox(height: 8), - Row( - children: [ - Expanded( - child: _MetricCard( - icon: LucideIcons.target, - iconColor: AppColors.krowBlue, - label: 'Needed', - value: '$totalNeeded', - ), - ), - const SizedBox(width: 8), - Expanded( - child: _MetricCard( - icon: LucideIcons.checkCircle2, - iconColor: const Color(0xFF059669), // emerald-600 - label: 'Filled', - value: '$totalConfirmed', - valueColor: const Color(0xFF059669), // emerald-600 - ), - ), - const SizedBox(width: 8), - Expanded( - child: _MetricCard( - icon: LucideIcons.alertCircle, - iconColor: const Color(0xFFDC2626), // red-600 - label: 'Open', - value: '${totalNeeded - totalConfirmed}', - valueColor: const Color(0xFFDC2626), // red-600 - ), - ), - ], - ), - ], - ); - } -} - -class _MetricCard extends StatelessWidget { - final IconData icon; - final Color iconColor; - final String label; - final String value; - final Color? valueColor; - - const _MetricCard({ - required this.icon, - required this.iconColor, - required this.label, - required this.value, - this.valueColor, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 2), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon(icon, size: 14, color: iconColor), - const SizedBox(width: 6), - Text( - label, - style: const TextStyle( - fontSize: 9, - color: AppColors.krowMuted, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - const SizedBox(height: 6), - Text( - value, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: valueColor ?? AppColors.krowCharcoal, - ), - ), - ], - ), - ); - } -} - -class _LiveActivityWidget extends StatelessWidget { - const _LiveActivityWidget(); - - @override - Widget build(BuildContext context) { - // Mock data for CoverageDashboard - final shifts = [ - { - 'workersNeeded': 5, - 'filled': 4, - 'hourlyRate': 20.0, - 'status': 'OPEN', - 'date': DateTime.now().toIso8601String().split('T')[0], - }, - { - 'workersNeeded': 5, - 'filled': 5, - 'hourlyRate': 22.0, - 'status': 'FILLED', - 'date': DateTime.now().toIso8601String().split('T')[0], - }, - ]; - final applications = [ - {'status': 'CONFIRMED', 'checkInTime': '09:00'}, - {'status': 'CONFIRMED', 'checkInTime': '09:05'}, - {'status': 'CONFIRMED'}, // not checked in - {'status': 'LATE'}, // late - ]; - - return Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'LIVE ACTIVITY', - style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - letterSpacing: 0.5, - ), - ), - GestureDetector( - onTap: () => context.push('/client-coverage'), - child: const Text( - 'View all', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w500, - color: AppColors.krowBlue, - ), - ), - ), - ], - ), - const SizedBox(height: 8), - CoverageDashboard(shifts: shifts, applications: applications), - ], - ); - } -} - -class _ShiftOrderFormSheet extends StatefulWidget { - final Map? initialData; - final Function(Map data) onSubmit; - final bool isLoading; - - const _ShiftOrderFormSheet({ - super.key, - this.initialData, - required this.onSubmit, - this.isLoading = false, - }); - - @override - State<_ShiftOrderFormSheet> createState() => _ShiftOrderFormSheetState(); -} - -class _ShiftOrderFormSheetState extends State<_ShiftOrderFormSheet> { - late Map _formData; - final List _roles = [ - 'Server', - 'Bartender', - 'Busser', - 'Cook', - 'Dishwasher', - 'Event Staff', - 'Warehouse Worker', - 'Retail Associate', - 'Host/Hostess', - ]; - - @override - void initState() { - super.initState(); - final defaultPosition = { - 'title': '', - 'start_time': '', - 'end_time': '', - 'workers_needed': 1, - 'hourly_rate': 18.0, - }; - - final defaults = { - 'date': '', - 'location': '', - 'recurring': false, - 'duration_days': null, - 'permanent': false, - 'duration_months': null, - 'positions': [Map.from(defaultPosition)], - }; - - if (widget.initialData != null) { - final input = widget.initialData!; - // Map keys from recentOrders to form fields - final firstPosition = { - ...defaultPosition, - 'title': input['title'] ?? input['role'] ?? '', - 'start_time': input['startTime'] ?? input['start_time'] ?? '', - 'end_time': input['endTime'] ?? input['end_time'] ?? '', - 'hourly_rate': (input['hourlyRate'] ?? input['hourly_rate'] ?? 18.0) - .toDouble(), - 'workers_needed': (input['workers'] ?? input['workers_needed'] ?? 1) - .toInt(), - }; - - _formData = { - ...defaults, - ...input, - 'positions': [firstPosition], - }; - } else { - _formData = Map.from(defaults); - } - - // Pre-fill date with tomorrow if reordering and date is empty - if (_formData['date'] == null || _formData['date'] == '') { - final tomorrow = DateTime.now().add(const Duration(days: 1)); - _formData['date'] = tomorrow.toIso8601String().split('T')[0]; - } - } - - void _updateField(String field, dynamic value) { - setState(() { - _formData[field] = value; - }); - } - - void _updatePositionField(int index, String field, dynamic value) { - setState(() { - _formData['positions'][index][field] = value; - }); - } - - void _addPosition() { - setState(() { - _formData['positions'].add({ - 'title': '', - 'start_time': '', - 'end_time': '', - 'workers_needed': 1, - 'hourly_rate': 18.0, - }); - }); - } - - void _removePosition(int index) { - if (_formData['positions'].length > 1) { - setState(() { - _formData['positions'].removeAt(index); - }); - } - } - - String _getShiftType() { - if (_formData['permanent'] == true || - _formData['duration_months'] != null) { - return 'Long Term'; - } - if (_formData['recurring'] == true || _formData['duration_days'] != null) { - return 'Multi-Day'; - } - return 'One Day'; - } - - @override - Widget build(BuildContext context) { - return Container( - height: MediaQuery.of(context).size.height * 0.9, - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.vertical(top: Radius.circular(24)), - ), - child: Column( - children: [ - Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - border: Border(bottom: BorderSide(color: Colors.grey.shade200)), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - widget.initialData != null - ? 'Edit & Reorder' - : 'Post a New Shift', - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - IconButton( - icon: const Icon(LucideIcons.x, color: AppColors.krowMuted), - onPressed: () => Navigator.pop(context), - ), - ], - ), - ), - if (widget.initialData != null) - Padding( - padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20), - child: Text( - 'Review and edit the details before posting', - style: TextStyle(fontSize: 14, color: Colors.grey.shade600), - ), - ), - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Shift Type Badge - Container( - margin: const EdgeInsets.only(bottom: 20), - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 6, - ), - decoration: BoxDecoration( - color: const Color(0xFFEFF6FF), // blue-50 - borderRadius: BorderRadius.circular(999), // rounded-full - border: Border.all( - color: const Color(0xFFBFDBFE), - ), // blue-200 - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 8, - height: 8, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: const Color(0xFF3B82F6), // blue-500 - ), - ), - const SizedBox(width: 8), - Text( - _getShiftType(), - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, // font-semibold - color: Color(0xFF1D4ED8), // blue-700 - ), - ), - ], - ), - ), - - // Date - _buildLabel('Date *'), - _buildInputField( - key: ValueKey('date_${_formData['date']}'), - hintText: 'mm/dd/yyyy', - icon: LucideIcons.calendar, - initialValue: _formData['date'], - onTap: () async { - final selectedDate = await showDatePicker( - context: context, - initialDate: - _formData['date'] != null && - _formData['date'].isNotEmpty - ? DateTime.parse(_formData['date']) - : DateTime.now(), - firstDate: DateTime.now(), - lastDate: DateTime.now().add( - const Duration(days: 365 * 5), - ), - ); - if (selectedDate != null) { - _updateField( - 'date', - selectedDate.toIso8601String().split('T')[0], - ); - } - }, - readOnly: true, - ), - const SizedBox(height: 20), - - // Location - _buildLabel('Location *'), - _buildInputField( - hintText: 'Business address', - icon: LucideIcons.mapPin, - initialValue: _formData['location'], - onChanged: (value) => _updateField('location', value), - ), - const SizedBox(height: 20), - - // Positions Section - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Positions', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - TextButton.icon( - onPressed: _addPosition, - icon: const Icon(LucideIcons.plus, size: 16), - label: const Text('Add Position'), - style: TextButton.styleFrom( - foregroundColor: const Color(0xFF2563EB), // blue-600 - textStyle: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - ), - padding: EdgeInsets.zero, - minimumSize: Size.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - ), - ], - ), - const SizedBox(height: 16), - - // Position Cards - ...(_formData['positions'] as List).asMap().entries.map(( - entry, - ) { - final index = entry.key; - final position = entry.value; - return Padding( - padding: const EdgeInsets.only(bottom: 20), - child: Card( - elevation: 0, - margin: EdgeInsets.zero, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - side: BorderSide(color: Colors.grey.shade200), - ), - color: Colors.grey.shade50, - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - width: 36, - height: 36, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: const Color( - 0xFF2563EB, - ), // blue-600 - ), - child: Center( - child: Text( - '${index + 1}', - style: const TextStyle( - color: Colors.white, - fontSize: 14, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - const SizedBox(width: 10), - Text( - 'Position ${index + 1}', - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF334155), // slate-700 - ), - ), - ], - ), - if (_formData['positions'].length > 1) - IconButton( - icon: const Icon( - LucideIcons.trash2, - size: 18, - color: Colors.red, - ), - onPressed: () => _removePosition(index), - ), - ], - ), - const SizedBox(height: 20), - - // Role Selection - _buildLabel('Role *', isSmall: true), - DropdownButtonFormField( - value: position['title'].isEmpty - ? null - : position['title'], - hint: const Text('Select role'), - items: _roles.map((role) { - return DropdownMenuItem( - value: role, - child: Text(role), - ); - }).toList(), - onChanged: (value) => - _updatePositionField(index, 'title', value), - icon: const Icon( - LucideIcons.chevronDown, - size: 16, - color: Color(0xFF94A3B8), // slate-400 - ), - decoration: _buildDropdownInputDecoration(), - ), - const SizedBox(height: 20), - - // Time - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - _buildLabel( - 'Start Time *', - isSmall: true, - icon: LucideIcons.clock, - ), - _buildInputField( - key: ValueKey( - 'start_time_${index}_${position['start_time']}', - ), - hintText: 'HH:MM', - initialValue: position['start_time'], - onTap: () async { - final selectedTime = - await showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ); - if (selectedTime != null) { - _updatePositionField( - index, - 'start_time', - '${selectedTime.hour.toString().padLeft(2, '0')}:${selectedTime.minute.toString().padLeft(2, '0')}', - ); - } - }, - readOnly: true, - ), - ], - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - _buildLabel( - 'End Time *', - isSmall: true, - icon: LucideIcons.clock, - ), - _buildInputField( - key: ValueKey( - 'end_time_${index}_${position['end_time']}', - ), - hintText: 'HH:MM', - initialValue: position['end_time'], - onTap: () async { - final selectedTime = - await showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ); - if (selectedTime != null) { - _updatePositionField( - index, - 'end_time', - '${selectedTime.hour.toString().padLeft(2, '0')}:${selectedTime.minute.toString().padLeft(2, '0')}', - ); - } - }, - readOnly: true, - ), - ], - ), - ), - ], - ), - const SizedBox(height: 20), - - // Workers Needed - _buildLabel('Number of Workers', isSmall: true), - Row( - children: [ - _buildWorkerCountButton( - icon: LucideIcons.minus, - onPressed: () { - if (position['workers_needed'] > 1) { - _updatePositionField( - index, - 'workers_needed', - position['workers_needed'] - 1, - ); - } - }, - ), - const SizedBox(width: 8), - Expanded( - child: Container( - height: 44, // h-11 - decoration: BoxDecoration( - border: Border.all( - color: Colors.grey.shade300, - ), - borderRadius: BorderRadius.circular( - 8, - ), // rounded-lg - color: Colors.white, - ), - child: Center( - child: Text( - '${position['workers_needed']}', - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ), - ), - ), - const SizedBox(width: 8), - _buildWorkerCountButton( - icon: LucideIcons.plus, - onPressed: () { - _updatePositionField( - index, - 'workers_needed', - position['workers_needed'] + 1, - ); - }, - ), - ], - ), - const SizedBox(height: 20), - - // Lunch Break - _buildLabel('Lunch Break', isSmall: true), - DropdownButtonFormField( - value: '30', // Default value - items: const [ - DropdownMenuItem( - value: '0', - child: Text('None'), - ), - DropdownMenuItem( - value: '30', - child: Text('30 min (Unpaid)'), - ), - DropdownMenuItem( - value: '60', - child: Text('60 min (Unpaid)'), - ), - ], - onChanged: (value) { - // TODO: Handle lunch break selection - }, - icon: const Icon( - LucideIcons.chevronDown, - size: 16, - color: Color(0xFF94A3B8), // slate-400 - ), - decoration: _buildDropdownInputDecoration(), - ), - const SizedBox(height: 20), - - // Different Location Option - TextButton.icon( - onPressed: () { - // TODO: Implement different location - }, - icon: const Icon(LucideIcons.mapPin, size: 14), - label: const Text( - 'Use different location for this position', - ), - style: TextButton.styleFrom( - foregroundColor: const Color( - 0xFF2563EB, - ), // blue-600 - textStyle: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - ), - padding: EdgeInsets.zero, - minimumSize: Size.zero, - tapTargetSize: - MaterialTapTargetSize.shrinkWrap, - ), - ), - ], - ), - ), - ), - ); - }).toList(), - const SizedBox(height: 20), - ], - ), - ), - ), - SafeArea( - top: false, - child: Padding( - padding: const EdgeInsets.all(20), - child: ElevatedButton( - onPressed: - (_formData['date']?.isNotEmpty == true && - _formData['location']?.isNotEmpty == true && - (_formData['positions'] as List).every( - (p) => - p['title']?.isNotEmpty == true && - p['start_time']?.isNotEmpty == true && - p['end_time']?.isNotEmpty == true, - )) - ? () => widget.onSubmit(_formData) - : null, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF2563EB), // blue-600 - foregroundColor: Colors.white, - minimumSize: const Size(double.infinity, 48), // h-12 - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), // rounded-xl - ), - elevation: 0, - textStyle: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, // font-semibold - ), - ), - child: widget.isLoading - ? const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation( - Colors.white, - ), - ), - ) - : const Text('Post Shift'), - ), - ), - ), - ], - ), - ); - } - - Widget _buildWorkerCountButton({ - required IconData icon, - required VoidCallback onPressed, - }) { - return SizedBox( - width: 44, // w-11 - height: 44, // h-11 - child: OutlinedButton( - onPressed: onPressed, - style: OutlinedButton.styleFrom( - padding: EdgeInsets.zero, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), // rounded-lg - ), - side: BorderSide(color: Colors.grey.shade300), - foregroundColor: AppColors.krowCharcoal, - backgroundColor: Colors.white, - elevation: 0, - textStyle: const TextStyle(fontSize: 18, fontWeight: FontWeight.w500), - ), - child: Icon(icon, size: 20), - ), - ); - } - - Widget _buildLabel(String text, {bool isSmall = false, IconData? icon}) { - return Padding( - padding: const EdgeInsets.only(bottom: 6), - child: Row( - children: [ - if (icon != null) ...[ - Icon(icon, size: 14, color: AppColors.krowCharcoal), - const SizedBox(width: 4), - ], - Text( - text, - style: TextStyle( - fontSize: isSmall ? 12 : 14, - fontWeight: isSmall - ? FontWeight.w500 - : FontWeight.w600, // font-medium vs font-semibold - color: AppColors.krowCharcoal, - ), - ), - ], - ), - ); - } - - InputDecoration _buildInputDecoration({String? hintText, IconData? icon}) { - return InputDecoration( - hintText: hintText, - hintStyle: const TextStyle(color: Color(0xFF94A3B8)), // slate-400 - filled: true, - fillColor: Colors.white, - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - prefixIcon: icon != null - ? Icon(icon, size: 16, color: const Color(0xFF94A3B8)) - : null, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), // rounded-xl - borderSide: const BorderSide(color: Color(0xFFCBD5E1)), // slate-300 - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), // rounded-xl - borderSide: const BorderSide(color: Color(0xFFCBD5E1)), // slate-300 - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), // rounded-xl - borderSide: const BorderSide( - color: Color(0xFF2563EB), - width: 2, - ), // blue-600 - ), - errorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: Colors.red, width: 2), - ), - focusedErrorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: Colors.red, width: 2), - ), - ); - } - - InputDecoration _buildDropdownInputDecoration() { - return InputDecoration( - filled: true, - fillColor: Colors.white, - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), // rounded-xl - borderSide: const BorderSide(color: Color(0xFFCBD5E1)), // slate-300 - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), // rounded-xl - borderSide: const BorderSide(color: Color(0xFFCBD5E1)), // slate-300 - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), // rounded-xl - borderSide: const BorderSide( - color: Color(0xFF2563EB), - width: 2, - ), // blue-600 - ), - ); - } - - Widget _buildInputField({ - Key? key, - String? hintText, - IconData? icon, - String? initialValue, - ValueChanged? onChanged, - GestureTapCallback? onTap, - bool readOnly = false, - }) { - return TextFormField( - key: key, - initialValue: initialValue, - readOnly: readOnly, - onTap: onTap, - onChanged: onChanged, - style: const TextStyle(fontSize: 14, color: AppColors.krowCharcoal), - decoration: _buildInputDecoration(hintText: hintText, icon: icon) - .copyWith( - // Ensure height is consistent h-11 - constraints: const BoxConstraints(minHeight: 44), - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_hubs_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_hubs_screen.dart deleted file mode 100644 index fd826473..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_hubs_screen.dart +++ /dev/null @@ -1,753 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; - -class ClientHubsScreen extends StatefulWidget { - const ClientHubsScreen({super.key}); - - @override - State createState() => _ClientHubsScreenState(); -} - -class _ClientHubsScreenState extends State { - // Mock Data - final List> _hubs = []; - bool _showAddHub = false; - bool _showIdentifyNFC = false; - Map? _selectedHub; - String? _nfcTagId; - - final _nameController = TextEditingController(); - final _locationNameController = TextEditingController(); - final _addressController = TextEditingController(); - - void _addHub() { - if (_nameController.text.isEmpty) return; - setState(() { - _hubs.add({ - 'id': DateTime.now().millisecondsSinceEpoch.toString(), - 'name': _nameController.text, - 'locationName': _locationNameController.text, - 'address': _addressController.text, - 'nfcTagId': null, - }); - _nameController.clear(); - _locationNameController.clear(); - _addressController.clear(); - _showAddHub = false; - }); - } - - void _deleteHub(String id) { - setState(() { - _hubs.removeWhere((hub) => hub['id'] == id); - }); - } - - void _simulateNFCScan() { - setState(() { - _nfcTagId = - 'NFC-${DateTime.now().millisecondsSinceEpoch.toString().substring(8).toUpperCase()}'; - }); - } - - void _assignTag() { - if (_selectedHub != null && _nfcTagId != null) { - setState(() { - final index = _hubs.indexWhere((h) => h['id'] == _selectedHub!['id']); - if (index != -1) { - _hubs[index]['nfcTagId'] = _nfcTagId; - } - _showIdentifyNFC = false; - _nfcTagId = null; - _selectedHub = null; - }); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFF8FAFC), // slate-50 - body: Stack( - children: [ - CustomScrollView( - slivers: [ - SliverAppBar( - backgroundColor: const Color(0xFF121826), - automaticallyImplyLeading: false, - expandedHeight: 140, - pinned: true, - flexibleSpace: FlexibleSpaceBar( - background: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [Color(0xFF121826), Color(0xFF1E293B)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - padding: const EdgeInsets.fromLTRB(20, 48, 20, 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 20, - ), - ), - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Hubs', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 24, - ), - ), - Text( - 'Manage clock-in locations', - style: TextStyle( - color: Color(0xFFCBD5E1), // slate-300 - fontSize: 14, - ), - ), - ], - ), - ElevatedButton.icon( - onPressed: () => - setState(() => _showAddHub = true), - icon: const Icon( - LucideIcons.plus, - size: 16, - color: Color(0xFF121826), - ), - label: const Text( - 'Add Hub', - style: TextStyle( - color: Color(0xFF121826), - fontWeight: FontWeight.bold, - fontSize: 13, - ), - ), - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFFFFED4A), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 4, - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - ), - ), - ], - ), - ], - ), - ), - ), - ), - - SliverPadding( - padding: const EdgeInsets.fromLTRB(20, 20, 20, 100), - sliver: SliverList( - delegate: SliverChildListDelegate([ - const SizedBox(height: 12), - ..._hubs.map((hub) => _buildHubCard(hub)), - - if (_hubs.isEmpty) _buildEmptyState(), - - const SizedBox(height: 20), - _buildInfoCard(), - ]), - ), - ), - ], - ), - - if (_showAddHub) _buildAddHubDialog(), - - if (_showIdentifyNFC) _buildIdentifyNFCDialog(), - ], - ), - ); - } - - Widget _buildHubCard(Map hub) { - final bool hasNfc = hub['nfcTagId'] != null; - return Container( - margin: const EdgeInsets.only(bottom: 12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.04), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Container( - width: 52, - height: 52, - decoration: BoxDecoration( - color: const Color(0xFFEFF6FF), // blue-50 - borderRadius: BorderRadius.circular(16), - ), - child: Icon( - hasNfc ? LucideIcons.checkCircle : LucideIcons.nfc, - color: hasNfc - ? const Color(0xFF16A34A) - : const Color(0xFF94A3B8), // green-600 or slate-400 - size: 24, - ), - ), - const SizedBox(width: 16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - hub['name'], - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16, - color: Color(0xFF0F172A), - ), - ), - if (hub['locationName'].isNotEmpty) - Text( - hub['locationName'], - style: const TextStyle( - color: Color(0xFF64748B), - fontSize: 12, - ), - ), - if (hub['address'].isNotEmpty) - Padding( - padding: const EdgeInsets.only(top: 4), - child: Row( - children: [ - const Icon( - LucideIcons.mapPin, - size: 12, - color: Color(0xFF94A3B8), - ), - const SizedBox(width: 4), - Expanded( - child: Text( - hub['address'], - style: const TextStyle( - color: Color(0xFF64748B), - fontSize: 12, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ), - if (hasNfc) - Padding( - padding: const EdgeInsets.only(top: 4), - child: Text( - 'Tag: ${hub['nfcTagId']}', - style: const TextStyle( - color: Color(0xFF16A34A), - fontSize: 12, - fontFamily: 'monospace', - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - ), - Row( - children: [ - IconButton( - onPressed: () { - setState(() { - _selectedHub = hub; - _showIdentifyNFC = true; - }); - }, - icon: const Icon( - LucideIcons.nfc, - color: Color(0xFF2563EB), - size: 20, - ), - padding: EdgeInsets.zero, - constraints: const BoxConstraints(), - splashRadius: 20, - ), - const SizedBox(width: 8), - IconButton( - onPressed: () => _deleteHub(hub['id']), - icon: const Icon( - LucideIcons.trash2, - color: Color(0xFFDC2626), - size: 20, - ), // red-600 - padding: EdgeInsets.zero, - constraints: const BoxConstraints(), - splashRadius: 20, - ), - ], - ), - ], - ), - ), - ); - } - - Widget _buildEmptyState() { - return Container( - padding: const EdgeInsets.all(32), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.04), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - children: [ - Container( - width: 64, - height: 64, - decoration: const BoxDecoration( - color: Color(0xFFF1F5F9), // slate-100 - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.nfc, - size: 32, - color: Color(0xFF94A3B8), - ), - ), - const SizedBox(height: 16), - const Text( - 'No hubs yet', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 8), - const Text( - 'Create clock-in stations for your locations', - textAlign: TextAlign.center, - style: TextStyle(color: Color(0xFF64748B), fontSize: 14), - ), - const SizedBox(height: 24), - ElevatedButton.icon( - onPressed: () => setState(() => _showAddHub = true), - icon: const Icon( - LucideIcons.plus, - size: 16, - color: Color(0xFF121826), - ), - label: const Text( - 'Add Your First Hub', - style: TextStyle( - color: Color(0xFF121826), - fontWeight: FontWeight.bold, - ), - ), - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFFFFED4A), - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 14), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), - elevation: 4, - ), - ), - ], - ), - ); - } - - Widget _buildInfoCard() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFFEFF6FF), // blue-50 - borderRadius: BorderRadius.circular(16), - ), - child: const Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon(LucideIcons.nfc, size: 20, color: Color(0xFF2563EB)), - SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'About Hubs', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: Color(0xFF0F172A), - ), - ), - SizedBox(height: 4), - Text( - 'Hubs are clock-in stations at your locations. Assign NFC tags to each hub so workers can quickly clock in/out using their phones.', - style: TextStyle( - color: Color(0xFF334155), - fontSize: 12, - height: 1.4, - ), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildAddHubDialog() { - return Container( - color: Colors.black.withOpacity(0.5), - child: Center( - child: Container( - width: MediaQuery.of(context).size.width * 0.9, - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(24), - boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.1), blurRadius: 20), - ], - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Text( - 'Add New Hub', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 24), - _buildFieldLabel('Hub Name *'), - TextField( - controller: _nameController, - decoration: _buildInputDecoration( - 'e.g., Main Kitchen, Front Desk', - ), - ), - const SizedBox(height: 16), - _buildFieldLabel('Location Name'), - TextField( - controller: _locationNameController, - decoration: _buildInputDecoration('e.g., Downtown Restaurant'), - ), - const SizedBox(height: 16), - _buildFieldLabel('Address'), - TextField( - controller: _addressController, - decoration: _buildInputDecoration('Full address'), - ), - const SizedBox(height: 32), - Row( - children: [ - Expanded( - child: OutlinedButton( - onPressed: () => setState(() => _showAddHub = false), - style: OutlinedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 14), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - side: const BorderSide(color: Color(0xFFE2E8F0)), - ), - child: const Text( - 'Cancel', - style: TextStyle(color: Color(0xFF64748B)), - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: ElevatedButton( - onPressed: _addHub, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFFFFED4A), - foregroundColor: const Color(0xFF121826), - padding: const EdgeInsets.symmetric(vertical: 14), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: const Text( - 'Create Hub', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - ], - ), - ], - ), - ), - ), - ); - } - - Widget _buildIdentifyNFCDialog() { - return Container( - color: Colors.black.withOpacity(0.5), - child: Center( - child: Container( - width: MediaQuery.of(context).size.width * 0.9, - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(24), - boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.1), blurRadius: 20), - ], - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Text( - 'Identify NFC Tag', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 32), - Container( - width: 80, - height: 80, - decoration: const BoxDecoration( - color: Color(0xFFEFF6FF), // blue-50 - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.nfc, - size: 40, - color: Color(0xFF2563EB), - ), - ), - const SizedBox(height: 16), - Text( - _selectedHub?['name'] ?? '', - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 8), - const Text( - 'Tap your phone to the NFC tag to identify it', - textAlign: TextAlign.center, - style: TextStyle(color: Color(0xFF64748B), fontSize: 14), - ), - const SizedBox(height: 24), - ElevatedButton.icon( - onPressed: _simulateNFCScan, - icon: const Icon(LucideIcons.nfc, size: 20), - label: const Text( - 'Scan NFC Tag', - style: TextStyle(fontWeight: FontWeight.bold), - ), - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0047FF), - foregroundColor: Colors.white, - padding: const EdgeInsets.symmetric( - horizontal: 24, - vertical: 14, - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), - elevation: 4, - ), - ), - if (_nfcTagId != null) ...[ - const SizedBox(height: 24), - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFFF0FDF4), // green-50 - borderRadius: BorderRadius.circular(16), - ), - child: Column( - children: [ - const Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - LucideIcons.checkCircle, - size: 20, - color: Color(0xFF16A34A), - ), - SizedBox(width: 8), - Text( - 'Tag Identified', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: Color(0xFF0F172A), - ), - ), - ], - ), - const SizedBox(height: 8), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: const Color(0xFFDCE8E0)), - ), - child: Text( - _nfcTagId!, - style: const TextStyle( - fontFamily: 'monospace', - fontWeight: FontWeight.bold, - fontSize: 12, - color: Color(0xFF334155), - ), - ), - ), - ], - ), - ), - ], - const SizedBox(height: 32), - Row( - children: [ - Expanded( - child: OutlinedButton( - onPressed: () { - setState(() { - _showIdentifyNFC = false; - _nfcTagId = null; - _selectedHub = null; - }); - }, - style: OutlinedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 14), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - side: const BorderSide(color: Color(0xFFE2E8F0)), - ), - child: const Text( - 'Cancel', - style: TextStyle(color: Color(0xFF64748B)), - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: ElevatedButton( - onPressed: _nfcTagId != null ? _assignTag : null, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFFFFED4A), - foregroundColor: const Color(0xFF121826), - padding: const EdgeInsets.symmetric(vertical: 14), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: const Text( - 'Assign Tag', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - ], - ), - ], - ), - ), - ), - ); - } - - Widget _buildFieldLabel(String label) { - return Padding( - padding: const EdgeInsets.only(bottom: 6), - child: Text( - label, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF0F172A), - ), - ), - ); - } - - InputDecoration _buildInputDecoration(String hint) { - return InputDecoration( - hintText: hint, - hintStyle: const TextStyle(color: Color(0xFF94A3B8), fontSize: 14), - filled: true, - fillColor: const Color(0xFFF8FAFC), - contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: Color(0xFFE2E8F0)), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: Color(0xFFE2E8F0)), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: Color(0xFF2563EB), width: 2), - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_reports_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_reports_screen.dart deleted file mode 100644 index f983b22e..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_reports_screen.dart +++ /dev/null @@ -1,544 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; - -class ClientReportsScreen extends StatefulWidget { - const ClientReportsScreen({super.key}); - - @override - State createState() => _ClientReportsScreenState(); -} - -class _ClientReportsScreenState extends State - with SingleTickerProviderStateMixin { - late TabController _tabController; - - @override - void initState() { - super.initState(); - _tabController = TabController(length: 4, vsync: this); - } - - @override - void dispose() { - _tabController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFF8FAFC), // slate-50 - body: SingleChildScrollView( - child: Column( - children: [ - // Header - Container( - padding: const EdgeInsets.only( - top: 60, - left: 20, - right: 20, - bottom: 32, - ), - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [ - Color(0xFF0A39DF), // React primary - Color(0xFF0830B8), // React darker - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - child: Column( - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.go('/client-home'), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - const Text( - 'Workforce Control Tower', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ], - ), - const SizedBox(height: 24), - // Tabs - Container( - height: 44, - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(12), - ), - child: TabBar( - controller: _tabController, - indicator: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), - labelColor: const Color(0xFF0A39DF), - unselectedLabelColor: Colors.white, - labelStyle: const TextStyle( - fontWeight: FontWeight.w600, - fontSize: 14, - ), - indicatorSize: TabBarIndicatorSize.tab, - dividerColor: Colors.transparent, - tabs: const [ - Tab(text: 'Today'), - Tab(text: 'Week'), - Tab(text: 'Month'), - Tab(text: 'Quarter'), - ], - ), - ), - ], - ), - ), - - // Content - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Key Metrics - 6 items as in React - GridView.count( - crossAxisCount: 2, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - mainAxisSpacing: 12, - crossAxisSpacing: 12, - childAspectRatio: 1.2, - children: const [ - _MetricCard( - icon: LucideIcons.clock, - label: 'Total Hrs', - value: '1,248', - badgeText: 'This period', - badgeColor: Color(0xFFEEF2FF), // indigo-50 - badgeTextColor: Color(0xFF4338CA), // indigo-700 - iconColor: Color(0xFF4F46E5), // indigo-600 - ), - _MetricCard( - icon: LucideIcons.trendingUp, - label: 'OT Hours', - value: '64', - badgeText: '5.1% of total', - badgeColor: Color(0xFFF1F5F9), // slate-100 - badgeTextColor: Color(0xFF475569), // slate-600 - iconColor: Color(0xFFD97706), // amber-600 - ), - _MetricCard( - icon: LucideIcons.dollarSign, - label: 'Total Spend', - value: '\$17.2k', - badgeText: '↓ 8% vs last week', - badgeColor: Color(0xFFD1FAE5), // emerald-100 - badgeTextColor: Color(0xFF047857), // emerald-700 - iconColor: Color(0xFF10B981), // emerald-600 - ), - _MetricCard( - icon: LucideIcons.trendingUp, - label: 'Fill Rate', - value: '96%', - badgeText: '↑ 2% improvement', - badgeColor: Color(0xFFDBEAFE), // blue-100 - badgeTextColor: Color(0xFF1D4ED8), // blue-700 - iconColor: Color(0xFF2563EB), // blue-600 - ), - _MetricCard( - icon: LucideIcons.clock, - label: 'Avg Fill Time', - value: '2.4 hrs', - badgeText: 'Industry best', - badgeColor: Color(0xFFDBEAFE), // blue-100 - badgeTextColor: Color(0xFF1D4ED8), // blue-700 - iconColor: Color(0xFF2563EB), // blue-600 - ), - _MetricCard( - icon: LucideIcons.alertTriangle, - label: 'No-Show Rate', - value: '2%', - badgeText: 'Below avg', - badgeColor: Color(0xFFD1FAE5), // emerald-100 - badgeTextColor: Color(0xFF047857), // emerald-700 - iconColor: Color(0xFFDC2626), // red-600 - ), - ], - ), - - // Quick Reports - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Quick Reports', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - TextButton.icon( - onPressed: () {}, - icon: const Icon(LucideIcons.download, size: 16), - label: const Text('Export All'), - style: TextButton.styleFrom( - foregroundColor: const Color(0xFF2563EB), // blue-600 - padding: EdgeInsets.zero, - minimumSize: Size.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - ), - ], - ), - - GridView.count( - crossAxisCount: 2, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - mainAxisSpacing: 12, - crossAxisSpacing: 12, - childAspectRatio: 1.3, - children: const [ - _ReportCard( - icon: LucideIcons.calendar, - name: 'Daily Ops Report', - iconBgColor: Color(0xFFDBEAFE), // blue-100 - iconColor: Color(0xFF2563EB), // blue-600 - route: '/daily-ops-report', - ), - _ReportCard( - icon: LucideIcons.dollarSign, - name: 'Spend Report', - iconBgColor: Color(0xFFD1FAE5), // emerald-100 - iconColor: Color(0xFF059669), // emerald-600 - route: '/spend-report', - ), - _ReportCard( - icon: LucideIcons.users, - name: 'Coverage Report', - iconBgColor: Color(0xFFDBEAFE), // blue-100 - iconColor: Color(0xFF2563EB), // blue-600 - route: '/coverage-report-detail', - ), - _ReportCard( - icon: LucideIcons.alertTriangle, - name: 'No-Show Report', - iconBgColor: Color(0xFFFEE2E2), // red-100 - iconColor: Color(0xFFDC2626), // red-600 - route: '/no-show-report', - ), - _ReportCard( - icon: LucideIcons.trendingUp, - name: 'Forecast Report', - iconBgColor: Color(0xFFFEF3C7), // amber-100 - iconColor: Color(0xFFD97706), // amber-600 - route: '/forecast-report', - ), - _ReportCard( - icon: LucideIcons.barChart3, - name: 'Performance Report', - iconBgColor: Color(0xFFDBEAFE), // blue-100 - iconColor: Color(0xFF2563EB), // blue-600 - route: '/performance-report', - ), - ], - ), - - // AI Insights - Container( - width: double.infinity, - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: const Color(0xFFEBF5FF), // Light blue as in React - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.02), - blurRadius: 2, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - '💡 AI Insights', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), // slate-900 - ), - ), - const SizedBox(height: 12), - _InsightRow( - children: [ - const TextSpan(text: 'You could save '), - const TextSpan( - text: '\$1,200/month', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const TextSpan( - text: ' by booking workers 48hrs in advance', - ), - ], - ), - _InsightRow( - children: [ - const TextSpan(text: 'Weekend demand is '), - const TextSpan( - text: '40% higher', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const TextSpan( - text: ' - consider scheduling earlier', - ), - ], - ), - _InsightRow( - children: [ - const TextSpan( - text: 'Your top 5 workers complete ', - ), - const TextSpan( - text: '95% of shifts', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const TextSpan(text: ' - mark them as preferred'), - ], - ), - ], - ), - ), - - const SizedBox(height: 100), // pb-24 - ], - ), - ), - ], - ), - ), - ); - } -} - -class _MetricCard extends StatelessWidget { - final IconData icon; - final String label; - final String value; - final String badgeText; - final Color badgeColor; - final Color badgeTextColor; - final Color iconColor; - - const _MetricCard({ - required this.icon, - required this.label, - required this.value, - required this.badgeText, - required this.badgeColor, - required this.badgeTextColor, - required this.iconColor, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.06), // shadow-md - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Icon(icon, size: 16, color: iconColor), - const SizedBox(width: 8), - Text( - label, - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), // slate-500 - ), - ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - value, - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), // slate-900 - ), - ), - const SizedBox(height: 4), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), - decoration: BoxDecoration( - color: badgeColor, - borderRadius: BorderRadius.circular(10), - ), - child: Text( - badgeText, - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w500, - color: badgeTextColor, - ), - ), - ), - ], - ), - ], - ), - ); - } -} - -class _ReportCard extends StatelessWidget { - final IconData icon; - final String name; - final Color iconBgColor; - final Color iconColor; - final String route; - - const _ReportCard({ - required this.icon, - required this.name, - required this.iconBgColor, - required this.iconColor, - required this.route, - }); - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: () => context.push(route), - child: Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 2), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: iconBgColor, - borderRadius: BorderRadius.circular(12), - ), - child: Icon(icon, size: 20, color: iconColor), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - const SizedBox(height: 4), - const Row( - children: [ - Icon( - LucideIcons.download, - size: 12, - color: Color(0xFF64748B), - ), - SizedBox(width: 4), - Text( - '2-click export', - style: TextStyle(fontSize: 12, color: Color(0xFF64748B)), - ), - ], - ), - ], - ), - ], - ), - ), - ); - } -} - -class _InsightRow extends StatelessWidget { - final List children; - - const _InsightRow({required this.children}); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(bottom: 8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - '• ', - style: TextStyle(color: Color(0xFF334155), fontSize: 14), - ), - Expanded( - child: Text.rich( - TextSpan( - style: const TextStyle( - fontSize: 14, - color: Color(0xFF334155), - height: 1.4, - ), - children: children, - ), - ), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_settings_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_settings_screen.dart deleted file mode 100644 index d1a0ffa5..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_settings_screen.dart +++ /dev/null @@ -1,210 +0,0 @@ -import 'package:client_app_mvp/theme.dart'; -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; - -class ClientSettingsScreen extends StatelessWidget { - const ClientSettingsScreen({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: CustomScrollView( - slivers: [ - SliverAppBar( - backgroundColor: AppColors.krowBlue, - expandedHeight: 200, - pinned: true, - flexibleSpace: FlexibleSpaceBar( - background: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [AppColors.krowBlue, Color(0xFF0047FF)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox(height: 40), - Container( - width: 80, - height: 80, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all(color: Colors.white24, width: 4), - color: Colors.white, - ), - child: Center( - child: Text( - 'C', - style: TextStyle( - fontSize: 32, - fontWeight: FontWeight.bold, - color: AppColors.krowBlue, - ), - ), - ), - ), - const SizedBox(height: 12), - const Text( - 'Client', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - const SizedBox(height: 4), - const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(LucideIcons.mail, size: 14, color: Colors.white70), - SizedBox(width: 6), - Text( - 'client@example.com', - style: TextStyle(color: Colors.white70, fontSize: 14), - ), - ], - ), - ], - ), - ), - ), - leading: IconButton( - icon: const Icon(LucideIcons.arrowLeft, color: Colors.white), - onPressed: () => context.pop(), - ), - title: const Text('Profile', style: TextStyle(color: Colors.white)), - ), - SliverPadding( - padding: const EdgeInsets.all(20), - sliver: SliverList( - delegate: SliverChildListDelegate([ - _buildActionButton( - 'Edit Profile', - () {}, - ), - const SizedBox(height: 16), - _buildActionButton( - 'Hubs', - () => context.push('/client-hubs'), - ), - const SizedBox(height: 16), - OutlinedButton( - onPressed: () => context.go('/client-sign-in'), - style: OutlinedButton.styleFrom( - minimumSize: const Size(double.infinity, 56), - side: const BorderSide(color: AppColors.krowCharcoal, width: 2), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), - foregroundColor: AppColors.krowCharcoal, - ), - child: const Text( - 'Log Out', - style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600), - ), - ), - const SizedBox(height: 24), - Card( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - side: BorderSide(color: Colors.grey.shade200), - ), - color: Colors.white, - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Quick Links', - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 14, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 12), - _buildQuickLink( - context, - icon: LucideIcons.nfc, - title: 'Clock-In Hubs', - onTap: () => context.push('/client-hubs'), - ), - _buildQuickLink( - context, - icon: LucideIcons.building2, - title: 'Billing & Payments', - onTap: () => context.push('/client-billing'), - ), - ], - ), - ), - ), - ]), - ), - ), - ], - ), - ); - } - - Widget _buildActionButton(String label, VoidCallback onTap) { - return ElevatedButton( - onPressed: onTap, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFFFFED4A), // krowYellow - foregroundColor: AppColors.krowCharcoal, - minimumSize: const Size(double.infinity, 56), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), - elevation: 2, - ), - child: Text( - label, - style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600), - ), - ); - } - - Widget _buildQuickLink( - BuildContext context, { - required IconData icon, - required String title, - required VoidCallback onTap, - }) { - return InkWell( - onTap: onTap, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Icon(icon, size: 20, color: const Color(0xFF475569)), - const SizedBox(width: 12), - Text( - title, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - const Icon(LucideIcons.chevronRight, size: 20, color: Color(0xFF94A3B8)), - ], - ), - ), - ); - } -} \ No newline at end of file diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_shifts_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_shifts_screen.dart deleted file mode 100644 index 4fb42e7e..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_shifts_screen.dart +++ /dev/null @@ -1,3161 +0,0 @@ -import 'dart:ui'; - -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:intl/intl.dart'; -import 'package:url_launcher/url_launcher.dart'; - -// --- THEME CONSTANTS (Matching React) --- -class AppColors { - static const krowBlue = Color(0xFF0A39DF); - static const krowBlue50 = Color(0xFFEFF6FF); - static const krowBlue100 = Color(0xFFDBEAFE); - static const krowBlue600 = Color(0xFF2563EB); - static const krowBlue700 = Color(0xFF1D4ED8); - - static const krowSlate50 = Color(0xFFF8FAFC); - static const krowSlate100 = Color(0xFFF1F5F9); - static const krowSlate200 = Color(0xFFE2E8F0); - static const krowSlate300 = Color(0xFFCBD5E1); - static const krowSlate400 = Color(0xFF94A3B8); - static const krowSlate500 = Color(0xFF64748B); - static const krowSlate600 = Color(0xFF475569); - static const krowSlate700 = Color(0xFF334155); - static const krowSlate800 = Color(0xFF1E293B); - static const krowSlate900 = Color(0xFF0F172A); - - static const krowYellow = Color(0xFFF9E547); - static const krowCharcoal = Color(0xFF121826); - - static const krowAmber500 = Color(0xFFF59E0B); - static const krowAmber600 = Color(0xFFD97706); - static const krowAmber700 = Color(0xFFB45309); - - static const krowEmerald100 = Color(0xFFD1FAE5); - static const krowEmerald500 = Color(0xFF10B981); - static const krowEmerald600 = Color(0xFF059669); - static const krowEmerald700 = Color(0xFF047857); - - static const krowRed500 = Color(0xFFEF4444); - static const krowRed600 = Color(0xFFDC2626); -} - -class ClientShiftsScreen extends StatefulWidget { - const ClientShiftsScreen({super.key}); - - @override - State createState() => _ClientShiftsScreenState(); -} - -class _ClientShiftsScreenState extends State { - DateTime _selectedDate = DateTime.now(); - String _filterTab = 'all'; // 'all' (Up Next), 'active', 'completed' - int _weekOffset = 0; - - // Mock Data (Matching React Structure) - final List> _shifts = [ - { - 'id': '1', - 'title': 'Server - Wedding', - 'client_name': 'Grand Plaza Hotel', - 'status': 'filled', - 'date': DateTime.now() - .add(const Duration(days: 1)) - .toIso8601String() - .split('T')[0], - 'start_time': '16:00', - 'end_time': '23:00', - 'location': 'Grand Plaza Hotel, 123 Main St', - 'location_address': 'Grand Plaza Hotel, 123 Main St', - 'filled': 10, - 'workers_needed': 10, - 'hourly_rate': 22.0, - 'confirmed_apps': List.generate( - 10, - (index) => { - 'id': 'app_$index', - 'worker_id': 'w_$index', - 'worker_name': 'Worker ${String.fromCharCode(65 + index)}', - 'status': 'confirmed', - 'check_in_time': index < 5 ? '15:55' : null, - }, - ), - }, - { - 'id': '2', - 'title': 'Bartender - Private Event', - 'client_name': 'Taste of the Town', - 'status': 'open', - 'date': DateTime.now() - .add(const Duration(days: 1)) - .toIso8601String() - .split('T')[0], - 'start_time': '18:00', - 'end_time': '02:00', - 'location': 'Downtown Loft, 456 High St', - 'location_address': 'Downtown Loft, 456 High St', - 'filled': 4, - 'workers_needed': 5, - 'hourly_rate': 28.0, - 'confirmed_apps': List.generate( - 4, - (index) => { - 'id': 'app_b_$index', - 'worker_id': 'w_b_$index', - 'worker_name': 'Bartender ${index + 1}', - 'status': 'confirmed', - }, - ), - }, - { - 'id': '3', - 'title': 'Event Staff', - 'client_name': 'City Center', - 'status': 'in_progress', - 'date': DateTime.now().toIso8601String().split('T')[0], - 'start_time': '08:00', - 'end_time': '16:00', - 'location': 'Convention Center, 789 Blvd', - 'location_address': 'Convention Center, 789 Blvd', - 'filled': 15, - 'workers_needed': 15, - 'hourly_rate': 20.0, - 'confirmed_apps': List.generate( - 15, - (index) => { - 'id': 'app_c_$index', - 'worker_id': 'w_c_$index', - 'worker_name': 'Staff ${index + 1}', - 'status': 'confirmed', - 'check_in_time': '07:55', - }, - ), - }, - { - 'id': '4', - 'title': 'Coat Check', - 'client_name': 'The Met Museum', - 'status': 'completed', - 'date': DateTime.now() - .subtract(const Duration(days: 1)) - .toIso8601String() - .split('T')[0], - 'start_time': '17:00', - 'end_time': '22:00', - 'location': 'The Met Museum, 1000 5th Ave', - 'location_address': 'The Met Museum, 1000 5th Ave', - 'filled': 2, - 'workers_needed': 2, - 'hourly_rate': 18.0, - 'confirmed_apps': List.generate( - 2, - (index) => { - 'id': 'app_d_$index', - 'worker_id': 'w_d_$index', - 'worker_name': 'Checker ${index + 1}', - 'status': 'confirmed', - 'check_in_time': '16:50', - }, - ), - }, - ]; - - // Logic from React: Generate 7-day calendar window (Friday - Thursday) - List _getCalendarDays() { - final now = DateTime.now(); - // Dart weekday: 1=Mon ... 7=Sun - // JS getDay(): 0=Sun ... 6=Sat - // We need to map Dart weekday to JS-style for consistent math with the React code - // React logic: const currentDay = now.getDay(); // 0=Sun, 5=Fri - // daysSinceFriday = (currentDay + 2) % 7; - - int jsDay = now.weekday == 7 ? 0 : now.weekday; - int daysSinceFriday = (jsDay + 2) % 7; - - final startDate = DateTime(now.year, now.month, now.day) - .subtract(Duration(days: daysSinceFriday)) - .add(Duration(days: _weekOffset * 7)); - - return List.generate(7, (index) => startDate.add(Duration(days: index))); - } - - List> _getFilteredShifts() { - final selectedDateStr = _selectedDate.toIso8601String().split('T')[0]; - - // Filter by date - final shiftsOnDate = _shifts - .where((s) => s['date'] == selectedDateStr) - .toList(); - - // Sort by start time - shiftsOnDate.sort( - (a, b) => - (a['start_time'] as String).compareTo(b['start_time'] as String), - ); - - if (_filterTab == 'all') { - return shiftsOnDate - .where((s) => ['open', 'filled', 'confirmed'].contains(s['status'])) - .toList(); - } else if (_filterTab == 'active') { - return shiftsOnDate.where((s) => s['status'] == 'in_progress').toList(); - } else if (_filterTab == 'completed') { - return shiftsOnDate.where((s) => s['status'] == 'completed').toList(); - } - return []; - } - - int _getCategoryCount(String category) { - final selectedDateStr = _selectedDate.toIso8601String().split('T')[0]; - final shiftsOnDate = _shifts - .where((s) => s['date'] == selectedDateStr) - .toList(); - - if (category == 'active') { - return shiftsOnDate.where((s) => s['status'] == 'in_progress').length; - } else if (category == 'completed') { - return shiftsOnDate.where((s) => s['status'] == 'completed').length; - } - return 0; // Default for 'all' which is calculated differently in UI - } - - // Helper for Up Next Count - int _getUpNextCount() { - final selectedDateStr = _selectedDate.toIso8601String().split('T')[0]; - final shiftsOnDate = _shifts - .where((s) => s['date'] == selectedDateStr) - .toList(); - return shiftsOnDate - .where((s) => ['open', 'filled', 'confirmed'].contains(s['status'])) - .length; - } - - String _formatDateHeader(DateTime date) { - // Matches React formatDate logic roughly - final now = DateTime.now(); - final today = DateTime(now.year, now.month, now.day); - final tomorrow = today.add(const Duration(days: 1)); - final checkDate = DateTime(date.year, date.month, date.day); - - if (checkDate == today) return 'Today'; - if (checkDate == tomorrow) return 'Tomorrow'; - return DateFormat('EEE, MMM d').format(date); - } - - @override - Widget build(BuildContext context) { - final calendarDays = _getCalendarDays(); - final filteredShifts = _getFilteredShifts(); - - // Header Colors logic - String sectionTitle = ''; - Color dotColor = Colors.transparent; - - if (_filterTab == 'all') { - sectionTitle = 'Up Next'; - dotColor = AppColors.krowBlue600; - } else if (_filterTab == 'active') { - sectionTitle = 'Active'; - dotColor = AppColors.krowAmber600; - } else if (_filterTab == 'completed') { - sectionTitle = 'Completed'; - dotColor = AppColors.krowBlue; - } - - return Scaffold( - backgroundColor: Colors.white, // Fallback if gradient doesn't cover - body: Stack( - children: [ - // Background Gradient - Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [AppColors.krowSlate50, Colors.white], - stops: [0.0, 0.3], - ), - ), - ), - - SafeArea( - child: Column( - children: [ - // Header + Filter + Calendar (Sticky-ish behavior visual) - // React uses sticky top-0 bg-white/80 backdrop-blur-lg - ClipRect( - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), - child: Container( - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.8), - border: Border( - bottom: BorderSide(color: AppColors.krowSlate100), - ), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - // Top Bar - Padding( - padding: const EdgeInsets.fromLTRB(20, 20, 20, 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.go('/client-home'), - child: Container( - width: 40, - height: 40, - decoration: const BoxDecoration( - color: AppColors.krowSlate100, - shape: BoxShape.circle, - ), - child: const Center( - child: Icon( - LucideIcons.arrowLeft, - color: AppColors.krowSlate600, - size: 20, - ), - ), - ), - ), - const SizedBox(width: 12), - const Text( - 'Orders', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowSlate900, - ), - ), - ], - ), - ElevatedButton( - onPressed: () => - context.push('/create-order'), - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 10, - ), - ), - child: const Row( - children: [ - Icon(LucideIcons.plus, size: 16), - SizedBox(width: 4), - Text( - 'Post', - style: TextStyle( - fontWeight: FontWeight.w600, - ), - ), - ], - ), - ), - ], - ), - ), - - // Filter Tabs - Padding( - padding: const EdgeInsets.only(bottom: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - _buildFilterTab('Up Next', null, 'all'), - const SizedBox(width: 24), - _buildFilterTab( - 'Active', - _getCategoryCount('active') + - _getUpNextCount(), - 'active', - showCount: true, - ), - const SizedBox(width: 24), - _buildFilterTab( - 'Completed', - _getCategoryCount('completed'), - 'completed', - showCount: true, - ), - ], - ), - ), - - // Calendar Header controls - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 8, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - IconButton( - icon: const Icon( - LucideIcons.chevronLeft, - size: 20, - color: AppColors.krowSlate600, - ), - onPressed: () => - setState(() => _weekOffset--), - padding: EdgeInsets.zero, - constraints: const BoxConstraints(), - splashRadius: 20, - ), - Text( - DateFormat( - 'MMMM yyyy', - ).format(calendarDays.first), - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowSlate600, - ), - ), - IconButton( - icon: const Icon( - LucideIcons.chevronRight, - size: 20, - color: AppColors.krowSlate600, - ), - onPressed: () => - setState(() => _weekOffset++), - padding: EdgeInsets.zero, - constraints: const BoxConstraints(), - splashRadius: 20, - ), - ], - ), - ), - - // Calendar Grid - SizedBox( - height: 72, - child: ListView.separated( - padding: const EdgeInsets.symmetric( - horizontal: 20, - ), - scrollDirection: Axis.horizontal, - itemCount: 7, - separatorBuilder: (context, index) => - const SizedBox(width: 8), - itemBuilder: (context, index) { - final date = calendarDays[index]; - final isSelected = - date.year == _selectedDate.year && - date.month == _selectedDate.month && - date.day == _selectedDate.day; - - // Check if this date has any shifts (any status) - final dateStr = date.toIso8601String().split( - 'T', - )[0]; - final hasShifts = _shifts.any( - (s) => s['date'] == dateStr, - ); - - return GestureDetector( - onTap: () => - setState(() => _selectedDate = date), - child: AnimatedContainer( - duration: const Duration(milliseconds: 200), - width: 48, - decoration: BoxDecoration( - color: isSelected - ? AppColors.krowBlue - : Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: isSelected - ? AppColors.krowBlue - : AppColors.krowSlate200, - ), - boxShadow: isSelected - ? [ - BoxShadow( - color: AppColors.krowBlue - .withValues(alpha: 0.25), - blurRadius: 12, - offset: const Offset(0, 4), - ), - ] - : null, - ), - child: Column( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Text( - DateFormat('dd').format(date), - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: isSelected - ? Colors.white - : AppColors.krowSlate900, - ), - ), - Text( - DateFormat('E').format(date), - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w500, - color: isSelected - ? Colors.white.withValues( - alpha: 0.8, - ) - : AppColors.krowSlate500, - ), - ), - if (hasShifts) ...[ - const SizedBox(height: 4), - Container( - width: 6, - height: 6, - decoration: BoxDecoration( - color: isSelected - ? Colors.white - : AppColors.krowBlue, - shape: BoxShape.circle, - ), - ), - ], - ], - ), - ), - ); - }, - ), - ), - const SizedBox( - height: 16, - ), // Padding bottom of header - ], - ), - ), - ), - ), - - // Content List - Expanded( - child: filteredShifts.isEmpty - ? _buildEmptyState() - : ListView( - padding: const EdgeInsets.fromLTRB(20, 16, 20, 100), - children: [ - if (filteredShifts.isNotEmpty) - Padding( - padding: const EdgeInsets.only(bottom: 12), - child: Row( - children: [ - Container( - width: 8, - height: 8, - decoration: BoxDecoration( - color: dotColor, - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 8), - Text( - sectionTitle.toUpperCase(), - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: AppColors.krowSlate900, - letterSpacing: 0.5, - ), - ), - const SizedBox(width: 4), - Text( - '(${filteredShifts.length})', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowSlate400, - ), - ), - ], - ), - ), - ...filteredShifts.map( - (shift) => Padding( - padding: const EdgeInsets.only(bottom: 12), - child: _OrderCoverageCard(shift: shift), - ), - ), - ], - ), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildFilterTab( - String label, - int? count, - String tabId, { - bool showCount = false, - }) { - final isSelected = _filterTab == tabId; - - // Logic to handle count display for Active tab per React code - // React: Active ({comingUpShifts.length + inProgressShifts.length}) - // For Flutter, just pass the calculated count. - - String text = label; - if (showCount && count != null) { - text = '$label ($count)'; - } - - return GestureDetector( - onTap: () => setState(() => _filterTab = tabId), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Text( - text, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: isSelected ? AppColors.krowBlue : AppColors.krowSlate400, - ), - ), - ), - AnimatedContainer( - duration: const Duration(milliseconds: 200), - height: 2, - width: isSelected ? 40 : 0, // Animate width - decoration: BoxDecoration( - color: AppColors.krowBlue, - borderRadius: BorderRadius.circular(2), - ), - ), - if (!isSelected) const SizedBox(height: 2), // Placeholder for height - ], - ), - ); - } - - Widget _buildEmptyState() { - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon( - LucideIcons.calendar, - size: 48, - color: AppColors.krowSlate300, - ), - const SizedBox(height: 12), - Text( - 'No orders for ${_formatDateHeader(_selectedDate)}', - style: const TextStyle(color: AppColors.krowSlate500), - ), - const SizedBox(height: 16), - ElevatedButton( - onPressed: () => context.push('/create-order'), - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - ), - child: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(LucideIcons.plus, size: 16), - SizedBox(width: 8), - Text('Post an Order'), - ], - ), - ), - ], - ), - ); - } -} - -class _OrderCoverageCard extends StatefulWidget { - final Map shift; - - const _OrderCoverageCard({required this.shift}); - - @override - State<_OrderCoverageCard> createState() => _OrderCoverageCardState(); -} - -class _OrderCoverageCardState extends State<_OrderCoverageCard> { - bool _expanded = true; // Default expanded in React is true - - void _openEditSheet(Map shiftData) { - showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) { - return _UnifiedOrderFlowSheet( - initialOrder: shiftData, - onBack: () { - Navigator.pop(context); // Close the sheet - // Invalidate queries or refresh data if needed - }, - ); - }, - ); - } - - // Helpers - Color _getStatusColor(String status) { - switch (status) { - case 'filled': - case 'confirmed': - return AppColors.krowBlue; - case 'completed': - return AppColors.krowBlue; - case 'in_progress': - return AppColors.krowAmber600; - case 'cancelled': - return AppColors.krowRed500; - default: - return AppColors.krowAmber600; // Open/Default - } - } - - String _getStatusLabel(String status) { - switch (status) { - case 'filled': - case 'confirmed': - return 'CONFIRMED'; - case 'in_progress': - return 'ACTIVE'; - default: - return status.toUpperCase(); - } - } - - String _formatTime(String time) { - if (time.isEmpty) return ''; - final parts = time.split(':'); - int hour = int.parse(parts[0]); - int minute = int.parse(parts[1]); - String ampm = hour >= 12 ? 'PM' : 'AM'; - hour = hour % 12; - if (hour == 0) hour = 12; - return '$hour:${minute.toString().padLeft(2, '0')} $ampm'; - } - - String _formatDate(String dateStr) { - final date = DateTime.parse(dateStr); - // Use helper from main screen or simple local - final now = DateTime.now(); - final today = DateTime(now.year, now.month, now.day); - final tomorrow = today.add(const Duration(days: 1)); - final checkDate = DateTime(date.year, date.month, date.day); - - if (checkDate == today) return 'Today'; - if (checkDate == tomorrow) return 'Tomorrow'; - return DateFormat('EEE, MMM d').format(date); - } - - void _showSnackbar(String message) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(message), duration: const Duration(seconds: 2)), - ); - } - - void _showMessageAllSheet() { - final TextEditingController _messageController = TextEditingController(); - final List workers = - widget.shift['confirmed_apps'] ?? []; // Get worker list from shift - final String shiftTitle = widget.shift['title'] ?? 'Shift'; - - showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) { - return Container( - height: MediaQuery.of(context).size.height * 0.8, // Adjust height - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.vertical(top: Radius.circular(24)), - ), - child: Column( - children: [ - // Header - Padding( - padding: const EdgeInsets.all(20), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Message All Workers for $shiftTitle', - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - IconButton( - icon: const Icon(LucideIcons.x), - onPressed: () => Navigator.pop(context), - ), - ], - ), - ), - const Divider(height: 1), - // Recipients - Expanded( - child: Padding( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Recipients:', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 8), - Wrap( - spacing: 8, - runSpacing: 8, - children: workers.map((worker) { - return Chip( - label: Text(worker['worker_name']), - backgroundColor: AppColors.krowBlue50, - labelStyle: const TextStyle( - color: AppColors.krowBlue700, - fontSize: 12, - ), - ); - }).toList(), - ), - const SizedBox(height: 20), - // Message Input - const Text( - 'Your Message:', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 8), - TextField( - controller: _messageController, - maxLines: 5, - decoration: InputDecoration( - hintText: 'Type your message here...', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowSlate200, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBlue, - ), - ), - ), - ), - ], - ), - ), - ), - // Send Button - Padding( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 100), - child: SizedBox( - width: double.infinity, - height: 56, - child: ElevatedButton( - onPressed: () { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Message "${_messageController.text}" sent to ${workers.length} workers (Placeholder)', - ), - duration: const Duration(seconds: 2), - ), - ); - Navigator.pop(context); // Close the sheet - }, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: const Text( - 'Send Message', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ), - ], - ), - ); - }, - ); - } - - Future _launchPhoneCall(String phoneNumber) async { - final Uri launchUri = Uri(scheme: 'tel', path: phoneNumber); - await launchUrl(launchUri); - } - - void _showWorkerChatSheet(String workerName) { - final TextEditingController _chatMessageController = - TextEditingController(); - // Mock chat history - final List> mockChatHistory = [ - { - 'sender': workerName, - 'message': 'Hi, I\'m running a bit late, maybe 10 mins.', - 'time': '10:05 AM', - }, - { - 'sender': 'You', - 'message': 'Okay, thanks for the heads up! Drive safely.', - 'time': '10:07 AM', - }, - { - 'sender': workerName, - 'message': 'Will do! Almost there.', - 'time': '10:20 AM', - }, - ]; - - showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) { - return Container( - height: MediaQuery.of(context).size.height * 0.8, // Adjust height - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.vertical(top: Radius.circular(24)), - ), - child: SafeArea( - child: Column( - children: [ - // Header - Padding( - padding: const EdgeInsets.all(20), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Chat with $workerName', - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - IconButton( - icon: const Icon(LucideIcons.x), - onPressed: () => Navigator.pop(context), - ), - ], - ), - ), - const Divider(height: 1), - // Chat History - Expanded( - child: ListView.builder( - padding: const EdgeInsets.all(20), - reverse: true, // Show latest messages at the bottom - itemCount: mockChatHistory.length, - itemBuilder: (context, index) { - final message = - mockChatHistory[mockChatHistory.length - - 1 - - index]; // Reverse order for display - final isMe = message['sender'] == 'You'; - return Align( - alignment: isMe - ? Alignment.centerRight - : Alignment.centerLeft, - child: Container( - margin: const EdgeInsets.only(bottom: 10), - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: isMe - ? AppColors.krowBlue - : AppColors.krowSlate100, - borderRadius: BorderRadius.circular(12), - ), - child: Column( - crossAxisAlignment: isMe - ? CrossAxisAlignment.end - : CrossAxisAlignment.start, - children: [ - Text( - message['message']!, - style: TextStyle( - color: isMe - ? Colors.white - : AppColors.krowSlate900, - ), - ), - const SizedBox(height: 4), - Text( - '${message['sender']} - ${message['time']}', - style: TextStyle( - color: isMe - ? Colors.white70 - : AppColors.krowSlate400, - fontSize: 10, - ), - ), - ], - ), - ), - ); - }, - ), - ), - // Message Input - Padding( - padding: const EdgeInsets.all(20), - child: Row( - children: [ - Expanded( - child: TextField( - controller: _chatMessageController, - decoration: InputDecoration( - hintText: 'Type a message...', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(24), - borderSide: BorderSide.none, - ), - filled: true, - fillColor: AppColors.krowSlate100, - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - ), - ), - ), - ), - const SizedBox(width: 12), - CircleAvatar( - backgroundColor: AppColors.krowBlue, - radius: 24, - child: IconButton( - icon: const Icon( - LucideIcons.send, - color: Colors.white, - ), - onPressed: () { - if (_chatMessageController.text.isNotEmpty) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Message "${_chatMessageController.text}" sent to $workerName (Placeholder)', - ), - duration: const Duration(seconds: 2), - ), - ); - _chatMessageController.clear(); - // In a real app, add message to history and update UI - } - }, - ), - ), - ], - ), - ), - ], - ), - ), - ); - }, - ); - } - - @override - Widget build(BuildContext context) { - final shift = widget.shift; - final statusColor = _getStatusColor(shift['status']); - final statusLabel = _getStatusLabel(shift['status']); - final filled = shift['filled'] as int; - final needed = shift['workers_needed'] as int; - final coveragePercent = needed > 0 ? ((filled / needed) * 100).round() : 0; - - // Calculations - final confirmedApps = shift['confirmed_apps'] as List; - final cost = - (shift['hourly_rate'] as double) * 8 * (filled > 0 ? filled : needed); - // React calculates hours based on start/end, default 8. Mock: - double hours = 8.0; - - return Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: AppColors.krowBlue.withValues(alpha: 0.12), // #0A39DF20 - width: 1.5, - ), - boxShadow: [ - BoxShadow( - color: AppColors.krowBlue.withValues(alpha: 0.08), - blurRadius: 3, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Header Row - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Status Dot & Label - Row( - children: [ - Container( - width: 6, - height: 6, - decoration: BoxDecoration( - color: statusColor, - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 8), - Text( - statusLabel, - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: statusColor, - letterSpacing: 0.5, - ), - ), - ], - ), - const SizedBox(height: 2), - // Title - Text( - shift['title'], - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowSlate900, - ), - ), - const SizedBox(height: 4), - // Client & Date - Row( - children: [ - Text( - shift['client_name'], - style: const TextStyle( - fontSize: 12, - color: AppColors.krowSlate500, - ), - ), - const Padding( - padding: EdgeInsets.symmetric(horizontal: 4), - child: Text( - '•', - style: TextStyle( - color: AppColors.krowSlate400, - ), - ), - ), - Text( - _formatDate(shift['date']), - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: AppColors.krowSlate600, - ), - ), - ], - ), - const SizedBox(height: 4), - // Address - Row( - children: [ - const Icon( - LucideIcons.mapPin, - size: 12, - color: AppColors.krowSlate600, - ), - const SizedBox(width: 4), - Expanded( - child: Text( - shift['location_address'], - style: const TextStyle( - fontSize: 11, - color: AppColors.krowSlate600, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - const SizedBox(width: 4), - GestureDetector( - onTap: () { - _showSnackbar(shift['location_address']); - }, - child: const Row( - children: [ - Icon( - LucideIcons.navigation, - size: 12, - color: AppColors.krowBlue600, - ), - SizedBox(width: 2), - Text( - 'Get direction', - style: TextStyle( - fontSize: 11, - color: AppColors.krowBlue600, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ), - ], - ), - ], - ), - ), - // Actions (Edit & Expand) - Row( - children: [ - _buildHeaderIconButton( - icon: LucideIcons.edit2, - color: AppColors.krowBlue600, - bgColor: AppColors.krowBlue50, - onTap: () => _openEditSheet(shift), - ), - const SizedBox(width: 8), - _buildHeaderIconButton( - icon: _expanded - ? LucideIcons.chevronUp - : LucideIcons.chevronDown, - color: AppColors.krowSlate600, - bgColor: AppColors.krowSlate50, - onTap: () => setState(() => _expanded = !_expanded), - ), - ], - ), - ], - ), - - const SizedBox(height: 12), - const Divider(height: 1, color: AppColors.krowSlate100), - const SizedBox(height: 12), - - // Stats Row - Row( - children: [ - Expanded( - child: _buildStatItem( - icon: LucideIcons.dollarSign, - value: '\$${cost.round()}', - label: 'Total', - ), - ), - Container( - width: 1, - height: 32, - color: AppColors.krowSlate100, - ), - Expanded( - child: _buildStatItem( - icon: LucideIcons.clock, - value: hours.toStringAsFixed(1), - label: 'HRS', - ), - ), - Container( - width: 1, - height: 32, - color: AppColors.krowSlate100, - ), - Expanded( - child: _buildStatItem( - icon: LucideIcons.users, - value: '${filled > 0 ? filled : needed}', - label: 'workers', - ), - ), - ], - ), - - const SizedBox(height: 16), - - // Clock In/Out Boxes - Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.symmetric(vertical: 8), - decoration: BoxDecoration( - color: AppColors.krowSlate50, - borderRadius: BorderRadius.circular(8), - ), - child: Column( - children: [ - const Text( - 'CLOCK IN', - style: TextStyle( - fontSize: 9, - color: AppColors.krowSlate500, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 2), - Text( - _formatTime(shift['start_time']), - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: AppColors.krowSlate900, - ), - ), - ], - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: Container( - padding: const EdgeInsets.symmetric(vertical: 8), - decoration: BoxDecoration( - color: AppColors.krowSlate50, - borderRadius: BorderRadius.circular(8), - ), - child: Column( - children: [ - const Text( - 'CLOCK OUT', - style: TextStyle( - fontSize: 9, - color: AppColors.krowSlate500, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 2), - Text( - _formatTime(shift['end_time']), - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: AppColors.krowSlate900, - ), - ), - ], - ), - ), - ), - ], - ), - - const SizedBox(height: 12), - - // Coverage Status - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Icon( - LucideIcons.checkCircle, - size: 16, - color: AppColors.krowEmerald500, - ), - const SizedBox(width: 6), - Text( - '$filled/$needed Workers', - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: AppColors.krowSlate900, - ), - ), - ], - ), - Text( - '$coveragePercent%', - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: AppColors.krowBlue600, - ), - ), - ], - ), - const SizedBox(height: 8), - // Coverage Bar - Stack( - children: [ - Container( - height: 8, - width: double.infinity, - decoration: BoxDecoration( - color: AppColors.krowSlate100, - borderRadius: BorderRadius.circular(4), - ), - ), - AnimatedContainer( - duration: const Duration(milliseconds: 300), - height: 8, - width: - MediaQuery.of(context).size.width * - (coveragePercent / 100) * - 0.8, // Approximation - decoration: BoxDecoration( - color: AppColors.krowBlue600, - borderRadius: BorderRadius.circular(4), - ), - ), - ], - ), - - // Avatars Stack (Preview) - if (confirmedApps.isNotEmpty) ...[ - const SizedBox(height: 12), - Row( - children: [ - SizedBox( - height: 28, - width: - 28.0 + - (confirmedApps.length > 3 - ? 3 - : confirmedApps.length - 1) * - 20.0, - child: Stack( - children: [ - for ( - int i = 0; - i < - (confirmedApps.length > 3 - ? 3 - : confirmedApps.length); - i++ - ) - Positioned( - left: i * 20.0, - child: Container( - width: 28, - height: 28, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: Colors.white, - width: 2, - ), - color: AppColors.krowBlue100, - ), - child: Center( - child: Text( - (confirmedApps[i]['worker_name'] - as String)[0], - style: const TextStyle( - fontSize: 10, - color: AppColors.krowBlue700, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ), - ], - ), - ), - if (confirmedApps.length > 3) - Padding( - padding: const EdgeInsets.only(left: 8), - child: Text( - '+${confirmedApps.length - 3} more', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowSlate500, - ), - ), - ), - ], - ), - ], - ], - ), - ), - - // Expanded Content - if (_expanded && confirmedApps.isNotEmpty) - Container( - decoration: const BoxDecoration( - color: AppColors.krowSlate50, - border: Border(top: BorderSide(color: AppColors.krowSlate100)), - borderRadius: BorderRadius.vertical( - bottom: Radius.circular(12), - ), - ), - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Assigned Workers', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: AppColors.krowSlate700, - ), - ), - SizedBox( - height: 28, - child: ElevatedButton.icon( - onPressed: _showMessageAllSheet, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue600, - foregroundColor: Colors.white, - padding: const EdgeInsets.symmetric(horizontal: 10), - elevation: 0, - textStyle: const TextStyle(fontSize: 10), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), - ), - ), - icon: const Icon(LucideIcons.messageCircle, size: 12), - label: const Text('Message All'), - ), - ), - ], - ), - const SizedBox(height: 12), - - // Worker List - ...confirmedApps.take(5).map((app) => _buildWorkerRow(app)), - - if (confirmedApps.length > 5) - Padding( - padding: const EdgeInsets.only(top: 8), - child: Center( - child: TextButton( - onPressed: () => - setState(() => _expanded = !_expanded), - child: Text( - 'Show ${confirmedApps.length - 5} more workers', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowBlue600, - ), - ), - ), - ), - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildWorkerRow(Map app) { - return Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - // Avatar - Container( - width: 36, - height: 36, - decoration: const BoxDecoration( - color: AppColors.krowBlue50, - shape: BoxShape.circle, - ), - child: Center( - child: Text( - (app['worker_name'] as String)[0], - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: AppColors.krowBlue700, - ), - ), - ), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - app['worker_name'], - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowSlate900, - ), - ), - const SizedBox(height: 2), - Row( - children: [ - Container( - padding: const EdgeInsets.symmetric( - horizontal: 4, - vertical: 1, - ), - decoration: BoxDecoration( - border: Border.all(color: AppColors.krowSlate200), - borderRadius: BorderRadius.circular(4), - ), - child: const Text( - '⭐ 4.8', - style: TextStyle( - fontSize: 10, - color: AppColors.krowSlate500, - ), - ), - ), - if (app['check_in_time'] != null) ...[ - const SizedBox(width: 4), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 4, - vertical: 1, - ), - decoration: BoxDecoration( - color: AppColors.krowEmerald100, - borderRadius: BorderRadius.circular(4), - ), - child: const Text( - 'Checked In', - style: TextStyle( - fontSize: 10, - color: AppColors.krowEmerald700, - ), - ), - ), - ], - ], - ), - ], - ), - ], - ), - - // Actions - Row( - children: [ - _buildActionIcon( - LucideIcons.phone, - AppColors.krowBlue600, - () => _launchPhoneCall( - 'tel:+1-555-123-4567', - ), // Placeholder number - ), - const SizedBox(width: 8), - _buildActionIcon( - LucideIcons.messageCircle, - AppColors.krowBlue600, - () => _showWorkerChatSheet(app['worker_name']), - ), - const SizedBox(width: 8), - const Icon( - LucideIcons.checkCircle, - size: 20, - color: AppColors.krowEmerald500, - ), - ], - ), - ], - ), - ), - ); - } - - Widget _buildActionIcon(IconData icon, Color color, VoidCallback onTap) { - return GestureDetector( - onTap: onTap, - child: Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - color: Colors.transparent, // Ghost button equivalent - ), - child: Icon(icon, size: 16, color: color), - ), - ); - } - - Widget _buildStatItem({ - required IconData icon, - required String value, - required String label, - }) { - return Column( - children: [ - Icon(icon, size: 14, color: AppColors.krowSlate400), - const SizedBox(height: 4), - Text( - value, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: AppColors.krowSlate900, - ), - ), - Text( - label, - style: const TextStyle(fontSize: 9, color: AppColors.krowSlate500), - ), - ], - ); - } - - Widget _buildHeaderIconButton({ - required IconData icon, - required Color color, - required Color bgColor, - required VoidCallback onTap, - }) { - return GestureDetector( - onTap: onTap, - child: Container( - width: 32, - height: 32, - decoration: BoxDecoration( - color: bgColor, - borderRadius: BorderRadius.circular(8), - ), - child: Icon(icon, size: 16, color: color), - ), - ); - } -} - -// Constants -const Map _roleRates = { - 'Server': 18.0, - 'Bartender': 22.0, - 'Cook': 20.0, - 'Busser': 16.0, - 'Host': 17.0, - 'Barista': 16.0, - 'Dishwasher': 15.0, - 'Event Staff': 20.0, - 'Manager': 25.0, -}; - -const List _roles = [ - 'Server', - 'Bartender', - 'Cook', - 'Busser', - 'Host', - 'Barista', - 'Dishwasher', - 'Event Staff', - 'Manager', -]; - -class _UnifiedOrderFlowSheet extends StatefulWidget { - final Map initialOrder; - final VoidCallback onBack; - - const _UnifiedOrderFlowSheet({ - required this.initialOrder, - required this.onBack, - }); - - @override - State<_UnifiedOrderFlowSheet> createState() => _UnifiedOrderFlowSheetState(); -} - -class _UnifiedOrderFlowSheetState extends State<_UnifiedOrderFlowSheet> { - late TextEditingController _dateController; - late TextEditingController _globalLocationController; - - // Order state - List> _positions = []; - bool _showReview = false; - bool _submitted = false; - bool _isLoading = false; - - // Validation errors - Map _errors = {}; - - @override - void initState() { - super.initState(); - final order = widget.initialOrder; - - _dateController = TextEditingController(text: order['date'] ?? ''); - _globalLocationController = TextEditingController( - text: order['location_address'] ?? order['location'] ?? '', - ); - - // Initialize positions - // In edit mode (from card), we usually have 1 position derived from the shift. - // If we want to support multiple, we'd need a different data structure or assume 1 for edit. - - final initialRole = _getInitialRole(order['title'] ?? ''); - - _positions = [ - { - 'role': initialRole, - 'count': order['workers_needed'] ?? 1, - 'start_time': order['start_time'] ?? '', - 'end_time': order['end_time'] ?? '', - 'location': '', // Override location - 'lunch_break': 30, - 'show_location_override': false, - }, - ]; - } - - String _getInitialRole(String title) { - if (_roles.contains(title)) return title; - - // Check if title contains any role - for (final role in _roles) { - if (title.contains(role)) { - return role; - } - } - - return ''; // Default to empty if no match found - } - - @override - void dispose() { - _dateController.dispose(); - _globalLocationController.dispose(); - super.dispose(); - } - - void _addPosition() { - setState(() { - _positions.add({ - 'role': '', - 'count': 1, - 'start_time': '', - 'end_time': '', - 'location': '', - 'lunch_break': 30, - 'show_location_override': false, - }); - }); - } - - void _removePosition(int index) { - if (_positions.length > 1) { - setState(() { - _positions.removeAt(index); - }); - } - } - - void _updatePosition(int index, String key, dynamic value) { - setState(() { - _positions[index][key] = value; - // Clear error for this field if exists - if (_errors.containsKey('${key}_$index')) { - _errors.remove('${key}_$index'); - } - }); - } - - bool _validate() { - final newErrors = {}; - - if (_dateController.text.isEmpty) { - newErrors['date'] = 'Date is required'; - } - - if (_globalLocationController.text.isEmpty) { - // Check if all positions have overrides - bool allHaveLocation = _positions.every( - (p) => - p['show_location_override'] == true && - p['location'].toString().isNotEmpty, - ); - if (!allHaveLocation) { - newErrors['location'] = 'Location is required'; - } - } - - for (int i = 0; i < _positions.length; i++) { - final pos = _positions[i]; - if (pos['role'].toString().isEmpty) newErrors['role_$i'] = 'Required'; - if (pos['start_time'].toString().isEmpty) - newErrors['start_time_$i'] = 'Required'; - if (pos['end_time'].toString().isEmpty) - newErrors['end_time_$i'] = 'Required'; - - if (pos['show_location_override'] == true && - pos['location'].toString().isEmpty) { - newErrors['location_$i'] = 'Required'; - } - } - - setState(() { - _errors = newErrors; - }); - return newErrors.isEmpty; - } - - void _submit() async { - setState(() => _isLoading = true); - // Simulate network delay - await Future.delayed(const Duration(seconds: 1)); - if (mounted) { - setState(() { - _isLoading = false; - _submitted = true; - }); - } - } - - double _calculateTotalCost() { - double total = 0; - for (var pos in _positions) { - final role = pos['role'] ?? ''; - final rate = _roleRates[role] ?? 0.0; - final count = pos['count'] as int; - // Estimate hours (simple parsing) - double hours = 8.0; - if (pos['start_time'] != '' && pos['end_time'] != '') { - try { - // Simple calc, ignore date crossing for MVP - final startParts = pos['start_time'].toString().split(':'); - final endParts = pos['end_time'].toString().split(':'); - final startH = - int.parse(startParts[0]) + int.parse(startParts[1]) / 60; - final endH = int.parse(endParts[0]) + int.parse(endParts[1]) / 60; - - hours = endH - startH; - if (hours < 0) hours += 24; // Crossed midnight - } catch (_) {} - } - - total += rate * hours * count; - } - return total; - } - - @override - Widget build(BuildContext context) { - if (_submitted) { - return _buildSuccessView(); - } - - if (_showReview) { - return _buildReviewView(); - } - - return _buildFormView(); - } - - Widget _buildFormView() { - return Container( - height: MediaQuery.of(context).size.height * 0.95, - decoration: const BoxDecoration( - color: AppColors.krowSlate50, - borderRadius: BorderRadius.vertical(top: Radius.circular(24)), - ), - child: Column( - children: [ - // Header - Container( - padding: const EdgeInsets.fromLTRB(20, 20, 20, 16), - decoration: const BoxDecoration( - color: AppColors.krowBlue, - borderRadius: BorderRadius.vertical(top: Radius.circular(24)), - ), - child: Row( - children: [ - GestureDetector( - onTap: widget.onBack, - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withValues(alpha: 0.2), - borderRadius: BorderRadius.circular(12), - ), - child: const Center( - child: Icon( - LucideIcons.chevronLeft, - color: Colors.white, - size: 24, - ), - ), - ), - ), - const SizedBox(width: 12), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Edit Order', // Or "Create Order" dynamic - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - Text( - 'Fast & flexible staffing', - style: TextStyle(fontSize: 12, color: Colors.white70), - ), - ], - ), - ], - ), - ), - - // Content - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - // Global Fields - _buildSectionLabel('Date *'), - _buildDatePicker( - controller: _dateController, - error: _errors['date'], - ), - const SizedBox(height: 16), - - _buildSectionLabel('Location *'), - _buildTextField( - controller: _globalLocationController, - hint: 'Business address', - icon: LucideIcons.mapPin, - error: _errors['location'], - ), - const SizedBox(height: 24), - - // Positions Header - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Positions', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowSlate900, - ), - ), - TextButton.icon( - onPressed: _addPosition, - icon: const Icon(LucideIcons.plus, size: 16), - label: const Text('Add Position'), - style: TextButton.styleFrom( - foregroundColor: AppColors.krowBlue600, - textStyle: const TextStyle( - fontWeight: FontWeight.w600, - ), - ), - ), - ], - ), - const SizedBox(height: 8), - - // Position Cards - ..._positions.asMap().entries.map((entry) { - final index = entry.key; - final pos = entry.value; - return _buildPositionCard(index, pos); - }), - - const SizedBox(height: 80), // Bottom padding - ], - ), - ), - ), - - // Footer - Container( - padding: const EdgeInsets.all(20), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: AppColors.krowSlate200)), - ), - child: SafeArea( - top: false, - child: ElevatedButton( - onPressed: () { - if (_validate()) { - setState(() => _showReview = true); - } - }, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - minimumSize: const Size(double.infinity, 48), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: Text( - 'Review ${_positions.length} Position${_positions.length > 1 ? 's' : ''}', - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ), - ], - ), - ); - } - - Widget _buildReviewView() { - final totalWorkers = _positions.fold( - 0, - (sum, p) => sum + (p['count'] as int), - ); - final totalCost = _calculateTotalCost(); - - return Container( - height: MediaQuery.of(context).size.height * 0.95, - decoration: const BoxDecoration( - color: AppColors.krowSlate50, - borderRadius: BorderRadius.vertical(top: Radius.circular(24)), - ), - child: Column( - children: [ - // Header - Container( - padding: const EdgeInsets.fromLTRB(20, 20, 20, 16), - decoration: const BoxDecoration( - color: AppColors.krowBlue, - borderRadius: BorderRadius.vertical(top: Radius.circular(24)), - ), - child: Row( - children: [ - GestureDetector( - onTap: () => setState(() => _showReview = false), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withValues(alpha: 0.2), - borderRadius: BorderRadius.circular(12), - ), - child: const Center( - child: Icon( - LucideIcons.chevronLeft, - color: Colors.white, - size: 24, - ), - ), - ), - ), - const SizedBox(width: 12), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Review Order', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - Text( - 'Confirm details before posting', - style: TextStyle(fontSize: 12, color: Colors.white70), - ), - ], - ), - ], - ), - ), - - // Content - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Summary Card - Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [ - AppColors.krowBlue50, - Color(0xFFDBEAFE), - ], // blue-50 to blue-100 - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: AppColors.krowBlue.withValues(alpha: 0.2), - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - _buildSummaryItem('${_positions.length}', 'Positions'), - _buildSummaryItem('$totalWorkers', 'Workers'), - _buildSummaryItem( - '\$${totalCost.round()}', - 'Est. Cost', - ), - ], - ), - ), - const SizedBox(height: 20), - - // Order Details - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowSlate200), - ), - child: Column( - children: [ - Row( - children: [ - const Icon( - LucideIcons.calendar, - size: 16, - color: AppColors.krowBlue600, - ), - const SizedBox(width: 8), - Text( - _dateController.text, - style: const TextStyle( - fontWeight: FontWeight.w600, - color: AppColors.krowSlate900, - ), - ), - ], - ), - if (_globalLocationController.text.isNotEmpty) ...[ - const SizedBox(height: 12), - Row( - children: [ - const Icon( - LucideIcons.mapPin, - size: 16, - color: AppColors.krowBlue600, - ), - const SizedBox(width: 8), - Expanded( - child: Text( - _globalLocationController.text, - style: const TextStyle( - color: AppColors.krowSlate900, - ), - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ], - ], - ), - ), - const SizedBox(height: 24), - - const Text( - 'Positions Breakdown', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: AppColors.krowSlate900, - ), - ), - const SizedBox(height: 12), - - ..._positions.map((pos) { - final role = pos['role'] ?? 'Unknown'; - final rate = _roleRates[role] ?? 0.0; - - double hours = 0; - if (pos['start_time'] != '' && pos['end_time'] != '') { - try { - final startParts = pos['start_time'].toString().split( - ':', - ); - final endParts = pos['end_time'].toString().split(':'); - final startH = - int.parse(startParts[0]) + - int.parse(startParts[1]) / 60; - final endH = - int.parse(endParts[0]) + - int.parse(endParts[1]) / 60; - - hours = endH - startH; - if (hours < 0) hours += 24; - } catch (_) {} - } - - final cost = hours * rate * (pos['count'] as int); - - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowSlate100), - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - role, - style: const TextStyle( - fontWeight: FontWeight.bold, - color: AppColors.krowSlate900, - ), - ), - Text( - '${pos['count']} worker${pos['count'] > 1 ? 's' : ''}', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowSlate500, - ), - ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - '\$${cost.round()}', - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowBlue, - ), - ), - Text( - '\$${rate.toStringAsFixed(0)}/hr', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowSlate500, - ), - ), - ], - ), - ], - ), - const SizedBox(height: 12), - Row( - children: [ - const Icon( - LucideIcons.clock, - size: 14, - color: AppColors.krowSlate400, - ), - const SizedBox(width: 6), - Text( - '${pos['start_time']} - ${pos['end_time']}', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowSlate600, - ), - ), - if (pos['location'].toString().isNotEmpty) ...[ - const SizedBox(width: 16), - const Icon( - LucideIcons.mapPin, - size: 14, - color: AppColors.krowSlate400, - ), - const SizedBox(width: 6), - Expanded( - child: Text( - pos['location'], - style: const TextStyle( - fontSize: 12, - color: AppColors.krowSlate600, - ), - overflow: TextOverflow.ellipsis, - ), - ), - ], - ], - ), - ], - ), - ); - }), - - const SizedBox(height: 80), - ], - ), - ), - ), - - // Footer - Container( - padding: const EdgeInsets.all(20), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: AppColors.krowSlate200)), - ), - child: SafeArea( - top: false, - child: Row( - children: [ - Expanded( - child: OutlinedButton( - onPressed: () => setState(() => _showReview = false), - style: OutlinedButton.styleFrom( - foregroundColor: AppColors.krowSlate900, - side: const BorderSide(color: AppColors.krowSlate300), - minimumSize: const Size(double.infinity, 48), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: const Text('Edit'), - ), - ), - const SizedBox(width: 12), - Expanded( - child: ElevatedButton( - onPressed: _isLoading ? null : _submit, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - foregroundColor: Colors.white, - minimumSize: const Size(double.infinity, 48), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: _isLoading - ? const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - color: Colors.white, - strokeWidth: 2, - ), - ) - : const Text( - 'Confirm & Post', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - ], - ), - ), - ), - ], - ), - ); - } - - Widget _buildSuccessView() { - return Container( - width: double.infinity, - height: MediaQuery.of(context).size.height * 0.95, - decoration: const BoxDecoration( - color: AppColors.krowBlue, // Primary background - borderRadius: BorderRadius.vertical(top: Radius.circular(24)), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 80, - height: 80, - decoration: const BoxDecoration( - color: Color(0xFFF9E547), // krowYellow (Accent) - shape: BoxShape.circle, - ), - child: const Center( - child: Icon( - LucideIcons.check, - size: 40, - color: AppColors.krowCharcoal, - ), - ), - ), - const SizedBox(height: 24), - const Text( - 'Order Updated!', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - const SizedBox(height: 12), - const Padding( - padding: EdgeInsets.symmetric(horizontal: 40), - child: Text( - 'Your shift has been updated successfully.', - textAlign: TextAlign.center, - style: TextStyle(color: Colors.white70, fontSize: 16), - ), - ), - const SizedBox(height: 40), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 40), - child: ElevatedButton( - onPressed: widget.onBack, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.white, - foregroundColor: AppColors.krowBlue, - minimumSize: const Size(double.infinity, 56), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), - ), - child: const Text( - 'Back to Orders', - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), - ), - ), - ), - ], - ), - ); - } - - Widget _buildSectionLabel(String text) { - return Padding( - padding: const EdgeInsets.only(bottom: 6), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - text, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: AppColors.krowSlate600, - ), - ), - ), - ); - } - - Widget _buildTextField({ - required TextEditingController controller, - String? hint, - IconData? icon, - String? error, - }) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextField( - controller: controller, - decoration: InputDecoration( - hintText: hint, - hintStyle: const TextStyle(color: AppColors.krowSlate400), - prefixIcon: icon != null - ? Icon(icon, size: 18, color: AppColors.krowSlate400) - : null, - filled: true, - fillColor: Colors.white, - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 14, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: BorderSide( - color: error != null - ? AppColors.krowRed500 - : AppColors.krowSlate200, - ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: BorderSide( - color: error != null - ? AppColors.krowRed500 - : AppColors.krowSlate200, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowBlue, width: 2), - ), - ), - ), - if (error != null) - Padding( - padding: const EdgeInsets.only(top: 4, left: 4), - child: Text( - error, - style: const TextStyle(fontSize: 11, color: AppColors.krowRed500), - ), - ), - ], - ); - } - - Widget _buildDatePicker({ - required TextEditingController controller, - String? error, - }) { - return GestureDetector( - onTap: () async { - final picked = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime.now(), - lastDate: DateTime.now().add(const Duration(days: 365)), - ); - if (picked != null) { - controller.text = picked.toIso8601String().split('T')[0]; - } - }, - child: AbsorbPointer( - child: _buildTextField( - controller: controller, - hint: 'Select Date', - icon: LucideIcons.calendar, - error: error, - ), - ), - ); - } - - Widget _buildPositionCard(int index, Map pos) { - return Container( - margin: const EdgeInsets.only(bottom: 16), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: AppColors.krowSlate100, width: 2), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Header - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - width: 24, - height: 24, - decoration: const BoxDecoration( - color: AppColors.krowBlue, - shape: BoxShape.circle, - ), - child: Center( - child: Text( - '${index + 1}', - style: const TextStyle( - color: Colors.white, - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - const SizedBox(width: 8), - Text( - 'Position ${index + 1}', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: AppColors.krowSlate500, - ), - ), - ], - ), - if (_positions.length > 1) - GestureDetector( - onTap: () => _removePosition(index), - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - color: Color(0xFFFEF2F2), // red-50 - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.x, - size: 14, - color: AppColors.krowRed600, - ), - ), - ), - ], - ), - const SizedBox(height: 16), - - // Role - DropdownButtonFormField( - value: pos['role'].toString().isNotEmpty ? pos['role'] : null, - hint: const Text('Select role *'), - icon: const Icon( - LucideIcons.chevronDown, - size: 14, - color: AppColors.krowSlate600, - ), - items: _roles.map((r) { - return DropdownMenuItem( - value: r, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(r), - const SizedBox(width: 8), - Text( - '\$${_roleRates[r]?.toStringAsFixed(0)}/hr', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowSlate500, - ), - ), - ], - ), - ); - }).toList(), - onChanged: (val) => _updatePosition(index, 'role', val), - decoration: InputDecoration( - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 12, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowSlate200), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: BorderSide( - color: _errors['role_$index'] != null - ? AppColors.krowRed500 - : AppColors.krowSlate200, - ), - ), - ), - ), - if (_errors['role_$index'] != null) - Padding( - padding: const EdgeInsets.only(top: 4, left: 4), - child: Text( - _errors['role_$index']!, - style: const TextStyle( - fontSize: 11, - color: AppColors.krowRed500, - ), - ), - ), - - const SizedBox(height: 12), - - // Grid: Start, End, Workers - Row( - children: [ - Expanded(child: _buildTimeInput(index, 'start_time', 'Start *')), - const SizedBox(width: 8), - Expanded(child: _buildTimeInput(index, 'end_time', 'End *')), - const SizedBox(width: 8), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Workers', - style: TextStyle( - fontSize: 11, - color: AppColors.krowSlate600, - ), - ), - const SizedBox(height: 4), - Container( - height: 48, - decoration: BoxDecoration( - border: Border.all(color: AppColors.krowSlate200), - borderRadius: BorderRadius.circular(12), - ), - child: Row( - children: [ - _buildCounterBtn( - icon: LucideIcons.minus, - onTap: () { - int count = pos['count']; - if (count > 1) - _updatePosition(index, 'count', count - 1); - }, - ), - Expanded( - child: Center( - child: Text( - '${pos['count']}', - style: const TextStyle( - fontWeight: FontWeight.bold, - ), - ), - ), - ), - _buildCounterBtn( - icon: LucideIcons.plus, - onTap: () { - int count = pos['count']; - _updatePosition(index, 'count', count + 1); - }, - ), - ], - ), - ), - ], - ), - ), - ], - ), - - const SizedBox(height: 12), - - // Location Override - if (pos['show_location_override'] != true) - Align( - alignment: Alignment.centerLeft, - child: TextButton.icon( - onPressed: () => - _updatePosition(index, 'show_location_override', true), - icon: const Icon(LucideIcons.mapPin, size: 14), - label: const Text('Use different location'), - style: TextButton.styleFrom( - foregroundColor: AppColors.krowBlue600, - textStyle: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - padding: EdgeInsets.zero, - minimumSize: Size.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - ), - ) - else - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Row( - children: [ - Icon( - LucideIcons.mapPin, - size: 14, - color: AppColors.krowSlate600, - ), - SizedBox(width: 4), - Text( - 'Different Location', - style: TextStyle( - fontSize: 12, - color: AppColors.krowSlate600, - ), - ), - ], - ), - GestureDetector( - onTap: () { - _updatePosition(index, 'show_location_override', false); - _updatePosition(index, 'location', ''); - }, - child: const Icon( - LucideIcons.x, - size: 14, - color: AppColors.krowRed600, - ), - ), - ], - ), - const SizedBox(height: 4), - TextField( - onChanged: (val) => _updatePosition(index, 'location', val), - decoration: InputDecoration( - hintText: 'Enter address', - contentPadding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 12, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowSlate200, - ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: BorderSide( - color: _errors['location_$index'] != null - ? AppColors.krowRed500 - : AppColors.krowSlate200, - ), - ), - ), - ), - if (_errors['location_$index'] != null) - Text( - _errors['location_$index']!, - style: const TextStyle( - fontSize: 11, - color: AppColors.krowRed500, - ), - ), - ], - ), - - const SizedBox(height: 12), - - // Lunch Break - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Lunch Break', - style: TextStyle(fontSize: 11, color: AppColors.krowSlate600), - ), - const SizedBox(height: 4), - DropdownButtonFormField( - value: pos['lunch_break'], - items: const [ - DropdownMenuItem(value: 0, child: Text('No break')), - DropdownMenuItem(value: 30, child: Text('30 min (Unpaid)')), - DropdownMenuItem(value: 60, child: Text('60 min (Unpaid)')), - ], - icon: const Icon( - LucideIcons.chevronDown, - size: 14, - color: AppColors.krowSlate600, - ), - onChanged: (val) => _updatePosition(index, 'lunch_break', val), - decoration: InputDecoration( - contentPadding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 0, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: AppColors.krowSlate200), - ), - ), - ), - ], - ), - - if (pos['role'].toString().isNotEmpty) ...[ - const SizedBox(height: 12), - const Divider(color: AppColors.krowSlate100), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Rate per hour', - style: TextStyle(fontSize: 12, color: AppColors.krowSlate600), - ), - Row( - children: [ - const Icon( - LucideIcons.dollarSign, - size: 14, - color: AppColors.krowEmerald600, - ), - Text( - '${_roleRates[pos['role']]?.toStringAsFixed(0)}', - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowEmerald600, - ), - ), - const Text( - '/hr', - style: TextStyle( - fontSize: 12, - color: AppColors.krowSlate500, - ), - ), - ], - ), - ], - ), - ], - ], - ), - ); - } - - Widget _buildTimeInput(int index, String field, String label) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Icon( - LucideIcons.clock, - size: 12, - color: AppColors.krowSlate600, - ), - const SizedBox(width: 4), - Text( - label, - style: const TextStyle( - fontSize: 11, - color: AppColors.krowSlate600, - ), - ), - ], - ), - const SizedBox(height: 4), - GestureDetector( - onTap: () async { - final picked = await showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ); - if (picked != null) { - final formatted = - '${picked.hour.toString().padLeft(2, '0')}:${picked.minute.toString().padLeft(2, '0')}'; - _updatePosition(index, field, formatted); - } - }, - child: Container( - height: 48, - padding: const EdgeInsets.symmetric(horizontal: 12), - alignment: Alignment.centerLeft, - decoration: BoxDecoration( - border: Border.all( - color: _errors['${field}_$index'] != null - ? AppColors.krowRed500 - : AppColors.krowSlate200, - ), - borderRadius: BorderRadius.circular(12), - color: Colors.white, - ), - child: Text( - _positions[index][field].toString().isEmpty - ? '--:--' - : _positions[index][field], - style: TextStyle( - color: _positions[index][field].toString().isEmpty - ? AppColors.krowSlate400 - : AppColors.krowSlate900, - ), - ), - ), - ), - if (_errors['${field}_$index'] != null) - Text( - _errors['${field}_$index']!, - style: const TextStyle(fontSize: 10, color: AppColors.krowRed500), - ), - ], - ); - } - - Widget _buildCounterBtn({ - required IconData icon, - required VoidCallback onTap, - }) { - return GestureDetector( - onTap: onTap, - child: Container( - width: 32, - color: Colors.transparent, - child: Icon(icon, size: 16, color: AppColors.krowSlate600), - ), - ); - } - - Widget _buildSummaryItem(String value, String label) { - return Column( - children: [ - Text( - value, - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowBlue, - ), - ), - Text( - label, - style: const TextStyle(fontSize: 12, color: AppColors.krowSlate500), - ), - ], - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_timesheets_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_timesheets_screen.dart deleted file mode 100644 index 483060bb..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_timesheets_screen.dart +++ /dev/null @@ -1,766 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; - -class ClientTimesheetsScreen extends StatefulWidget { - const ClientTimesheetsScreen({super.key}); - - @override - State createState() => _ClientTimesheetsScreenState(); -} - -class _ClientTimesheetsScreenState extends State - with SingleTickerProviderStateMixin { - late TabController _tabController; - final TextEditingController _searchController = TextEditingController(); - - List> _timesheets = []; - - @override - void initState() { - super.initState(); - _tabController = TabController(length: 4, vsync: this); - _timesheets = [ - { - 'id': '1', - 'staffName': 'John Doe', - 'status': 'pending', - 'date': 'Jan 24', - 'startTime': '09:00 AM', - 'endTime': '05:00 PM', - 'totalHours': 8.0, - 'hourlyRate': 25.0, - 'totalPay': 200.00, - }, - { - 'id': '2', - 'staffName': 'Jane Smith', - 'status': 'pending', - 'date': 'Jan 24', - 'startTime': '10:00 AM', - 'endTime': '06:00 PM', - 'totalHours': 8.0, - 'hourlyRate': 22.0, - 'totalPay': 176.00, - }, - { - 'id': '3', - 'staffName': 'Mike Ross', - 'status': 'pending', - 'date': 'Jan 24', - 'startTime': '08:00 AM', - 'endTime': '12:00 PM', - 'totalHours': 4.0, - 'hourlyRate': 18.5, - 'totalPay': 74.00, - }, - { - 'id': '4', - 'staffName': 'Alice Wonderland', - 'status': 'approved', - 'date': 'Jan 23', - 'startTime': '09:00 AM', - 'endTime': '05:00 PM', - 'totalHours': 8.0, - 'hourlyRate': 25.0, - 'totalPay': 200.00, - }, - { - 'id': '5', - 'staffName': 'Bob The Builder', - 'status': 'paid', - 'date': 'Jan 22', - 'startTime': '10:00 AM', - 'endTime': '06:00 PM', - 'totalHours': 8.0, - 'hourlyRate': 22.0, - 'totalPay': 176.00, - }, - { - 'id': '6', - 'staffName': 'Charlie Chaplin', - 'status': 'disputed', - 'date': 'Jan 21', - 'startTime': '08:00 AM', - 'endTime': '12:00 PM', - 'totalHours': 4.0, - 'hourlyRate': 18.5, - 'totalPay': 74.00, - }, - ]; - } - - void _approveTimesheet(String id) { - setState(() { - final index = _timesheets.indexWhere((ts) => ts['id'] == id); - if (index != -1) { - _timesheets[index]['status'] = 'approved'; - } - }); - } - - void _disputeTimesheet(String id) { - setState(() { - final index = _timesheets.indexWhere((ts) => ts['id'] == id); - if (index != -1) { - _timesheets[index]['status'] = 'disputed'; - } - }); - } - - void _approveAllPendingTimesheets() { - setState(() { - for (var ts in _timesheets) { - if (ts['status'] == 'pending') { - ts['status'] = 'approved'; - } - } - }); - } - - @override - void dispose() { - _tabController.dispose(); - _searchController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: SafeArea( - child: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) { - return [ - SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Header Row - Row( - children: [ - GestureDetector( - onTap: () => context.go('/client-home'), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.grey.shade100, - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: AppColors.krowCharcoal, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - const Text( - 'Timesheets', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - const SizedBox(height: 16), - - // Summary Cards - Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Colors.amber.shade50, - Colors.yellow.shade50, - ], - ), - borderRadius: BorderRadius.circular(12), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon( - LucideIcons.clock, - size: 14, - color: Colors.amber.shade600, - ), - const SizedBox(width: 4), - Text( - 'Pending', - style: TextStyle( - fontSize: 12, - color: Colors.grey.shade600, - ), - ), - ], - ), - const SizedBox(height: 4), - const Text( - '3 timesheets', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 2), - Text( - '\$450.00', - style: TextStyle( - fontSize: 14, - color: Colors.amber.shade700, - ), - ), - ], - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Colors.green.shade50, - Colors.greenAccent.shade100.withOpacity( - 0.2, - ), - ], // Changed from emerald - ), - borderRadius: BorderRadius.circular(12), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon( - LucideIcons.checkCircle, - size: 14, - color: Colors.green.shade600, - ), // Changed from emerald - const SizedBox(width: 4), - Text( - 'Approved', - style: TextStyle( - fontSize: 12, - color: Colors.grey.shade600, - ), - ), - ], - ), - const SizedBox(height: 4), - const Text( - 'This Week', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 2), - Text( - '\$1,200.00', - style: TextStyle( - fontSize: 14, - color: Colors.green.shade700, - ), // Changed from emerald - ), - ], - ), - ), - ), - ], - ), - - const SizedBox(height: 16), - // Search Bar - TextField( - controller: _searchController, - decoration: InputDecoration( - hintText: 'Search by worker name...', - prefixIcon: const Icon( - LucideIcons.search, - color: AppColors.krowMuted, - ), - filled: true, - fillColor: Colors.white, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: BorderSide.none, - ), - contentPadding: const EdgeInsets.symmetric( - vertical: 0, - ), - ), - ), - const SizedBox(height: 16), - // Tabs - Container( - height: 36, - decoration: BoxDecoration( - color: Colors.grey.shade200, - borderRadius: BorderRadius.circular(10), - ), - child: TabBar( - controller: _tabController, - indicator: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - ), - ], - ), - labelColor: AppColors.krowCharcoal, - unselectedLabelColor: AppColors.krowMuted, - labelStyle: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - padding: const EdgeInsets.all(2), - indicatorSize: TabBarIndicatorSize.tab, - tabs: [ - Tab( - text: - 'Pending (${_timesheets.where((ts) => ts['status'] == 'pending').length})', - ), - Tab( - text: - 'Approved (${_timesheets.where((ts) => ts['status'] == 'approved').length})', - ), - Tab( - text: - 'Paid (${_timesheets.where((ts) => ts['status'] == 'paid').length})', - ), - Tab( - text: - 'Disputed (${_timesheets.where((ts) => ts['status'] == 'disputed').length})', - ), - ], - ), - ), - ], - ), - ), - ), - ]; - }, - body: TabBarView( - controller: _tabController, - children: [ - _TimesheetList( - timesheets: _timesheets - .where((ts) => ts['status'] == 'pending') - .toList(), - onApproveAll: _approveAllPendingTimesheets, - onApprove: _approveTimesheet, - onDispute: _disputeTimesheet, - ), - _TimesheetList( - timesheets: _timesheets - .where((ts) => ts['status'] == 'approved') - .toList(), - onApproveAll: - _approveAllPendingTimesheets, // Still needed for consistency - onApprove: _approveTimesheet, - onDispute: _disputeTimesheet, - ), - _TimesheetList( - timesheets: _timesheets - .where((ts) => ts['status'] == 'paid') - .toList(), - onApproveAll: - _approveAllPendingTimesheets, // Still needed for consistency - onApprove: _approveTimesheet, - onDispute: _disputeTimesheet, - ), - _TimesheetList( - timesheets: _timesheets - .where((ts) => ts['status'] == 'disputed') - .toList(), - onApproveAll: - _approveAllPendingTimesheets, // Still needed for consistency - onApprove: _approveTimesheet, - onDispute: _disputeTimesheet, - ), - ], - ), - ), - ), - floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, - floatingActionButton: Padding( - padding: const EdgeInsets.only(bottom: 80), - child: SizedBox( - height: 48, - child: ElevatedButton.icon( - onPressed: () {}, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.white, - foregroundColor: AppColors.krowCharcoal, - elevation: 4, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - side: BorderSide(color: Colors.grey.shade200), - ), - icon: const Icon(LucideIcons.download, size: 18), - label: const Text('Export Timesheets'), - ), - ), - ), - ); - } -} - -class _TimesheetList extends StatelessWidget { - final List> timesheets; - final VoidCallback onApproveAll; - final Function(String id) onApprove; - final Function(String id) onDispute; - - const _TimesheetList({ - super.key, - required this.timesheets, - required this.onApproveAll, - required this.onApprove, - required this.onDispute, - }); - - @override - Widget build(BuildContext context) { - if (timesheets.isEmpty) { - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon( - LucideIcons.clock, - size: 48, - color: AppColors.krowBorder, - ), - const SizedBox(height: 16), - Text( - 'No timesheets', - style: const TextStyle(color: AppColors.krowMuted), - ), - ], - ), - ); - } - - // Determine if any timesheets are pending for the "Approve All" banner - final bool hasPendingTimesheets = timesheets.any( - (ts) => ts['status'] == 'pending', - ); - final int pendingCount = timesheets - .where((ts) => ts['status'] == 'pending') - .length; - - return ListView( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 140), - children: [ - if (hasPendingTimesheets) - // Approve All Banner - Container( - padding: const EdgeInsets.all(12), - margin: const EdgeInsets.only(bottom: 16), - decoration: BoxDecoration( - color: Colors.purple.shade50, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: Colors.purple.shade100), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - '$pendingCount pending approval', - style: TextStyle( - color: Colors.purple.shade700, - fontSize: 14, - fontWeight: FontWeight.w500, - ), - ), - ElevatedButton.icon( - onPressed: onApproveAll, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.purple.shade600, - foregroundColor: Colors.white, - elevation: 0, - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - minimumSize: Size.zero, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - icon: const Icon(LucideIcons.checkCircle, size: 14), - label: const Text( - 'Approve All', - style: TextStyle(fontSize: 12), - ), - ), - ], - ), - ), - - ...timesheets.map( - (timesheet) => Padding( - padding: const EdgeInsets.only(bottom: 12), - child: _TimesheetCard( - timesheet: timesheet, - onApprove: onApprove, - onDispute: onDispute, - ), - ), - ), - ], - ); - } -} - -class _TimesheetCard extends StatelessWidget { - final Map timesheet; - final Function(String id) onApprove; - final Function(String id) onDispute; - - const _TimesheetCard({ - super.key, - required this.timesheet, - required this.onApprove, - required this.onDispute, - }); - - @override - Widget build(BuildContext context) { - final String staffName = timesheet['staffName']; - final String status = timesheet['status']; - final String date = timesheet['date']; - final String startTime = timesheet['startTime']; - final String endTime = timesheet['endTime']; - final double totalHours = timesheet['totalHours']; - final double hourlyRate = timesheet['hourlyRate']; - final double totalPay = timesheet['totalPay']; - - Color statusBg; - Color statusText; - - switch (status) { - case 'pending': - statusBg = Colors.amber.shade100; - statusText = Colors.amber.shade700; - break; - case 'approved': - statusBg = Colors.green.shade100; - statusText = Colors.green.shade700; - break; - case 'paid': - statusBg = Colors.blue.shade100; - statusText = Colors.blue.shade700; - break; - case 'disputed': - statusBg = Colors.red.shade100; - statusText = Colors.red.shade700; - break; - default: - statusBg = Colors.grey.shade100; - statusText = Colors.grey.shade700; - } - - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.02), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.purple.shade100, - shape: BoxShape.circle, - ), - child: Center( - child: Text( - staffName[0], - style: TextStyle( - color: Colors.purple.shade700, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - staffName, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), - decoration: BoxDecoration( - color: statusBg, - borderRadius: BorderRadius.circular(6), - ), - child: Text( - status.toUpperCase(), - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: statusText, - ), - ), - ), - ], - ), - const SizedBox(height: 8), - Row( - children: [ - Icon( - LucideIcons.calendar, - size: 12, - color: AppColors.krowMuted, - ), - const SizedBox(width: 4), - Text( - date, - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - const SizedBox(width: 12), - Icon( - LucideIcons.clock, - size: 12, - color: AppColors.krowMuted, - ), - const SizedBox(width: 4), - Text( - '$startTime - $endTime', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text( - '$totalHours hrs', - style: const TextStyle( - fontSize: 14, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(width: 4), - Text( - '@ \$$hourlyRate/hr', - style: const TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - ), - ), - ], - ), - Text( - '\$${totalPay.toStringAsFixed(2)}', - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - if (status == 'pending') ...[ - const SizedBox(height: 12), - Row( - children: [ - Expanded( - child: ElevatedButton.icon( - onPressed: () => onApprove(timesheet['id']), - style: ElevatedButton.styleFrom( - backgroundColor: Colors.green.shade500, - foregroundColor: Colors.white, - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - icon: const Icon(LucideIcons.checkCircle, size: 14), - label: const Text('Approve'), - ), - ), - const SizedBox(width: 12), - Expanded( - child: OutlinedButton.icon( - onPressed: () => onDispute(timesheet['id']), - style: OutlinedButton.styleFrom( - foregroundColor: Colors.red.shade600, - side: BorderSide(color: Colors.red.shade200), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - icon: const Icon(LucideIcons.alertCircle, size: 14), - label: const Text('Dispute'), - ), - ), - ], - ), - ], - ], - ), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_workers_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_workers_screen.dart deleted file mode 100644 index b5eeb0b3..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/client_workers_screen.dart +++ /dev/null @@ -1,747 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; - -class ClientWorkersScreen extends StatefulWidget { - const ClientWorkersScreen({super.key}); - - @override - State createState() => _ClientWorkersScreenState(); -} - -class _ClientWorkersScreenState extends State - with SingleTickerProviderStateMixin { - late TabController _tabController; - final TextEditingController _searchController = TextEditingController(); - - @override - void initState() { - super.initState(); - _tabController = TabController(length: 3, vsync: this); - } - - @override - void dispose() { - _tabController.dispose(); - _searchController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: SafeArea( - child: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) { - return [ - SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Header Row - Row( - children: [ - GestureDetector( - onTap: () => context.go('/client-home'), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.grey.shade100, - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: AppColors.krowCharcoal, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - const Text( - 'Smart Assign', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - const SizedBox(height: 16), - // Search Bar - TextField( - controller: _searchController, - decoration: InputDecoration( - hintText: 'Search workers by name or skill...', - prefixIcon: const Icon( - LucideIcons.search, - color: AppColors.krowMuted, - ), - filled: true, - fillColor: Colors.white, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: BorderSide.none, - ), - contentPadding: const EdgeInsets.symmetric( - vertical: 0, - ), - ), - ), - const SizedBox(height: 16), - // Tabs and Filter - Row( - children: [ - Expanded( - child: Container( - height: 36, - decoration: BoxDecoration( - color: Colors.grey.shade200, - borderRadius: BorderRadius.circular(10), - ), - child: TabBar( - controller: _tabController, - indicator: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 2, - ), - ], - ), - labelColor: AppColors.krowCharcoal, - unselectedLabelColor: AppColors.krowMuted, - labelStyle: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - padding: const EdgeInsets.all(2), - indicatorSize: TabBarIndicatorSize.tab, - tabs: const [ - Tab( - child: FittedBox( - fit: BoxFit.scaleDown, - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Icon(LucideIcons.sparkles, size: 12), - SizedBox(width: 4), - Text('AI Picks'), - ], - ), - ), - ), - Tab( - child: FittedBox( - fit: BoxFit.scaleDown, - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Icon(LucideIcons.star, size: 12), - SizedBox(width: 4), - Text('Top Rated'), - ], - ), - ), - ), - Tab( - child: FittedBox( - fit: BoxFit.scaleDown, - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Icon(LucideIcons.users, size: 12), - SizedBox(width: 4), - Text('Past'), - ], - ), - ), - ), - ], - ), - ), - ), - const SizedBox(width: 8), - GestureDetector( - onTap: () => _showFilterSheet(context), - child: Container( - height: 36, - padding: const EdgeInsets.symmetric(horizontal: 12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(10), - border: Border.all(color: AppColors.krowBorder), - ), - child: const Row( - children: [ - Icon( - LucideIcons.filter, - size: 14, - color: AppColors.krowCharcoal, - ), - SizedBox(width: 4), - Text( - 'Filters', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - ), - ), - ], - ), - ), - ), - ], - ), - ], - ), - ), - ), - ]; - }, - body: TabBarView( - controller: _tabController, - children: [ - _WorkerList(type: 'recommended'), - _WorkerList(type: 'top-rated'), - _WorkerList(type: 'past'), - ], - ), - ), - ), - ); - } - - void _showFilterSheet(BuildContext context) { - showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) => const _FilterSheet(), - ); - } -} - -class _FilterSheet extends StatefulWidget { - const _FilterSheet(); - - @override - State<_FilterSheet> createState() => _FilterSheetState(); -} - -class _FilterSheetState extends State<_FilterSheet> { - double _minRating = 4.0; - double _reliabilityScore = 80.0; - bool _certifiedOnly = false; - bool _pastWorkersOnly = false; - - @override - Widget build(BuildContext context) { - return Container( - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.vertical(top: Radius.circular(24)), - ), - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Filter Workers', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - IconButton( - icon: const Icon(LucideIcons.x, color: AppColors.krowMuted), - onPressed: () => Navigator.pop(context), - ), - ], - ), - const SizedBox(height: 24), - - // Min Rating - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Minimum Rating', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF334155), // slate-700 - ), - ), - Text( - '${_minRating.toStringAsFixed(1)}+ stars', - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: Color(0xFF7C3AED), // violet-600 - ), - ), - ], - ), - Slider( - value: _minRating, - min: 1.0, - max: 5.0, - divisions: 8, - activeColor: const Color(0xFF7C3AED), // violet-600 - onChanged: (value) => setState(() => _minRating = value), - ), - const SizedBox(height: 20), - - // Reliability Score - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Reliability Score', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF334155), // slate-700 - ), - ), - Text( - '${_reliabilityScore.toInt()}%+', - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: Color(0xFF7C3AED), // violet-600 - ), - ), - ], - ), - Slider( - value: _reliabilityScore, - min: 50.0, - max: 100.0, - divisions: 10, - activeColor: const Color(0xFF7C3AED), // violet-600 - onChanged: (value) => setState(() => _reliabilityScore = value), - ), - const SizedBox(height: 20), - - // Checkboxes - _buildCheckbox( - 'Certified Only', - LucideIcons.award, - Colors.amber, - _certifiedOnly, - (v) => setState(() => _certifiedOnly = v ?? false), - ), - const SizedBox(height: 12), - _buildCheckbox( - 'Past Workers Only', - LucideIcons.users, - Colors.blue, - _pastWorkersOnly, - (v) => setState(() => _pastWorkersOnly = v ?? false), - ), - - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: () { - // Apply filters logic would go here - Navigator.pop(context); - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF7C3AED), // violet-600 - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - textStyle: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - child: const Text('Apply Filters'), - ), - ), - const SizedBox(height: 24), // Bottom padding - ], - ), - ); - } - - Widget _buildCheckbox( - String label, - IconData icon, - Color iconColor, - bool value, - ValueChanged onChanged, - ) { - return InkWell( - onTap: () => onChanged(!value), - borderRadius: BorderRadius.circular(8), - child: Row( - children: [ - Checkbox( - value: value, - onChanged: onChanged, - activeColor: const Color(0xFF7C3AED), // violet-600 - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4), - ), - ), - Icon(icon, size: 16, color: iconColor), - const SizedBox(width: 8), - Text( - label, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF334155), // slate-700 - ), - ), - ], - ), - ); - } -} - -class _WorkerList extends StatelessWidget { - final String type; - - const _WorkerList({required this.type}); - - @override - Widget build(BuildContext context) { - return ListView( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 100), - children: [ - if (type == 'recommended') - Container( - margin: const EdgeInsets.only(bottom: 20), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [Colors.purple.shade50, Colors.deepPurple.shade50], - ), - borderRadius: BorderRadius.circular(16), - border: Border.all(color: Colors.purple.shade100), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: Colors.purple.shade100, - borderRadius: BorderRadius.circular(12), - ), - child: const Icon( - LucideIcons.sparkles, - color: Colors.purple, - size: 20, - ), - ), - const SizedBox(width: 12), - const Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'AI-Powered Matching', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - SizedBox(height: 4), - Text( - 'Workers ranked by performance, reliability, skills match, and past work history with your company.', - style: TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - ], - ), - ), - - const Text( - '12 workers found', - style: TextStyle(fontSize: 14, color: AppColors.krowMuted), - ), - const SizedBox(height: 12), - - // Mock Staff / Workers - _WorkerCard( - name: 'Sarah Wilson', - role: 'Head Server', - averageRating: 4.9, - totalShifts: 142, - reliabilityScore: 98, - isRecommended: type == 'recommended', - photoUrl: 'https://i.pravatar.cc/150?u=sarah', - ), - const SizedBox(height: 12), - _WorkerCard( - name: 'Michael Chen', - role: 'Bartender', - averageRating: 4.8, - totalShifts: 89, - reliabilityScore: 95, - isRecommended: type == 'recommended', - photoUrl: 'https://i.pravatar.cc/150?u=michael', - ), - const SizedBox(height: 12), - _WorkerCard( - name: 'Jessica Davis', - role: 'Event Staff', - averageRating: 4.7, - totalShifts: 215, - reliabilityScore: 92, - isRecommended: false, // Only top 2 recommended - photoUrl: 'https://i.pravatar.cc/150?u=jessica', - ), - ], - ); - } -} - -class _WorkerCard extends StatelessWidget { - final String name; - final String role; - final double averageRating; - final int totalShifts; - final int reliabilityScore; - final bool isRecommended; - final String photoUrl; - - const _WorkerCard({ - required this.name, - required this.role, - required this.averageRating, - required this.totalShifts, - required this.reliabilityScore, - required this.isRecommended, - required this.photoUrl, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: isRecommended ? Colors.purple.shade200 : AppColors.krowBorder, - width: isRecommended ? 1.5 : 1, - ), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.02), - blurRadius: 8, - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Avatar - Container( - width: 60, - height: 60, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - image: DecorationImage( - image: NetworkImage(photoUrl), - fit: BoxFit.cover, - ), - ), - ), - const SizedBox(width: 12), - // Info - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - name, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - overflow: TextOverflow.ellipsis, - ), - ), - if (isRecommended) - Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 2, - ), - decoration: BoxDecoration( - color: Colors.purple.shade50, - borderRadius: BorderRadius.circular(100), - border: Border.all(color: Colors.purple.shade100), - ), - child: Row( - children: [ - Icon( - LucideIcons.sparkles, - size: 10, - color: Colors.purple.shade600, - ), - const SizedBox(width: 4), - Text( - 'Best Match', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: Colors.purple.shade700, - ), - ), - ], - ), - ), - ], - ), - const SizedBox(height: 4), - Text( - role, - style: const TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 8), - // Stats Row - Wrap( - spacing: 8, - runSpacing: 4, - children: [ - _StatBadge( - icon: LucideIcons.star, - text: '$averageRating', - color: Colors.amber, - ), - _StatBadge( - icon: LucideIcons.briefcase, - text: '$totalShifts jobs', - color: Colors.blue, - ), - _StatBadge( - icon: LucideIcons.shieldCheck, - text: '$reliabilityScore%', - color: Colors.green, - ), - ], - ), - ], - ), - ), - ], - ), - const SizedBox(height: 16), - // Buttons - Row( - children: [ - Expanded( - child: OutlinedButton( - onPressed: () {}, - style: OutlinedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 12), - side: const BorderSide(color: AppColors.krowBorder), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - child: const Text( - 'View Profile', - style: TextStyle(color: AppColors.krowCharcoal), - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: ElevatedButton( - onPressed: () {}, - style: ElevatedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 12), - backgroundColor: AppColors.krowBlue, - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - child: const Text( - 'Direct Offer', - style: TextStyle(color: Colors.white), - ), - ), - ), - ], - ), - ], - ), - ); - } -} - -class _StatBadge extends StatelessWidget { - final IconData icon; - final String text; - final Color color; - - const _StatBadge({ - required this.icon, - required this.text, - required this.color, - }); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Icon(icon, size: 12, color: color), - const SizedBox(width: 4), - Text( - text, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: AppColors.krowCharcoal, - ), - ), - ], - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/coverage_dashboard.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/coverage_dashboard.dart deleted file mode 100644 index 109f170c..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/coverage_dashboard.dart +++ /dev/null @@ -1,330 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; - -class CoverageDashboard extends StatelessWidget { - const CoverageDashboard({ - super.key, - required this.shifts, - required this.applications, - }); - - final List shifts; - final List applications; - - @override - Widget build(BuildContext context) { - // Mock Data Logic (simulating React component) - final todayShifts = - shifts; // Assuming shifts passed are already filtered or we treat all as 'today' for mock - - // Calculate coverage stats - // Mock data structures: - // shift: { workersNeeded: int, filled: int, status: String, hourlyRate: double } - // application: { status: String, checkInTime: String? } - - int totalNeeded = 0; - int totalConfirmed = 0; - double todayCost = 0; - - for (var s in todayShifts) { - // Handle map or object access safely for mock - final needed = s['workersNeeded'] as int? ?? 0; - final confirmed = s['filled'] as int? ?? 0; - final rate = s['hourlyRate'] as double? ?? 20.0; - - totalNeeded += needed; - totalConfirmed += confirmed; - todayCost += rate * 8 * confirmed; // 8 hours avg - } - - final coveragePercent = totalNeeded > 0 - ? ((totalConfirmed / totalNeeded) * 100).round() - : 100; - final unfilledPositions = totalNeeded - totalConfirmed; - - // Mock status counts from applications - final checkedInCount = applications - .where((a) => a['checkInTime'] != null) - .length; - final lateWorkersCount = applications - .where((a) => a['status'] == 'LATE') - .length; - - // Colors - final isCoverageGood = coveragePercent >= 90; - final coverageBadgeColor = isCoverageGood - ? const Color(0xFFD1FAE5) - : const Color(0xFFFEF3C7); // emerald-100 vs amber-100 - final coverageTextColor = isCoverageGood - ? const Color(0xFF047857) - : const Color(0xFFB45309); // emerald-700 vs amber-700 - - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: AppColors.krowBorder, - ), // border-0 in React but typically cards have borders in Flutter or shadow - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.02), - blurRadius: 4, - offset: const Offset(0, 1), - ), - ], - ), - child: Column( - children: [ - // Header - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - "Today's Status", - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 14, - color: AppColors.krowCharcoal, - ), - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), - decoration: BoxDecoration( - color: coverageBadgeColor, - borderRadius: BorderRadius.circular(10), - ), - child: Text( - '$coveragePercent% Covered', - style: TextStyle( - fontSize: 10, // approximate text-xs/Badge size - fontWeight: FontWeight.bold, - color: coverageTextColor, - ), - ), - ), - ], - ), - const SizedBox(height: 16), - - // Grid - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Column 1 - Expanded( - child: Column( - children: [ - // Unfilled / Filled Status - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: unfilledPositions > 0 - ? const Color(0xFFFFFBEB) - : const Color(0xFFECFDF5), // amber-50 : emerald-50 - border: Border.all( - color: unfilledPositions > 0 - ? const Color(0xFFFDE68A) - : const Color( - 0xFFA7F3D0, - ), // amber-200 : emerald-200 - ), - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon( - LucideIcons.alertTriangle, - size: 16, - color: unfilledPositions > 0 - ? const Color(0xFFD97706) - : const Color( - 0xFF059669, - ), // amber-600 : emerald-600 - ), - const SizedBox(width: 8), - Text( - 'Unfilled Today', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: unfilledPositions > 0 - ? const Color(0xFF78350F) - : const Color( - 0xFF064E3B, - ), // amber-900 : emerald-900 - ), - ), - ], - ), - const SizedBox(height: 4), - Text( - '$unfilledPositions', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: unfilledPositions > 0 - ? const Color(0xFFB45309) - : const Color( - 0xFF047857, - ), // amber-700 : emerald-700 - ), - ), - ], - ), - ), - const SizedBox(height: 8), - // Running Late (Conditional) - if (lateWorkersCount > 0) - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFFFEF2F2), // red-50 - border: Border.all( - color: const Color(0xFFFECACA), - ), // red-200 - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Icon( - LucideIcons.alertTriangle, - size: 16, - color: Color(0xFFDC2626), // red-600 - ), - const SizedBox(width: 8), - const Text( - 'Running Late', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF7F1D1D), // red-900 - ), - ), - ], - ), - const SizedBox(height: 4), - Text( - '$lateWorkersCount', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Color(0xFFB91C1C), // red-700 - ), - ), - ], - ), - ), - ], - ), - ), - const SizedBox(width: 8), - // Column 2 - Expanded( - child: Column( - children: [ - // Checked In - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFFEFF6FF), // blue-50 - border: Border.all( - color: const Color(0xFFBFDBFE), - ), // blue-200 - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Icon( - LucideIcons.checkCircle, - size: 16, - color: Color(0xFF2563EB), // blue-600 - ), - const SizedBox(width: 8), - const Text( - 'Checked In', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF1E3A8A), // blue-900 - ), - ), - ], - ), - const SizedBox(height: 4), - Text( - '$checkedInCount/$totalConfirmed', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Color(0xFF1D4ED8), // blue-700 - ), - ), - ], - ), - ), - const SizedBox(height: 8), - // Today's Cost - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFFEFF6FF), // blue-50 - border: Border.all( - color: const Color(0xFFBFDBFE), - ), // blue-200 - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Icon( - LucideIcons.dollarSign, - size: 16, - color: Color(0xFF2563EB), // blue-600 - ), - const SizedBox(width: 8), - const Text( - 'Today\'s Cost', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xFF1E3A8A), // blue-900 - ), - ), - ], - ), - const SizedBox(height: 4), - Text( - '\$${todayCost.round()}', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Color(0xFF1D4ED8), // blue-700 - ), - ), - ], - ), - ), - ], - ), - ), - ], - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/one_time_order_flow_page.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/one_time_order_flow_page.dart deleted file mode 100644 index 23a9bd7c..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/one_time_order_flow_page.dart +++ /dev/null @@ -1,789 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:intl/intl.dart'; - -// Color constants from React - Global access -const Color reactPrimary = Color(0xFF0A39DF); -const Color reactAccent = Color(0xFFF9E547); -const Color reactForeground = Color(0xFF121826); -const Color reactMuted = Color(0xFF6A7382); -const Color reactBackground = Color(0xFFFAFBFC); -const Color reactBorder = Color(0xFFE3E6E9); - -class OneTimeOrderFlowPage extends StatefulWidget { - const OneTimeOrderFlowPage({super.key}); - - @override - State createState() => _OneTimeOrderFlowPageState(); -} - -class _Position { - String role; - int count; - String startTime; - String endTime; - int lunchBreak; - String location; - bool showLocationOverride; - - _Position({ - this.role = '', - this.count = 1, - this.startTime = '', - this.endTime = '', - this.lunchBreak = 30, - this.location = '', - this.showLocationOverride = false, - }); -} - -class _OneTimeOrderFlowPageState extends State { - bool _submitted = false; - bool _isCreating = false; - - final TextEditingController _dateController = TextEditingController(); - final TextEditingController _locationController = TextEditingController(); - - final List<_Position> _positions = [_Position()]; - - final List> _roles = [ - {'name': 'Server', 'rate': 18.0}, - {'name': 'Bartender', 'rate': 22.0}, - {'name': 'Cook', 'rate': 20.0}, - {'name': 'Busser', 'rate': 16.0}, - {'name': 'Host', 'rate': 17.0}, - {'name': 'Barista', 'rate': 16.0}, - {'name': 'Dishwasher', 'rate': 15.0}, - {'name': 'Event Staff', 'rate': 20.0}, - ]; - - void _addPosition() { - setState(() { - _positions.add(_Position()); - }); - } - - void _removePosition(int index) { - if (_positions.length > 1) { - setState(() { - _positions.removeAt(index); - }); - } - } - - void _updatePosition(int index, String field, dynamic value) { - setState(() { - if (field == 'role') { - _positions[index].role = value; - } else if (field == 'count') { - _positions[index].count = value; - } else if (field == 'startTime') { - _positions[index].startTime = value; - } else if (field == 'endTime') { - _positions[index].endTime = value; - } else if (field == 'lunchBreak') { - _positions[index].lunchBreak = value; - } else if (field == 'location') { - _positions[index].location = value; - } else if (field == 'showLocationOverride') { - _positions[index].showLocationOverride = value; - } - }); - } - - Future _handleSubmit() async { - setState(() => _isCreating = true); - await Future.delayed(const Duration(milliseconds: 800)); - if (mounted) { - setState(() { - _isCreating = false; - _submitted = true; - }); - } - } - - @override - Widget build(BuildContext context) { - if (_submitted) { - return const _SuccessView(); - } - - return Scaffold( - backgroundColor: reactBackground, - body: Column( - children: [ - // Header - Container( - padding: EdgeInsets.only( - top: MediaQuery.of(context).padding.top + 20, - bottom: 20, - left: 20, - right: 20, - ), - color: reactPrimary, - child: Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(10), - ), - child: const Icon( - LucideIcons.chevronLeft, - color: Colors.white, - size: 24, - ), - ), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'One-Time Order', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - Text( - 'Single event or shift request', - style: TextStyle( - fontSize: 12, - color: Colors.white.withOpacity(0.8), - ), - ), - ], - ), - ], - ), - ), - - // Content - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Create Your Order', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 16), - - // Date - _buildLabel('Date'), - const SizedBox(height: 6), - _buildInputField( - controller: _dateController, - hint: 'Select date', - icon: LucideIcons.calendar, - readOnly: true, - onTap: () async { - final picked = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime.now(), - lastDate: DateTime.now().add(const Duration(days: 365)), - ); - if (picked != null) { - _dateController.text = DateFormat( - 'yyyy-MM-dd', - ).format(picked); - } - }, - ), - const SizedBox(height: 16), - - // Location - _buildLabel('Location'), - const SizedBox(height: 6), - _buildInputField( - controller: _locationController, - hint: 'Enter address', - icon: LucideIcons.mapPin, - ), - - const SizedBox(height: 24), - - // Positions Header - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Positions', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xFF0F172A), - ), - ), - GestureDetector( - onTap: _addPosition, - child: const Row( - children: [ - Icon( - LucideIcons.plus, - size: 16, - color: Color(0xFF0032A0), - ), - SizedBox(width: 4), - Text( - 'Add Position', - style: TextStyle( - color: Color(0xFF0032A0), - fontSize: 14, - ), - ), - ], - ), - ), - ], - ), - const SizedBox(height: 12), - - // Positions List - ..._positions.asMap().entries.map((entry) { - return _buildPositionCard(entry.key, entry.value); - }), - ], - ), - ), - ), - - // Footer - Container( - padding: EdgeInsets.only( - left: 20, - right: 20, - top: 20, - bottom: MediaQuery.of(context).padding.bottom + 20, - ), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: reactBorder)), - ), - child: SizedBox( - width: double.infinity, - height: 52, - child: ElevatedButton( - onPressed: _isCreating ? null : _handleSubmit, - style: ElevatedButton.styleFrom( - backgroundColor: reactPrimary, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - elevation: 0, - ), - child: Text( - _isCreating ? 'Creating...' : 'Create Order', - style: const TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ), - ], - ), - ); - } - - Widget _buildLabel(String text) { - return Text( - text, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF475569), - ), - ); - } - - Widget _buildInputField({ - required TextEditingController controller, - required String hint, - required IconData icon, - bool readOnly = false, - VoidCallback? onTap, - }) { - return Container( - height: 48, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: reactBorder), - ), - child: TextField( - controller: controller, - readOnly: readOnly, - onTap: onTap, - decoration: InputDecoration( - hintText: hint, - hintStyle: const TextStyle(color: Color(0xFF94A3B8), fontSize: 14), - prefixIcon: Icon(icon, size: 18, color: Color(0xFF94A3B8)), - border: InputBorder.none, - contentPadding: const EdgeInsets.symmetric(vertical: 13), - ), - ), - ); - } - - Widget _buildPositionCard(int index, _Position pos) { - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: Color(0xFFF1F5F9)), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Position ${index + 1}', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: reactMuted, - ), - ), - if (_positions.length > 1) - GestureDetector( - onTap: () => _removePosition(index), - child: const Text( - 'Remove', - style: TextStyle( - fontSize: 12, - color: Colors.red, - fontWeight: FontWeight.w500, - ), - ), - ), - ], - ), - const SizedBox(height: 12), - - // Role Selector - Container( - padding: const EdgeInsets.symmetric(horizontal: 12), - height: 44, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - border: Border.all(color: reactBorder), - ), - child: DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - hint: const Text('Select role', style: TextStyle(fontSize: 14)), - value: pos.role.isEmpty ? null : pos.role, - icon: const Icon( - LucideIcons.chevronDown, - size: 18, - color: reactMuted, - ), - onChanged: (val) => _updatePosition(index, 'role', val), - items: _roles.map((role) { - final String name = role['name'] as String; - final double rate = role['rate'] as double; - return DropdownMenuItem( - value: name, - child: Text( - '$name - \$${rate.toStringAsFixed(0)}/hr', - style: const TextStyle(fontSize: 14), - ), - ); - }).toList(), - ), - ), - ), - - const SizedBox(height: 12), - - Row( - children: [ - // Start Time - Expanded( - child: _buildTimeInput( - label: 'Start', - value: pos.startTime, - onTap: () async { - final time = await showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ); - if (time != null) - _updatePosition(index, 'startTime', time.format(context)); - }, - ), - ), - const SizedBox(width: 8), - // End Time - Expanded( - child: _buildTimeInput( - label: 'End', - value: pos.endTime, - onTap: () async { - final time = await showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ); - if (time != null) - _updatePosition(index, 'endTime', time.format(context)); - }, - ), - ), - const SizedBox(width: 8), - // Workers Count - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Workers', - style: TextStyle(fontSize: 12, color: reactMuted), - ), - const SizedBox(height: 4), - Container( - height: 40, - decoration: BoxDecoration( - color: const Color(0xFFF1F5F9), - borderRadius: BorderRadius.circular(8), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - GestureDetector( - onTap: () => _updatePosition( - index, - 'count', - (pos.count > 1) ? pos.count - 1 : 1, - ), - child: const Icon(LucideIcons.minus, size: 12), - ), - Text( - '${pos.count}', - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 13, - ), - ), - GestureDetector( - onTap: () => - _updatePosition(index, 'count', pos.count + 1), - child: const Icon(LucideIcons.plus, size: 12), - ), - ], - ), - ), - ], - ), - ), - ], - ), - - const SizedBox(height: 16), - - // Optional Location Override - if (!pos.showLocationOverride) - GestureDetector( - onTap: () => _updatePosition(index, 'showLocationOverride', true), - child: const Row( - children: [ - Icon(LucideIcons.mapPin, size: 14, color: Color(0xFF2563EB)), - SizedBox(width: 4), - Text( - 'Use different location for this position', - style: TextStyle( - fontSize: 12, - color: Color(0xFF2563EB), - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ) - else - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Row( - children: [ - Icon(LucideIcons.mapPin, size: 14, color: reactMuted), - SizedBox(width: 4), - Text( - 'Different Location', - style: TextStyle( - fontSize: 12, - color: reactMuted, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - GestureDetector( - onTap: () { - _updatePosition(index, 'showLocationOverride', false); - _updatePosition(index, 'location', ''); - }, - child: const Icon( - LucideIcons.x, - size: 14, - color: Colors.red, - ), - ), - ], - ), - const SizedBox(height: 6), - Container( - height: 40, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: reactBorder), - ), - child: TextField( - onChanged: (val) => _updatePosition(index, 'location', val), - style: const TextStyle(fontSize: 13), - decoration: const InputDecoration( - hintText: 'Enter different address', - hintStyle: TextStyle( - color: Color(0xFF94A3B8), - fontSize: 13, - ), - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( - horizontal: 12, - vertical: 10, - ), - ), - ), - ), - ], - ), - - const SizedBox(height: 12), - - // Lunch Break - const Text( - 'Lunch Break', - style: TextStyle(fontSize: 12, color: reactMuted), - ), - const SizedBox(height: 4), - Container( - height: 44, - padding: const EdgeInsets.symmetric(horizontal: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - border: Border.all(color: reactBorder), - ), - child: DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - value: pos.lunchBreak, - icon: const Icon( - LucideIcons.chevronDown, - size: 18, - color: reactMuted, - ), - onChanged: (val) => _updatePosition(index, 'lunchBreak', val), - items: const [ - DropdownMenuItem( - value: 0, - child: Text('No break', style: TextStyle(fontSize: 14)), - ), - DropdownMenuItem( - value: 10, - child: Text( - '10 min (Paid)', - style: TextStyle(fontSize: 14), - ), - ), - DropdownMenuItem( - value: 15, - child: Text( - '15 min (Paid)', - style: TextStyle(fontSize: 14), - ), - ), - DropdownMenuItem( - value: 30, - child: Text( - '30 min (Unpaid)', - style: TextStyle(fontSize: 14), - ), - ), - DropdownMenuItem( - value: 45, - child: Text( - '45 min (Unpaid)', - style: TextStyle(fontSize: 14), - ), - ), - DropdownMenuItem( - value: 60, - child: Text( - '60 min (Unpaid)', - style: TextStyle(fontSize: 14), - ), - ), - ], - ), - ), - ), - ], - ), - ); - } - - Widget _buildTimeInput({ - required String label, - required String value, - required VoidCallback onTap, - }) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(label, style: const TextStyle(fontSize: 12, color: reactMuted)), - const SizedBox(height: 4), - GestureDetector( - onTap: onTap, - child: Container( - height: 40, - padding: const EdgeInsets.symmetric(horizontal: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all(color: reactBorder), - ), - alignment: Alignment.centerLeft, - child: Text( - value.isEmpty ? '--:--' : value, - style: const TextStyle(fontSize: 13), - ), - ), - ), - ], - ); - } -} - -class _SuccessView extends StatelessWidget { - const _SuccessView(); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Container( - width: double.infinity, - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xFF0A39DF), Color(0xFF0830B8)], - ), - ), - child: SafeArea( - child: Center( - child: Container( - margin: const EdgeInsets.symmetric(horizontal: 40), - padding: const EdgeInsets.all(32), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(24), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.2), - blurRadius: 20, - offset: const Offset(0, 10), - ), - ], - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 64, - height: 64, - decoration: const BoxDecoration( - color: reactAccent, - shape: BoxShape.circle, - ), - child: const Center( - child: Icon( - LucideIcons.check, - color: reactForeground, - size: 32, - ), - ), - ), - const SizedBox(height: 24), - const Text( - 'Order Created!', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: reactForeground, - ), - ), - const SizedBox(height: 12), - const Text( - 'Your shift request has been posted. Workers will start applying soon.', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - color: reactMuted, - height: 1.5, - ), - ), - const SizedBox(height: 32), - SizedBox( - width: double.infinity, - height: 52, - child: ElevatedButton( - onPressed: () => context.pop(), - style: ElevatedButton.styleFrom( - backgroundColor: reactPrimary, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: const Text( - 'Back to Orders', - style: TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ), - ), - ), - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/permanent_order_flow_page.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/permanent_order_flow_page.dart deleted file mode 100644 index 22e00b83..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/permanent_order_flow_page.dart +++ /dev/null @@ -1,1222 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:intl/intl.dart'; -import '../../../theme.dart'; - -class PermanentOrderFlowPage extends StatefulWidget { - const PermanentOrderFlowPage({super.key}); - - @override - State createState() => _PermanentOrderFlowPageState(); -} - -class _Schedule { - List selectedDays; - String startTime; - String endTime; - - _Schedule({ - required this.selectedDays, - this.startTime = '', - this.endTime = '', - }); - - _Schedule copy() => _Schedule( - selectedDays: List.from(selectedDays), - startTime: startTime, - endTime: endTime, - ); -} - -class _Position { - String role; - String employmentType; - double salaryMin; - double salaryMax; - int count; - String description; - String requirements; - List<_Schedule> schedules; - - _Position({ - this.role = '', - this.employmentType = '', - this.salaryMin = 0, - this.salaryMax = 0, - this.count = 1, - this.description = '', - this.requirements = '', - required this.schedules, - }); - - _Position copy() => _Position( - role: role, - employmentType: employmentType, - salaryMin: salaryMin, - salaryMax: salaryMax, - count: count, - description: description, - requirements: requirements, - schedules: schedules.map((s) => s.copy()).toList(), - ); -} - -class _PermanentOrderFlowPageState extends State { - bool _submitted = false; - bool _showReview = false; - int _openPositionIndex = 0; - - final TextEditingController _locationController = TextEditingController(); - final List<_Position> _positions = [ - _Position(schedules: [_Schedule(selectedDays: [])]), - ]; - - final List _employmentTypes = ['FULL-TIME', 'PART-TIME', 'CONTRACT']; - final List _days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; - final List _roles = [ - 'Server', - 'Bartender', - 'Cook', - 'Busser', - 'Host', - 'Barista', - 'Dishwasher', - 'Event Staff', - 'Manager', - 'Supervisor' - ]; - - void _addPosition() { - setState(() { - _positions.add(_Position(schedules: [_Schedule(selectedDays: [])])); - _openPositionIndex = _positions.length - 1; - }); - } - - void _removePosition(int index) { - if (_positions.length > 1) { - setState(() { - _positions.removeAt(index); - if (_openPositionIndex >= _positions.length) { - _openPositionIndex = _positions.length - 1; - } - }); - } - } - - void _toggleDay(int posIndex, int scheduleIndex, String day) { - setState(() { - final selectedDays = - _positions[posIndex].schedules[scheduleIndex].selectedDays; - if (selectedDays.contains(day)) { - selectedDays.remove(day); - } else { - selectedDays.add(day); - } - }); - } - - void _addSchedule(int posIndex) { - setState(() { - _positions[posIndex].schedules.add(_Schedule(selectedDays: [])); - }); - } - - void _removeSchedule(int posIndex, int scheduleIndex) { - if (_positions[posIndex].schedules.length > 1) { - setState(() { - _positions[posIndex].schedules.removeAt(scheduleIndex); - }); - } - } - - void _updateScheduleTime( - int posIndex, - int scheduleIndex, - String field, - String time, - ) { - setState(() { - if (field == 'startTime') { - _positions[posIndex].schedules[scheduleIndex].startTime = time; - } else { - _positions[posIndex].schedules[scheduleIndex].endTime = time; - } - }); - } - - @override - Widget build(BuildContext context) { - if (_submitted) { - return const _SuccessView(); - } - - if (_showReview) { - return _buildReviewView(); - } - - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: Column( - children: [ - // Header - _buildHeader( - title: 'Permanent Placement', - subtitle: 'Long-term staffing solution', - onBack: () => context.pop(), - color: const Color(0xFF121826), - ), - - // Content - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Location - _buildLabel('Location'), - const SizedBox(height: 8), - _buildTextField( - controller: _locationController, - hint: 'Enter work location', - icon: LucideIcons.mapPin, - ), - const SizedBox(height: 24), - - // Positions - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [_buildLabel('Positions (${_positions.length})')], - ), - const SizedBox(height: 12), - ..._positions.asMap().entries.map((entry) { - return _buildPositionAccordion(entry.key, entry.value); - }), - - const SizedBox(height: 16), - _buildAddButton( - label: 'Add Another Position', - onTap: _addPosition, - dashed: true, - isPrimary: true, - ), - const SizedBox(height: 32), - ], - ), - ), - ), - - // Footer - _buildFooterButton( - label: 'Review Order', - onTap: () => setState(() => _showReview = true), - ), - ], - ), - ); - } - - Widget _buildReviewView() { - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: Column( - children: [ - _buildHeader( - title: 'Review Order', - subtitle: 'Confirm details before posting', - onBack: () => setState(() => _showReview = false), - color: const Color(0xFF121826), - ), - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Order Details - _buildSectionTitle('Order Details'), - const SizedBox(height: 12), - _buildReviewCard([ - _buildReviewRow( - 'Location', - _locationController.text.isEmpty - ? 'Not set' - : _locationController.text, - ), - ]), - const SizedBox(height: 24), - - // Positions Summary - _buildSectionTitle('Positions (${_positions.length})'), - const SizedBox(height: 12), - ..._positions.map((pos) => _buildPositionReviewCard(pos)), - const SizedBox(height: 24), - - // Total Summary - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBlue, width: 2), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Total Positions', - style: TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - Text( - '${_positions.fold(0, (sum, p) => sum + p.count)}', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - '${_positions.length} role${_positions.length > 1 ? 's' : ''}', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - Text( - '${_positions.fold(0, (sum, p) => sum + p.schedules.length)} schedules', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - ), - ), - const SizedBox(height: 32), - ], - ), - ), - ), - _buildFooterButton( - label: 'Confirm & Post', - onTap: () => setState(() => _submitted = true), - ), - ], - ), - ); - } - - // --- UI Helpers --- - - Widget _buildHeader({ - required String title, - required String subtitle, - required VoidCallback onBack, - required Color color, - }) { - return Container( - padding: EdgeInsets.only( - top: MediaQuery.of(context).padding.top + 20, - bottom: 20, - left: 20, - right: 20, - ), - color: color, - child: Row( - children: [ - GestureDetector( - onTap: onBack, - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(10), - ), - child: const Icon( - LucideIcons.chevronLeft, - color: Colors.white, - size: 24, - ), - ), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - Text( - subtitle, - style: TextStyle( - fontSize: 12, - color: Colors.white.withOpacity(0.8), - ), - ), - ], - ), - ], - ), - ); - } - - Widget _buildLabel(String text) { - return Text( - text, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, // Medium as per React font-medium - color: Color(0xFF475569), // slate-600 - ), - ); - } - - Widget _buildSectionTitle(String text) { - return Text( - text, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ); - } - - Widget _buildTextField({ - required TextEditingController controller, - required String hint, - required IconData icon, - }) { - return Container( - height: 48, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: TextField( - controller: controller, - decoration: InputDecoration( - hintText: hint, - hintStyle: const TextStyle(color: Colors.grey, fontSize: 14), - prefixIcon: Icon(icon, size: 20, color: const Color(0xFF94A3B8)), // slate-400 - border: InputBorder.none, - contentPadding: const EdgeInsets.symmetric(vertical: 14), - ), - ), - ); - } - - Widget _buildPositionAccordion(int index, _Position pos) { - bool isOpen = _openPositionIndex == index; - return Container( - margin: const EdgeInsets.only(bottom: 12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), // rounded-xl - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - children: [ - GestureDetector( - onTap: () => - setState(() => _openPositionIndex = isOpen ? -1 : index), - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - color: Colors.transparent, - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - pos.role.isEmpty ? 'Position ${index + 1}' : pos.role, - style: const TextStyle( - fontWeight: FontWeight.w600, - fontSize: 14, - color: AppColors.krowCharcoal, - ), - ), - if (pos.role.isNotEmpty) - Padding( - padding: const EdgeInsets.only(top: 4), - child: Row( - children: [ - const Icon(LucideIcons.users, size: 12, color: AppColors.krowMuted), - const SizedBox(width: 4), - Text('${pos.count}', style: const TextStyle(fontSize: 12, color: AppColors.krowMuted)), - if (pos.employmentType.isNotEmpty) ...[ - const SizedBox(width: 8), - Text(pos.employmentType, style: const TextStyle(fontSize: 12, color: AppColors.krowMuted)), - ], - const SizedBox(width: 8), - const Icon(LucideIcons.clock, size: 12, color: AppColors.krowMuted), - const SizedBox(width: 4), - Text('${pos.schedules.length} schedule${pos.schedules.length > 1 ? 's' : ''}', style: const TextStyle(fontSize: 12, color: AppColors.krowMuted)), - ], - ), - ), - ], - ), - ), - Icon( - isOpen ? LucideIcons.chevronUp : LucideIcons.chevronDown, - size: 20, - color: AppColors.krowMuted, - ), - ], - ), - ), - ), - if (isOpen) - Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Divider(height: 1, color: AppColors.krowBorder), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Position ${index + 1}', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: AppColors.krowMuted, - ), - ), - if (_positions.length > 1) - GestureDetector( - onTap: () => _removePosition(index), - child: const Text( - 'Remove', - style: TextStyle(fontSize: 12, color: Colors.red), - ), - ), - ], - ), - const SizedBox(height: 12), - // Role - _buildDropdown( - hint: 'Select role', - value: pos.role.isEmpty ? null : pos.role, - items: _roles, - onChanged: (val) => setState(() => pos.role = val ?? ''), - ), - const SizedBox(height: 16), - // Employment Type - const Text( - 'Employment Type', - style: TextStyle(fontSize: 12, color: Color(0xFF64748B)), - ), - const SizedBox(height: 4), - Row( - children: _employmentTypes.map((type) { - final isSelected = pos.employmentType == type; - return Expanded( - child: GestureDetector( - onTap: () => - setState(() => pos.employmentType = type), - child: Container( - margin: const EdgeInsets.symmetric(horizontal: 4), - padding: const EdgeInsets.symmetric(vertical: 8), - decoration: BoxDecoration( - color: isSelected - ? AppColors.krowBlue - : Colors.white, - borderRadius: BorderRadius.circular(6), - border: Border.all( - color: isSelected - ? AppColors.krowBlue - : AppColors.krowBorder, - ), - ), - alignment: Alignment.center, - child: Text( - type, - style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.bold, - color: isSelected - ? Colors.white - : AppColors.krowCharcoal, - ), - ), - ), - ), - ); - }).toList(), - ), - const SizedBox(height: 16), - // Count & Salary (Positions / Salary Range) - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text('Positions', style: TextStyle(fontSize: 12, color: Color(0xFF64748B))), - const SizedBox(height: 4), - Row( - children: [ - _buildCounterButton(LucideIcons.minus, () => setState(() => pos.count = (pos.count > 1) ? pos.count - 1 : 1)), - Expanded( - child: Container( - height: 40, - alignment: Alignment.center, - decoration: const BoxDecoration( - border: Border.symmetric(vertical: BorderSide.none, horizontal: BorderSide(color: AppColors.krowBorder)), - ), - child: Text('${pos.count}', style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14)), - ), - ), - _buildCounterButton(LucideIcons.plus, () => setState(() => pos.count++)), - ], - ), - ], - ), - ), - const SizedBox(width: 12), - Expanded( - flex: 2, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text('Salary Range (Annual)', style: TextStyle(fontSize: 12, color: Color(0xFF64748B))), - const SizedBox(height: 4), - Row( - children: [ - Expanded( - child: _buildSmallTextField( - hint: 'Min', - value: pos.salaryMin == 0 ? '' : pos.salaryMin.toStringAsFixed(0), - onChanged: (v) => pos.salaryMin = double.tryParse(v) ?? 0, - ), - ), - const Padding(padding: EdgeInsets.symmetric(horizontal: 4), child: Text('-')), - Expanded( - child: _buildSmallTextField( - hint: 'Max', - value: pos.salaryMax == 0 ? '' : pos.salaryMax.toStringAsFixed(0), - onChanged: (v) => pos.salaryMax = double.tryParse(v) ?? 0, - ), - ), - ], - ), - ], - ), - ), - ], - ), - const SizedBox(height: 16), - // Description - const Text( - 'Description', - style: TextStyle(fontSize: 12, color: Color(0xFF64748B)), - ), - const SizedBox(height: 4), - _buildLargeTextField( - hint: 'Tell candidates about the role...', - onChanged: (v) => pos.description = v, - ), - const SizedBox(height: 16), - // Requirements - const Text( - 'Requirements', - style: TextStyle(fontSize: 12, color: Color(0xFF64748B)), - ), - const SizedBox(height: 4), - _buildLargeTextField( - hint: 'Skills, experience, certificates...', - onChanged: (v) => pos.requirements = v, - ), - const SizedBox(height: 20), - const Text( - 'Schedules', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Color(0xFF475569), - ), - ), - const SizedBox(height: 8), - ...pos.schedules.asMap().entries.map((sEntry) { - final sIdx = sEntry.key; - final schedule = sEntry.value; - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFFF8FAFC), // slate-50 - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Schedule ${sIdx + 1}', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: AppColors.krowMuted, - ), - ), - if (pos.schedules.length > 1) - GestureDetector( - onTap: () => _removeSchedule(index, sIdx), - child: const Text('Remove', style: TextStyle(fontSize: 10, color: Colors.red)), - ), - ], - ), - const SizedBox(height: 12), - Row( - children: _days.map((day) { - final isSelected = schedule.selectedDays.contains( - day, - ); - return Expanded( - child: GestureDetector( - onTap: () => _toggleDay(index, sIdx, day), - child: Container( - margin: const EdgeInsets.symmetric( - horizontal: 2, - ), - padding: const EdgeInsets.symmetric( - vertical: 8, - ), - decoration: BoxDecoration( - color: isSelected - ? AppColors.krowBlue - : Colors.white, - borderRadius: BorderRadius.circular(6), - ), - alignment: Alignment.center, - child: Text( - day, - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: isSelected - ? Colors.white - : AppColors.krowMuted, - ), - ), - ), - ), - ); - }).toList(), - ), - const SizedBox(height: 12), - Row( - children: [ - Expanded( - child: _buildTimeInput( - hint: 'Start', - value: schedule.startTime, - onTap: () async { - final picked = await showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ); - if (picked != null) - _updateScheduleTime( - index, - sIdx, - 'startTime', - picked.format(context), - ); - }, - ), - ), - const SizedBox(width: 8), - Expanded( - child: _buildTimeInput( - hint: 'End', - value: schedule.endTime, - onTap: () async { - final picked = await showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ); - if (picked != null) - _updateScheduleTime( - index, - sIdx, - 'endTime', - picked.format(context), - ); - }, - ), - ), - ], - ), - ], - ), - ); - }), - _buildAddButton( - label: 'Add Another Schedule', - onTap: () => _addSchedule(index), - dashed: false, - isPrimary: false, - small: true, - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildDropdown({ - required String hint, - required String? value, - required List items, - required Function(String?) onChanged, - }) { - return Container( - height: 44, // h-11 - padding: const EdgeInsets.symmetric(horizontal: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - ), - child: DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - hint: Text(hint, style: const TextStyle(fontSize: 14)), - value: value, - onChanged: (v) => onChanged(v), - items: items - .map( - (r) => DropdownMenuItem( - value: r, - child: Text(r, style: const TextStyle(fontSize: 14)), - ), - ) - .toList(), - ), - ), - ); - } - - Widget _buildSmallTextField({ - required String hint, - required String value, - required Function(String) onChanged, - }) { - return Container( - height: 40, // h-10 - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - ), - child: TextField( - keyboardType: TextInputType.number, - style: const TextStyle(fontSize: 13), - decoration: InputDecoration( - border: InputBorder.none, - hintText: hint, - prefixText: ' \$ ', // Space for spacing - contentPadding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 10, // Center vertically - ), - ), - onChanged: onChanged, - controller: TextEditingController(text: value), - ), - ); - } - - Widget _buildLargeTextField({ - required String hint, - required Function(String) onChanged, - }) { - return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - ), - child: TextField( - minLines: 3, - maxLines: null, - style: const TextStyle(fontSize: 13), - decoration: InputDecoration( - border: InputBorder.none, - hintText: hint, - hintStyle: const TextStyle(color: Colors.grey, fontSize: 13), - contentPadding: const EdgeInsets.all(12), - ), - onChanged: onChanged, - ), - ); - } - - Widget _buildReviewRow(String label, String value) { - return Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - label, - style: const TextStyle(fontSize: 14, color: AppColors.krowMuted), - ), - Text( - value, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - ); - } - - Widget _buildReviewCard(List children) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), // rounded-xl - border: Border.all(color: AppColors.krowBorder), - ), - child: Column(children: children), - ); - } - - Widget _buildPositionReviewCard(_Position pos) { - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), // rounded-xl - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - pos.role.isEmpty ? 'Unspecified Role' : pos.role, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - Padding( - padding: const EdgeInsets.only(top: 4), - child: Row( - children: [ - Text( - '${pos.count} position${pos.count > 1 ? 's' : ''}', - style: const TextStyle(fontSize: 12, color: AppColors.krowMuted), - ), - const SizedBox(width: 12), - if (pos.employmentType.isNotEmpty) ...[ - Text(pos.employmentType, style: const TextStyle(fontSize: 12, color: AppColors.krowMuted)), - const SizedBox(width: 12), - ], - Text( - '\$${pos.salaryMin ~/ 1000}k - \$${pos.salaryMax ~/ 1000}k', - style: const TextStyle(fontSize: 12, color: AppColors.krowMuted), - ), - ], - ), - ), - if (pos.description.isNotEmpty) ...[ - const SizedBox(height: 8), - Text(pos.description, style: const TextStyle(fontSize: 12, color: AppColors.krowMuted), maxLines: 2, overflow: TextOverflow.ellipsis), - ], - if (pos.schedules.isNotEmpty) ...[ - const SizedBox(height: 12), - ...pos.schedules.map( - (sche) => Container( - margin: const EdgeInsets.only(bottom: 6), - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: const Color(0xFFF8FAFC), // slate-50 - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Schedule 1', // Simplified for mock - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Text( - '${sche.selectedDays.isNotEmpty ? sche.selectedDays.join(', ') : 'No days'}: ${sche.startTime.isNotEmpty ? sche.startTime : '--'} - ${sche.endTime.isNotEmpty ? sche.endTime : '--'}', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - ), - ], - ], - ), - ); - } - - Widget _buildAddButton({required String label, required VoidCallback onTap, bool dashed = false, bool isPrimary = true, bool small = false}) { - return GestureDetector( - onTap: onTap, - child: Container( - width: double.infinity, - height: small ? 36 : 44, // h-9 or h-11 - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: isPrimary ? AppColors.krowBlue : AppColors.krowBorder, - width: isPrimary && dashed ? 2 : 1, - style: BorderStyle.solid, // Use custom painter for real dash if needed, solid for now - ), - color: isPrimary ? Colors.white : Colors.transparent, - ), - child: Center( - child: Text( - '+ $label', - style: TextStyle( - color: isPrimary ? AppColors.krowBlue : AppColors.krowMuted, - fontWeight: isPrimary ? FontWeight.bold : FontWeight.w500, - fontSize: small ? 12 : 14, - ), - ), - ), - ), - ); - } - - Widget _buildTimeInput({ - required String hint, - required String value, - required VoidCallback onTap, - }) { - return GestureDetector( - onTap: onTap, - child: Container( - height: 40, - padding: const EdgeInsets.symmetric(horizontal: 12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - ), - alignment: Alignment.centerLeft, - child: Text( - value.isEmpty ? hint : value, - style: TextStyle( - fontSize: 12, - color: value.isEmpty ? Colors.grey : AppColors.krowCharcoal, - ), - ), - ), - ); - } - - Widget _buildCounterButton(IconData icon, VoidCallback onTap) { - return GestureDetector( - onTap: onTap, - child: Container( - width: 36, // w-9 - height: 40, // h-10 - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - color: Colors.white, - ), - child: Icon(icon, size: 16, color: AppColors.krowMuted), - ), - ); - } - - Widget _buildAddSmallButton({ - required String label, - required VoidCallback onTap, - }) { - return _buildAddButton(label: label, onTap: onTap, dashed: false, isPrimary: false, small: true); - } - - Widget _buildFooterButton({ - required String label, - required VoidCallback onTap, - }) { - return Container( - padding: EdgeInsets.only( - left: 20, - right: 20, - top: 20, - bottom: MediaQuery.of(context).padding.bottom + 20, - ), - color: Colors.white, - child: SizedBox( - width: double.infinity, - height: 48, // h-12 - child: ElevatedButton( - onPressed: onTap, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), // rounded-md - ), - elevation: 0, - ), - child: Text( - label, - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 14, - ), - ), - ), - ), - ); - } -} - -class _SuccessView extends StatelessWidget { - const _SuccessView(); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Container( - width: double.infinity, - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Color(0xFF2D3748), Color(0xFF1A202C)], // slate-800 to slate-900 - ), - ), - child: SafeArea( - child: Center( - child: Container( - margin: const EdgeInsets.symmetric(horizontal: 40), - padding: const EdgeInsets.all(32), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), // rounded-lg - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.2), - blurRadius: 20, - offset: const Offset(0, 10), - ), - ], - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 64, - height: 64, - decoration: const BoxDecoration( - color: AppColors.krowYellow, - shape: BoxShape.circle, - ), - child: const Center( - child: Icon( - LucideIcons.check, - color: AppColors.krowCharcoal, - size: 32, - ), - ), - ), - const SizedBox(height: 24), - const Text( - 'Position Posted!', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 12), - const Text( - 'Your permanent position has been posted. We\'ll match qualified candidates for you.', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - height: 1.5, - ), - ), - const SizedBox(height: 32), - SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: () => context.go('/client-home'), - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowCharcoal, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), // rounded-md - ), - elevation: 0, - ), - child: const Text( - 'Back to Orders', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ), - ), - ), - ), - ), - ); - } -} - diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/rapid_order_flow_page.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/rapid_order_flow_page.dart deleted file mode 100644 index 87e57bd5..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/rapid_order_flow_page.dart +++ /dev/null @@ -1,530 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:intl/intl.dart'; -import '../../../theme.dart'; - -class RapidOrderFlowPage extends StatefulWidget { - const RapidOrderFlowPage({super.key}); - - @override - State createState() => _RapidOrderFlowPageState(); -} - -class _RapidOrderFlowPageState extends State { - final TextEditingController _messageController = TextEditingController(); - bool _isListening = false; - bool _submitted = false; - bool _isSending = false; - - final List _examples = [ - '"We had a call out. Need 2 cooks ASAP"', - '"Need 5 bartenders ASAP until 5am"', - '"Emergency! Need 3 servers right now till midnight"', - ]; - - Future _handleSubmit() async { - if (_messageController.text.trim().isEmpty) return; - - setState(() { - _isSending = true; - }); - - // Simulate API call - await Future.delayed(const Duration(seconds: 1)); - - if (mounted) { - setState(() { - _isSending = false; - _submitted = true; - }); - } - } - - void _handleSpeak() { - setState(() { - _isListening = !_isListening; - }); - // Mock speech recognition - if (_isListening) { - Future.delayed(const Duration(seconds: 2), () { - if (mounted) { - setState(() { - _messageController.text = "Need 2 servers for a banquet right now."; - _isListening = false; - }); - } - }); - } - } - - @override - Widget build(BuildContext context) { - if (_submitted) { - return const _SuccessView(); - } - - final now = DateTime.now(); - final dateStr = DateFormat('EEE, MMM dd, yyyy').format(now); - final timeStr = DateFormat('h:mm a').format(now); - - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: Column( - children: [ - // Header - Container( - padding: EdgeInsets.only( - top: MediaQuery.of(context).padding.top + 20, - bottom: 20, - left: 20, - right: 20, - ), - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [Color(0xFFF04444), Color(0xFFD63939)], - begin: Alignment.centerLeft, - end: Alignment.centerRight, - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(10), - ), - child: const Icon( - LucideIcons.chevronLeft, - color: Colors.white, - size: 24, - ), - ), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Icon( - LucideIcons.zap, - color: AppColors.krowYellow, - size: 18, - ), - const SizedBox(width: 6), - const Text( - 'RAPID Order', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ], - ), - Text( - 'Emergency staffing in minutes', - style: TextStyle( - fontSize: 12, - color: Colors.white.withOpacity(0.8), - ), - ), - ], - ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - dateStr, - style: TextStyle( - fontSize: 12, - color: Colors.white.withOpacity(0.9), - ), - ), - Text( - timeStr, - style: TextStyle( - fontSize: 12, - color: Colors.white.withOpacity(0.9), - ), - ), - ], - ), - ], - ), - ), - - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Tell us what you need', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 4, - ), - decoration: BoxDecoration( - color: const Color(0xFFF04444), - borderRadius: BorderRadius.circular(6), - ), - child: const Text( - 'URGENT', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ), - ], - ), - const SizedBox(height: 16), - - // Main Card - Container( - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - children: [ - Container( - width: 64, - height: 64, - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFFF04444), Color(0xFFD63939)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: const Color(0xFFF04444).withOpacity(0.3), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: const Icon( - LucideIcons.zap, - color: Colors.white, - size: 32, - ), - ), - const SizedBox(height: 16), - const Text( - 'Need staff urgently?', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 6), - const Text( - 'Type or speak what you need. I\'ll handle the rest', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 24), - - // Examples - ..._examples.asMap().entries.map((entry) { - final index = entry.key; - final example = entry.value; - final isFirst = index == 0; - return Padding( - padding: const EdgeInsets.only(bottom: 10), - child: GestureDetector( - onTap: () { - setState(() { - _messageController.text = example.replaceAll( - '"', - '', - ); - }); - }, - child: Container( - width: double.infinity, - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 14, - ), - decoration: BoxDecoration( - color: isFirst - ? AppColors.krowYellow.withOpacity(0.15) - : Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: isFirst - ? AppColors.krowYellow - : AppColors.krowBorder, - ), - ), - child: RichText( - text: TextSpan( - style: const TextStyle( - color: AppColors.krowCharcoal, - fontSize: 14, - ), - children: [ - const TextSpan( - text: 'Example: ', - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - TextSpan(text: example), - ], - ), - ), - ), - ), - ); - }), - const SizedBox(height: 16), - - // Input - TextField( - controller: _messageController, - maxLines: 4, - decoration: InputDecoration( - hintText: - 'Type or speak... (e.g., "Need 5 cooks ASAP until 5am")', - hintStyle: const TextStyle( - color: Colors.grey, - fontSize: 14, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide( - color: AppColors.krowBorder, - ), - ), - contentPadding: const EdgeInsets.all(16), - ), - ), - const SizedBox(height: 16), - - // Actions - Row( - children: [ - Expanded( - child: SizedBox( - height: 52, - child: OutlinedButton.icon( - onPressed: _handleSpeak, - icon: Icon( - LucideIcons.mic, - size: 20, - color: _isListening - ? Colors.red - : AppColors.krowCharcoal, - ), - label: Text( - _isListening ? 'Listening...' : 'Speak', - style: TextStyle( - color: _isListening - ? Colors.red - : AppColors.krowCharcoal, - fontWeight: FontWeight.w600, - ), - ), - style: OutlinedButton.styleFrom( - backgroundColor: _isListening - ? Colors.red.withOpacity(0.05) - : Colors.white, - side: BorderSide( - color: _isListening - ? Colors.red - : AppColors.krowBorder, - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: SizedBox( - height: 52, - child: ElevatedButton.icon( - onPressed: - _isSending || - _messageController.text.trim().isEmpty - ? null - : _handleSubmit, - icon: const Icon( - LucideIcons.send, - size: 20, - color: Colors.white, - ), - label: Text( - _isSending ? 'Sending...' : 'Send Message', - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - ), - ), - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - ), - ), - ), - ], - ), - ], - ), - ), - ], - ), - ), - ), - ], - ), - ); - } -} - -class _SuccessView extends StatelessWidget { - const _SuccessView(); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Container( - width: double.infinity, - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [AppColors.krowBlue, Color(0xFF0830B8)], - ), - ), - child: SafeArea( - child: Center( - child: Container( - margin: const EdgeInsets.symmetric(horizontal: 40), - padding: const EdgeInsets.all(32), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(24), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.2), - blurRadius: 20, - offset: const Offset(0, 10), - ), - ], - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 64, - height: 64, - decoration: const BoxDecoration( - color: AppColors.krowYellow, - shape: BoxShape.circle, - ), - child: const Center( - child: Icon( - LucideIcons.zap, - color: AppColors.krowCharcoal, - size: 32, - ), - ), - ), - const SizedBox(height: 24), - const Text( - 'Request Sent!', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 12), - const Text( - 'We\'re finding available workers for you right now. You\'ll be notified as they accept.', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - height: 1.5, - ), - ), - const SizedBox(height: 32), - SizedBox( - width: double.infinity, - height: 52, - child: ElevatedButton( - onPressed: () => context.pop(), - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowCharcoal, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - elevation: 0, - ), - child: const Text( - 'Back to Orders', - style: TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ), - ), - ), - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/recurring_order_flow_page.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/recurring_order_flow_page.dart deleted file mode 100644 index caca4114..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_pages/recurring_order_flow_page.dart +++ /dev/null @@ -1,1352 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:intl/intl.dart'; -import '../../../theme.dart'; - -class RecurringOrderFlowPage extends StatefulWidget { - const RecurringOrderFlowPage({super.key}); - - @override - State createState() => _RecurringOrderFlowPageState(); -} - -class _Schedule { - List selectedDays; - String startTime; - String endTime; - - _Schedule({ - required this.selectedDays, - this.startTime = '', - this.endTime = '', - }); - - _Schedule copy() => _Schedule( - selectedDays: List.from(selectedDays), - startTime: startTime, - endTime: endTime, - ); -} - -class _Position { - String role; - int count; - double rate; - List<_Schedule> schedules; - - _Position({ - this.role = '', - this.count = 1, - this.rate = 20, - required this.schedules, - }); - - _Position copy() => _Position( - role: role, - count: count, - rate: rate, - schedules: schedules.map((s) => s.copy()).toList(), - ); -} - -class _RecurringOrderFlowPageState extends State { - bool _submitted = false; - bool _showReview = false; - int _openPositionIndex = 0; - - final TextEditingController _locationController = TextEditingController(); - String _duration = 'weekly'; - int _lunchBreak = 30; - String _startDate = ''; - String _endDate = ''; - - final List<_Position> _positions = [ - _Position(schedules: [_Schedule(selectedDays: [])]), - ]; - - final List _days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; - final List _roles = [ - 'Server', - 'Bartender', - 'Cook', - 'Busser', - 'Host', - 'Barista', - 'Dishwasher', - 'Event Staff', - ]; - - double _calculateTotalCost() { - double total = 0; - for (var pos in _positions) { - for (var schedule in pos.schedules) { - if (schedule.startTime.isNotEmpty && - schedule.endTime.isNotEmpty && - schedule.selectedDays.isNotEmpty) { - try { - // Very basic estimation for mock: start/end times difference - // In a real app, use DateFormat or TimeOfDay logic more robustly - // Here assuming standard inputs or just returning a mock cost if calculation fails - // to prevent crashes. React code does precise math, let's approximate or try-catch. - // Simplified logic: assume 8 hours per shift for mock visuals if empty - // But let's try to parse: - - // Note: input format from TimePicker is usually "h:mm AM/PM" or "HH:mm" depending on locale - // React uses "HH:mm" input type="time". Flutter TimePicker returns formatted string. - // We'll trust the user input or default to 0. - - // For MVP, if we can't parse, we ignore. - total += - 8 * - pos.rate * - pos.count * - schedule.selectedDays.length * - (_duration == 'weekly' ? 1 : 4); - } catch (e) { - // ignore - } - } - } - } - // Return a non-zero mock value if everything is empty for better visual - if (total == 0) return 1200.00; - return total; - } - - void _addPosition() { - setState(() { - _positions.add(_Position(schedules: [_Schedule(selectedDays: [])])); - _openPositionIndex = _positions.length - 1; - }); - } - - void _removePosition(int index) { - if (_positions.length > 1) { - setState(() { - _positions.removeAt(index); - if (_openPositionIndex >= _positions.length) { - _openPositionIndex = _positions.length - 1; - } - }); - } - } - - void _addSchedule(int posIndex) { - setState(() { - _positions[posIndex].schedules.add(_Schedule(selectedDays: [])); - }); - } - - void _removeSchedule(int posIndex, int scheduleIndex) { - if (_positions[posIndex].schedules.length > 1) { - setState(() { - _positions[posIndex].schedules.removeAt(scheduleIndex); - }); - } - } - - void _toggleDay(int posIndex, int scheduleIndex, String day) { - setState(() { - final selectedDays = - _positions[posIndex].schedules[scheduleIndex].selectedDays; - if (selectedDays.contains(day)) { - selectedDays.remove(day); - } else { - selectedDays.add(day); - } - }); - } - - @override - Widget build(BuildContext context) { - if (_submitted) { - return const _SuccessView(); - } - - if (_showReview) { - return _buildReviewView(); - } - - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: Column( - children: [ - // Header - _buildHeader( - title: 'Recurring Order', - subtitle: 'Ongoing weekly/monthly coverage', - onBack: () => context.pop(), - color: const Color(0xFF121826), // Match React foreground color - ), - - // Content - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Location - _buildLabel('Location'), - const SizedBox(height: 8), - _buildTextField( - controller: _locationController, - hint: 'Enter address', - icon: null, // React input doesn't show icon - ), - const SizedBox(height: 24), - - // Duration - _buildLabel('Duration'), - const SizedBox(height: 8), - Row( - children: ['weekly', 'monthly'].map((d) { - final isSelected = _duration == d; - return Expanded( - child: GestureDetector( - onTap: () => setState(() => _duration = d), - child: Container( - margin: EdgeInsets.only( - right: d == 'weekly' ? 12 : 0, - ), - padding: const EdgeInsets.symmetric(vertical: 14), - decoration: BoxDecoration( - color: isSelected - ? AppColors.krowBlue - : Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: isSelected - ? AppColors.krowBlue - : AppColors.krowBorder, - ), - ), - alignment: Alignment.center, - child: Text( - d[0].toUpperCase() + d.substring(1), - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: isSelected - ? Colors.white - : AppColors.krowCharcoal, - ), - ), - ), - ), - ); - }).toList(), - ), - const SizedBox(height: 24), - - // Dates - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildLabel('Start Date'), - const SizedBox(height: 8), - _buildDateField( - value: _startDate, - onTap: () async { - final picked = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime.now(), - lastDate: DateTime.now().add( - const Duration(days: 365), - ), - ); - if (picked != null) { - setState( - () => _startDate = DateFormat( - 'yyyy-MM-dd', - ).format(picked), - ); - } - }, - ), - ], - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildLabel('End Date (Optional)'), - const SizedBox(height: 8), - _buildDateField( - value: _endDate, - onTap: () async { - final picked = await showDatePicker( - context: context, - initialDate: DateTime.now().add( - const Duration(days: 7), - ), - firstDate: DateTime.now(), - lastDate: DateTime.now().add( - const Duration(days: 730), - ), - ); - if (picked != null) { - setState( - () => _endDate = DateFormat( - 'yyyy-MM-dd', - ).format(picked), - ); - } - }, - ), - ], - ), - ), - ], - ), - const SizedBox(height: 24), - - // Lunch Break - _buildLabel('Lunch Break'), - const SizedBox(height: 8), - _buildLunchBreakDropdown(), - const SizedBox(height: 24), - - // Positions - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [_buildLabel('Positions (${_positions.length})')], - ), - const SizedBox(height: 12), - ..._positions.asMap().entries.map((entry) { - return _buildPositionAccordion(entry.key, entry.value); - }), - - const SizedBox(height: 16), - _buildAddButton( - label: 'Add Another Position', - onTap: _addPosition, - dashed: true, - isPrimary: true, - ), - const SizedBox(height: 32), - ], - ), - ), - ), - - // Footer - _buildFooterButton( - label: 'Review Order', - onTap: () => setState(() => _showReview = true), - ), - ], - ), - ); - } - - Widget _buildReviewView() { - final totalCost = _calculateTotalCost(); - return Scaffold( - backgroundColor: AppColors.krowBackground, - body: Column( - children: [ - _buildHeader( - title: 'Review Order', - subtitle: 'Confirm details before submitting', - onBack: () => setState(() => _showReview = false), - color: const Color(0xFF121826), - ), - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Order Details Card - _buildSectionTitle('Order Details'), - const SizedBox(height: 12), - _buildReviewCard([ - _buildReviewRow( - 'Location', - _locationController.text.isEmpty - ? 'Not set' - : _locationController.text, - ), - _buildReviewRow( - 'Duration', - _duration[0].toUpperCase() + _duration.substring(1), - ), - _buildReviewRow( - 'Lunch Break', - _lunchBreak == 0 ? 'No break' : '$_lunchBreak min', - ), - _buildReviewRow( - 'Start Date', - _startDate.isEmpty ? 'Not set' : _startDate, - ), - if (_endDate.isNotEmpty) - _buildReviewRow('End Date', _endDate), - ]), - const SizedBox(height: 24), - - // Positions Summary - _buildSectionTitle('Positions (${_positions.length})'), - const SizedBox(height: 12), - ..._positions.map((pos) => _buildPositionReviewCard(pos)), - - const SizedBox(height: 24), - - // Total Cost Card - Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - border: Border.all(color: AppColors.krowBlue, width: 2), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Estimated $_duration cost', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - const SizedBox(height: 4), - Text( - '\$${totalCost.toStringAsFixed(2)}', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - '${_positions.fold(0, (sum, p) => sum + p.count)} total workers', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - Text( - '${_positions.fold(0, (sum, p) => sum + p.schedules.length)} schedules', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ], - ), - ), - const SizedBox(height: 32), - ], - ), - ), - ), - _buildFooterButton( - label: 'Confirm & Submit', - onTap: () => setState(() => _submitted = true), - ), - ], - ), - ); - } - - // --- UI Helpers --- - - Widget _buildHeader({ - required String title, - required String subtitle, - required VoidCallback onBack, - Color color = AppColors.krowBlue, - }) { - return Container( - padding: EdgeInsets.only( - top: MediaQuery.of(context).padding.top + 20, - bottom: 20, - left: 20, - right: 20, - ), - color: color, - child: Row( - children: [ - GestureDetector( - onTap: onBack, - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(10), - ), - child: const Icon( - LucideIcons.chevronLeft, - color: Colors.white, - size: 24, - ), - ), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - Text( - subtitle, - style: TextStyle( - fontSize: 12, - color: Colors.white.withOpacity(0.8), - ), - ), - ], - ), - ], - ), - ); - } - - Widget _buildLabel(String text) { - return Text( - text, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, // Medium as per React - color: Color(0xFF475569), // slate-600 - ), - ); - } - - Widget _buildSectionTitle(String text) { - return Text( - text, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: AppColors.krowCharcoal, - ), - ); - } - - Widget _buildTextField({ - required TextEditingController controller, - required String hint, - IconData? icon, - }) { - return Container( - height: 48, // React input h-12 (48px) - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), // rounded-xl - border: Border.all(color: AppColors.krowBorder), - ), - padding: EdgeInsets.only(left: icon != null ? 0 : 16), - child: TextField( - controller: controller, - decoration: InputDecoration( - hintText: hint, - hintStyle: const TextStyle(color: Colors.grey, fontSize: 14), - prefixIcon: icon != null - ? Icon(icon, size: 20, color: AppColors.krowMuted) - : null, - border: InputBorder.none, - contentPadding: const EdgeInsets.symmetric( - vertical: 14, - ), // Centered vertically - ), - ), - ); - } - - Widget _buildDateField({required String value, required VoidCallback onTap}) { - return GestureDetector( - onTap: onTap, - child: Container( - height: 48, - padding: const EdgeInsets.symmetric(horizontal: 16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: Row( - children: [ - if (value.isEmpty) ...[ - // No icon in React input type=date typically unless customized, but looks like standard input - // Keeping it simpler - ], - Expanded( - child: Text( - value.isEmpty ? 'mm/dd/yyyy' : value, // Placeholder style - style: TextStyle( - color: value.isEmpty ? Colors.grey : AppColors.krowCharcoal, - fontSize: 14, - ), - ), - ), - ], - ), - ), - ); - } - - Widget _buildLunchBreakDropdown() { - return Container( - height: 48, - padding: const EdgeInsets.symmetric(horizontal: 16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.krowBorder), - ), - child: DropdownButtonHideUnderline( - child: DropdownButton( - value: _lunchBreak, - isExpanded: true, - icon: const Icon(LucideIcons.chevronDown, size: 20), - onChanged: (val) => setState(() => _lunchBreak = val ?? 30), - items: [ - const DropdownMenuItem(value: 0, child: Text('No break')), - const DropdownMenuItem(value: 10, child: Text('10 min (Paid)')), - const DropdownMenuItem(value: 15, child: Text('15 min (Paid)')), - const DropdownMenuItem(value: 30, child: Text('30 min (Unpaid)')), - const DropdownMenuItem(value: 45, child: Text('45 min (Unpaid)')), - const DropdownMenuItem(value: 60, child: Text('60 min (Unpaid)')), - ], - ), - ), - ); - } - - Widget _buildPositionAccordion(int index, _Position pos) { - bool isOpen = _openPositionIndex == index; - return Container( - margin: const EdgeInsets.only(bottom: 12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), // rounded-xl - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - children: [ - GestureDetector( - onTap: () => - setState(() => _openPositionIndex = isOpen ? -1 : index), - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - color: Colors.transparent, - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - pos.role.isEmpty ? 'Position ${index + 1}' : pos.role, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: AppColors.krowCharcoal, - ), - ), - if (pos.role.isNotEmpty) - Padding( - padding: const EdgeInsets.only(top: 4), - child: Row( - children: [ - _buildBadge(LucideIcons.users, '${pos.count}'), - const SizedBox(width: 8), - _buildBadge( - LucideIcons.dollarSign, - '${pos.rate}/hr', - ), - const SizedBox(width: 8), - _buildBadge( - LucideIcons.clock, - '${pos.schedules.length} schedule${pos.schedules.length > 1 ? 's' : ''}', - ), - ], - ), - ), - ], - ), - ), - Icon( - isOpen ? LucideIcons.chevronUp : LucideIcons.chevronDown, - size: 20, - color: AppColors.krowMuted, - ), - ], - ), - ), - ), - if (isOpen) - Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Divider(height: 1, color: AppColors.krowBorder), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Position ${index + 1}', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: AppColors.krowMuted, - ), - ), - if (_positions.length > 1) - GestureDetector( - onTap: () => _removePosition(index), - child: const Text( - 'Remove', - style: TextStyle(fontSize: 12, color: Colors.red), - ), - ), - ], - ), - const SizedBox(height: 12), - // Role - Container( - height: 44, // h-11 - padding: const EdgeInsets.symmetric(horizontal: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - ), - child: DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - icon: const Icon( - LucideIcons.chevronDown, - size: 20, - color: AppColors.krowMuted, - ), - hint: const Text( - 'Select role', - style: TextStyle(fontSize: 14), - ), - value: pos.role.isEmpty ? null : pos.role, - onChanged: (val) => - setState(() => pos.role = val ?? ''), - items: _roles - .map( - (r) => DropdownMenuItem(value: r, child: Text(r)), - ) - .toList(), - ), - ), - ), - const SizedBox(height: 12), - // Count & Rate - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Workers', - style: TextStyle( - fontSize: 12, - color: Color(0xFF64748B), // slate-500 - ), - ), - const SizedBox(height: 4), - Row( - children: [ - _buildCounterButton( - LucideIcons.minus, - () => setState( - () => pos.count = (pos.count > 1) - ? pos.count - 1 - : 1, - ), - ), - Expanded( - child: Container( - height: 44, - alignment: Alignment.center, - decoration: const BoxDecoration( - border: Border.symmetric( - vertical: BorderSide.none, - horizontal: BorderSide( - color: AppColors.krowBorder, - ), - ), - ), - child: Text( - '${pos.count}', - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16, - ), - ), - ), - ), - _buildCounterButton( - LucideIcons.plus, - () => setState(() => pos.count++), - ), - ], - ), - ], - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Rate/hr', - style: TextStyle( - fontSize: 12, - color: Color(0xFF64748B), - ), - ), - const SizedBox(height: 4), - Container( - height: 44, - alignment: Alignment.center, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - ), - child: TextField( - keyboardType: TextInputType.number, - textAlign: TextAlign.left, - style: const TextStyle(fontSize: 14), - decoration: const InputDecoration( - border: InputBorder.none, - isDense: true, - contentPadding: EdgeInsets.symmetric( - horizontal: 12, - ), - ), - onChanged: (val) => - pos.rate = double.tryParse(val) ?? 20.0, - controller: TextEditingController( - text: pos.rate.toStringAsFixed(0), - ), - ), - ), - ], - ), - ), - ], - ), - const SizedBox(height: 20), - const Text( - 'Schedules', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Color(0xFF475569), - ), - ), - const SizedBox(height: 12), - ...pos.schedules.asMap().entries.map((scheEntry) { - return _buildScheduleItem( - index, - scheEntry.key, - scheEntry.value, - ); - }), - _buildAddButton( - label: 'Add Another Schedule', - onTap: () => _addSchedule(index), - dashed: false, - isPrimary: false, // Outline button - small: true, - ), - ], - ), - ), - ], - ), - ); - } - - Widget _buildBadge(IconData icon, String text) { - return Row( - children: [ - Icon(icon, size: 12, color: AppColors.krowMuted), - const SizedBox(width: 4), - Text( - text, - style: const TextStyle(fontSize: 12, color: AppColors.krowMuted), - ), - ], - ); - } - - Widget _buildCounterButton(IconData icon, VoidCallback onTap) { - return GestureDetector( - onTap: onTap, - child: Container( - width: 40, - height: 44, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - color: Colors.white, - ), - child: Icon(icon, size: 16, color: AppColors.krowMuted), - ), - ); - } - - Widget _buildScheduleItem(int posIndex, int scheIndex, _Schedule sche) { - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFFF8FAFC), // slate-50 - borderRadius: BorderRadius.circular(8), - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Schedule ${scheIndex + 1}', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: AppColors.krowMuted, - ), - ), - if (_positions[posIndex].schedules.length > 1) - GestureDetector( - onTap: () => _removeSchedule(posIndex, scheIndex), - child: const Text( - 'Remove', - style: TextStyle(fontSize: 10, color: Colors.red), - ), - ), - ], - ), - const SizedBox(height: 12), - // Days - Row( - children: _days.map((day) { - final isSelected = sche.selectedDays.contains(day); - return Expanded( - child: GestureDetector( - onTap: () => _toggleDay(posIndex, scheIndex, day), - child: Container( - margin: const EdgeInsets.symmetric(horizontal: 2), - padding: const EdgeInsets.symmetric(vertical: 8), - decoration: BoxDecoration( - color: isSelected ? AppColors.krowBlue : Colors.white, - borderRadius: BorderRadius.circular(6), - ), - alignment: Alignment.center, - child: Text( - day, - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: isSelected ? Colors.white : AppColors.krowMuted, - ), - ), - ), - ), - ); - }).toList(), - ), - const SizedBox(height: 12), - // Times - Row( - children: [ - Expanded( - child: _buildTimeInput( - value: sche.startTime, - hint: 'Start', - onTap: () async { - final time = await showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ); - if (time != null) - setState(() => sche.startTime = time.format(context)); - }, - ), - ), - const SizedBox(width: 8), - Expanded( - child: _buildTimeInput( - value: sche.endTime, - hint: 'End', - onTap: () async { - final time = await showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ); - if (time != null) - setState(() => sche.endTime = time.format(context)); - }, - ), - ), - ], - ), - ], - ), - ); - } - - Widget _buildTimeInput({ - required String value, - required String hint, - required VoidCallback onTap, - }) { - return GestureDetector( - onTap: onTap, - child: Container( - height: 40, - padding: const EdgeInsets.symmetric(horizontal: 12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColors.krowBorder), - ), - alignment: Alignment.centerLeft, - child: Text( - value.isEmpty ? hint : value, - style: TextStyle( - fontSize: 12, - color: value.isEmpty ? Colors.grey : AppColors.krowCharcoal, - ), - ), - ), - ); - } - - Widget _buildReviewRow(String label, String value) { - return Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - label, - style: const TextStyle(fontSize: 14, color: AppColors.krowMuted), - ), - Text( - value, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - ); - } - - Widget _buildReviewCard(List children) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), // rounded-xl - border: Border.all(color: AppColors.krowBorder), - ), - child: Column(children: children), - ); - } - - Widget _buildPositionReviewCard(_Position pos) { - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), // rounded-xl - border: Border.all(color: AppColors.krowBorder), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - pos.role.isEmpty ? 'Unspecified Role' : pos.role, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: AppColors.krowCharcoal, - ), - ), - ], - ), - Padding( - padding: const EdgeInsets.only(top: 4), - child: Row( - children: [ - Text( - '${pos.count} worker${pos.count > 1 ? 's' : ''}', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - const SizedBox(width: 12), - Text( - '\$${pos.rate}/hr', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - const SizedBox(height: 12), - ...pos.schedules.map( - (sche) => Container( - margin: const EdgeInsets.only(bottom: 6), - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: const Color(0xFFF8FAFC), // slate-50 - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - sche.selectedDays.isNotEmpty - ? sche.selectedDays.join(', ') - : 'No days selected', - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - Text( - (sche.startTime.isNotEmpty || sche.endTime.isNotEmpty) - ? '${sche.startTime} - ${sche.endTime}' - : 'Time not set', - style: const TextStyle( - fontSize: 12, - color: AppColors.krowMuted, - ), - ), - ], - ), - ), - ), - ], - ), - ); - } - - Widget _buildAddButton({ - required String label, - required VoidCallback onTap, - bool dashed = false, - bool isPrimary = true, - bool small = false, - }) { - return GestureDetector( - onTap: onTap, - child: Container( - width: double.infinity, - height: small ? 36 : 44, // h-9 or h-11 - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: isPrimary ? AppColors.krowBlue : AppColors.krowBorder, - width: isPrimary && dashed ? 2 : 1, - style: dashed - ? BorderStyle.solid - : BorderStyle - .solid, // Flutter doesn't support dashed native easily without package, sticking to solid per instruction or using custom painter. - // NOTE: React used `border-dashed`. Without external package, solid is standard fallback. - ), - color: isPrimary ? Colors.white : Colors.transparent, - ), - child: Center( - child: Text( - '+ $label', - style: TextStyle( - color: isPrimary ? AppColors.krowBlue : AppColors.krowMuted, - fontWeight: isPrimary ? FontWeight.bold : FontWeight.w500, - fontSize: small ? 12 : 14, - ), - ), - ), - ), - ); - } - - Widget _buildFooterButton({ - required String label, - required VoidCallback onTap, - }) { - return Container( - padding: EdgeInsets.only( - left: 20, - right: 20, - top: 20, - bottom: MediaQuery.of(context).padding.bottom + 20, - ), - decoration: const BoxDecoration( - color: Colors.white, - border: Border(top: BorderSide(color: AppColors.krowBorder)), - ), - child: SizedBox( - width: double.infinity, - height: 48, // h-12 - child: ElevatedButton( - onPressed: onTap, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowBlue, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), // rounded-md - ), - elevation: 0, - ), - child: Text( - label, - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 14, - ), - ), - ), - ), - ); - } -} - -class _SuccessView extends StatelessWidget { - const _SuccessView(); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Container( - width: double.infinity, - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [AppColors.krowBlue, Color(0xFF0830B8)], - ), - ), - child: SafeArea( - child: Center( - child: Container( - margin: const EdgeInsets.symmetric(horizontal: 40), - padding: const EdgeInsets.all(32), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), // rounded-lg - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.2), - blurRadius: 20, - offset: const Offset(0, 10), - ), - ], - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 64, - height: 64, - decoration: const BoxDecoration( - color: AppColors.krowYellow, - shape: BoxShape.circle, - ), - child: const Center( - child: Icon( - LucideIcons.check, - color: AppColors.krowCharcoal, - size: 32, - ), - ), - ), - const SizedBox(height: 16), - const Text( - 'Schedule Created!', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: AppColors.krowCharcoal, - ), - ), - const SizedBox(height: 8), - const Text( - 'Your recurring schedule has been set up. Workers will be auto-assigned weekly.', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - color: AppColors.krowMuted, - height: 1.5, - ), - ), - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - height: 48, - child: ElevatedButton( - onPressed: () => context.go('/client-home'), - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.krowCharcoal, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), // rounded-md - ), - elevation: 0, - ), - child: const Text( - 'Back to Orders', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ), - ), - ), - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_screen.dart deleted file mode 100644 index 9a4b31b2..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/create_order_screen.dart +++ /dev/null @@ -1,242 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../../theme.dart'; - -class CreateOrderScreen extends StatefulWidget { - const CreateOrderScreen({super.key}); - - @override - State createState() => _CreateOrderScreenState(); -} - -class _CreateOrderScreenState extends State { - final List> _orderTypes = [ - { - 'id': 'rapid', - 'icon': LucideIcons.zap, - 'title': 'RAPID', - 'description': 'URGENT same-day Coverage', - }, - { - 'id': 'one-time', - 'icon': LucideIcons.calendar, - 'title': 'One-Time', - 'description': 'Single Event or Shift Request', - }, - { - 'id': 'recurring', - 'icon': LucideIcons.refreshCw, - 'title': 'Recurring', - 'description': 'Ongoing Weekly / Monthly Coverage', - }, - { - 'id': 'permanent', - 'icon': LucideIcons.users, - 'title': 'Permanent', - 'description': 'Long-Term Staffing Placement', - }, - ]; - - Map _getTypeColors(String id) { - switch (id) { - case 'rapid': - return { - 'bg': const Color(0xFFFEF2F2), // red-50 - 'border': const Color(0xFFFECACA), // red-200 - 'iconBg': const Color(0xFFFEE2E2), // red-100 - 'icon': const Color(0xFFDC2626), // red-600 - 'text': const Color(0xFF7F1D1D), // red-900 - 'desc': const Color(0xFFB91C1C), // red-700 - }; - case 'one-time': - return { - 'bg': const Color(0xFFEFF6FF), // blue-50 - 'border': const Color(0xFFBFDBFE), // blue-200 - 'iconBg': const Color(0xFFDBEAFE), // blue-100 - 'icon': const Color(0xFF2563EB), // blue-600 - 'text': const Color(0xFF1E3A8A), // blue-900 - 'desc': const Color(0xFF1D4ED8), // blue-700 - }; - case 'recurring': - return { - 'bg': const Color(0xFFFAF5FF), // purple-50 - 'border': const Color(0xFFE9D5FF), // purple-200 - 'iconBg': const Color(0xFFF3E8FF), // purple-100 - 'icon': const Color(0xFF9333EA), // purple-600 - 'text': const Color(0xFF581C87), // purple-900 - 'desc': const Color(0xFF7E22CE), // purple-700 - }; - case 'permanent': - return { - 'bg': const Color(0xFFF0FDF4), // green-50 - 'border': const Color(0xFFBBF7D0), // green-200 - 'iconBg': const Color(0xFFDCFCE7), // green-100 - 'icon': const Color(0xFF16A34A), // green-600 - 'text': const Color(0xFF14532D), // green-900 - 'desc': const Color(0xFF15803D), // green-700 - }; - default: - return { - 'bg': Colors.white, - 'border': AppColors.krowBorder, - 'iconBg': AppColors.krowBackground, - 'icon': AppColors.krowMuted, - 'text': AppColors.krowCharcoal, - 'desc': AppColors.krowMuted, - }; - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.krowBackground, - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1.0), - child: Container(color: AppColors.krowBorder, height: 1.0), - ), - leading: IconButton( - icon: const Icon(LucideIcons.chevronLeft, color: AppColors.krowMuted), - onPressed: () => context.go('/client-home'), - ), - title: const Text( - 'Create Order', - style: TextStyle( - color: AppColors.krowCharcoal, - fontWeight: FontWeight.w600, - fontSize: 18, - ), - ), - ), - body: SafeArea( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Padding( - padding: EdgeInsets.only(bottom: 24), - child: Text( - 'ORDER TYPE', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: AppColors.krowMuted, - letterSpacing: 0.5, // Matches tracking-wide approx - ), - ), - ), - Expanded( - child: GridView.builder( - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - mainAxisSpacing: 16, - crossAxisSpacing: 16, - childAspectRatio: 1, // Adjust for layout - ), - itemCount: _orderTypes.length, - itemBuilder: (context, index) { - final type = _orderTypes[index]; - final colors = _getTypeColors(type['id']); - - return _OrderTypeCard( - icon: type['icon'], - title: type['title'], - description: type['description'], - colors: colors, - onTap: () { - String routePath = ''; - switch (type['id']) { - case 'rapid': - routePath = '/create-order/rapid'; - break; - case 'one-time': - routePath = '/create-order/one-time'; - break; - case 'recurring': - routePath = '/create-order/recurring'; - break; - case 'permanent': - routePath = '/create-order/permanent'; - break; - } - context.push(routePath); - }, - ); - }, - ), - ), - ], - ), - ), - ), - ); - } -} - -class _OrderTypeCard extends StatelessWidget { - final IconData icon; - final String title; - final String description; - final Map colors; - final VoidCallback onTap; - - const _OrderTypeCard({ - required this.icon, - required this.title, - required this.description, - required this.colors, - required this.onTap, - }); - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: onTap, - child: Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: colors['bg'], - borderRadius: BorderRadius.circular(8), // rounded-lg - border: Border.all(color: colors['border'], width: 2), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - width: 48, - height: 48, - margin: const EdgeInsets.only(bottom: 12), - decoration: BoxDecoration( - color: colors['iconBg'], - borderRadius: BorderRadius.circular(8), // rounded-lg - ), - child: Icon(icon, color: colors['icon'], size: 24), - ), - Text( - title, - style: TextStyle( - fontSize: 14, // text-sm - fontWeight: FontWeight.w600, // font-semibold - color: colors['text'], - ), - ), - const SizedBox(height: 4), - Text( - description, - style: TextStyle( - fontSize: 12, // text-xs - color: colors['desc'], - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/coverage_report_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/coverage_report_screen.dart deleted file mode 100644 index c5858edb..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/coverage_report_screen.dart +++ /dev/null @@ -1,449 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; - -class CoverageReportScreen extends StatelessWidget { - const CoverageReportScreen({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFF8FAFC), // slate-50 - body: SingleChildScrollView( - child: Column( - children: [ - // Header - Container( - padding: const EdgeInsets.only( - top: 60, - left: 20, - right: 20, - bottom: 32, - ), - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [Color(0xFF0A39DF), Color(0xFF0830B8)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Coverage Report', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - Text( - 'Staffing levels & gaps', - style: TextStyle( - fontSize: 12, - color: Colors.white70, - ), - ), - ], - ), - ], - ), - GestureDetector( - onTap: () { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Exporting Coverage Report (Placeholder)'), - duration: Duration(seconds: 2), - ), - ); - }, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), - child: const Row( - children: [ - Icon( - LucideIcons.download, - size: 14, - color: Color(0xFF0A39DF), - ), - SizedBox(width: 6), - Text( - 'Export', - style: TextStyle( - color: Color(0xFF0A39DF), - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - ), - ], - ), - ), - - // Content - Transform.translate( - offset: const Offset(0, -16), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Summary Cards - Row( - children: [ - const Expanded( - child: _CoverageStatCard( - label: 'Avg Coverage', - value: '96%', - icon: LucideIcons.trendingUp, - color: Color(0xFF7C3AED), // violet-600 - ), - ), - const SizedBox(width: 8), - const Expanded( - child: _CoverageStatCard( - label: 'Full', - value: '5', - icon: LucideIcons.checkCircle2, - color: Color(0xFF059669), // emerald-600 - ), - ), - const SizedBox(width: 8), - const Expanded( - child: _CoverageStatCard( - label: 'Needs Help', - value: '2', - icon: LucideIcons.alertCircle, - color: Color(0xFFDC2626), // red-600 - ), - ), - ], - ), - const SizedBox(height: 24), - - const Text( - 'NEXT 7 DAYS', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Color(0xFF64748B), - letterSpacing: 1.2, - ), - ), - const SizedBox(height: 12), - - // Daily Coverage List - const _DailyCoverageItem( - date: 'Sat, Dec 20', - confirmed: 12, - needed: 12, - coverage: 100, - ), - const _DailyCoverageItem( - date: 'Sun, Dec 21', - confirmed: 8, - needed: 10, - coverage: 80, - ), - const _DailyCoverageItem( - date: 'Mon, Dec 22', - confirmed: 15, - needed: 15, - coverage: 100, - ), - const _DailyCoverageItem( - date: 'Tue, Dec 23', - confirmed: 5, - needed: 8, - coverage: 62, - ), - const _DailyCoverageItem( - date: 'Wed, Dec 24', - confirmed: 12, - needed: 12, - coverage: 100, - ), - - const SizedBox(height: 24), - - // Insights Card - Container( - width: double.infinity, - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFFF5F3FF), Color(0xFFEDE9FE)], - ), - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: const Color(0xFF7C3AED).withOpacity(0.1), - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - '💡 Coverage Insights', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 12), - _insightRow( - 'Your average coverage rate is ', - '96%', - ' - above industry standard', - ), - _insightRow( - '', - '2 days', - ' need immediate attention to reach full coverage', - ), - _insightRow( - 'Weekend coverage is typically ', - '98%', - ' vs weekday 94%', - ), - ], - ), - ), - const SizedBox(height: 100), - ], - ), - ), - ), - ], - ), - ), - ); - } - - Widget _insightRow(String prefix, String bold, String suffix) { - return Padding( - padding: const EdgeInsets.only(bottom: 8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text('• ', style: TextStyle(color: Color(0xFF334155))), - Expanded( - child: RichText( - text: TextSpan( - style: const TextStyle( - color: Color(0xFF334155), - fontSize: 13, - height: 1.4, - ), - children: [ - TextSpan(text: prefix), - TextSpan( - text: bold, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - TextSpan(text: suffix), - ], - ), - ), - ), - ], - ), - ); - } -} - -class _CoverageStatCard extends StatelessWidget { - final String label; - final String value; - final IconData icon; - final Color color; - - const _CoverageStatCard({ - required this.label, - required this.value, - required this.icon, - required this.color, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.06), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon(icon, size: 12, color: color), - const SizedBox(width: 4), - Text( - label, - style: const TextStyle(fontSize: 10, color: Color(0xFF64748B)), - ), - ], - ), - const SizedBox(height: 8), - Text( - value, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - ], - ), - ); - } -} - -class _DailyCoverageItem extends StatelessWidget { - final String date; - final int confirmed; - final int needed; - final int coverage; - - const _DailyCoverageItem({ - required this.date, - required this.confirmed, - required this.needed, - required this.coverage, - }); - - @override - Widget build(BuildContext context) { - Color getStatusColor() { - if (coverage == 100) return const Color(0xFF059669); - if (coverage >= 80) return const Color(0xFF2563EB); - return const Color(0xFFDC2626); - } - - Color getStatusBg() { - if (coverage == 100) return const Color(0xFFD1FAE5); - if (coverage >= 80) return const Color(0xFFDBEAFE); - return const Color(0xFFFEE2E2); - } - - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 2), - ], - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - date, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: Color(0xFF0F172A), - ), - ), - Text( - '$confirmed/$needed workers confirmed', - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), - ), - ), - ], - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: getStatusBg(), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - '$coverage%', - style: TextStyle( - color: getStatusColor(), - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - const SizedBox(height: 12), - ClipRRect( - borderRadius: BorderRadius.circular(4), - child: LinearProgressIndicator( - value: coverage / 100, - backgroundColor: const Color(0xFFF1F5F9), - valueColor: AlwaysStoppedAnimation(getStatusColor()), - minHeight: 6, - ), - ), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text( - needed - confirmed > 0 - ? '${needed - confirmed} spots remaining' - : 'Fully staffed', - style: const TextStyle(fontSize: 10, color: Color(0xFF94A3B8)), - ), - ], - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/daily_ops_report_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/daily_ops_report_screen.dart deleted file mode 100644 index 69d785d6..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/daily_ops_report_screen.dart +++ /dev/null @@ -1,517 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import 'package:intl/intl.dart'; - -class DailyOpsReportScreen extends StatefulWidget { - const DailyOpsReportScreen({super.key}); - - @override - State createState() => _DailyOpsReportScreenState(); -} - -class _DailyOpsReportScreenState extends State { - DateTime selectedDate = DateTime.now(); - - Future _selectDate(BuildContext context) async { - final DateTime? picked = await showDatePicker( - context: context, - initialDate: selectedDate, - firstDate: DateTime(2020), - lastDate: DateTime(2030), - ); - if (picked != null && picked != selectedDate) { - setState(() { - selectedDate = picked; - }); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFF8FAFC), // slate-50 - body: SingleChildScrollView( - child: Column( - children: [ - // Header with Gradient - Container( - padding: const EdgeInsets.only( - top: 60, - left: 20, - right: 20, - bottom: 32, - ), - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [ - Color(0xFF0A39DF), // Krow Blue - Color(0xFF0830B8), // Darker Blue - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Daily Ops Report', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - Text( - 'Real-time shift tracking', - style: TextStyle( - fontSize: 12, - color: Colors.white.withOpacity(0.8), - ), - ), - ], - ), - ], - ), - GestureDetector( - onTap: () { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Exporting Daily Operations Report (Placeholder)'), - duration: Duration(seconds: 2), - ), - ); - }, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), - child: const Row( - children: [ - Icon( - LucideIcons.download, - size: 14, - color: Color(0xFF0A39DF), - ), - SizedBox(width: 6), - Text( - 'Export', - style: TextStyle( - color: Color(0xFF0A39DF), - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - ), - ], - ), - ], - ), - ), - - // Content - Transform.translate( - offset: const Offset(0, -16), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Date Selector - GestureDetector( - onTap: () => _selectDate(context), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 12, - ), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 10, - offset: const Offset(0, 4), - ), - ], - ), - child: Row( - children: [ - const Icon( - LucideIcons.calendar, - size: 18, - color: Color(0xFF64748B), - ), - const SizedBox(width: 12), - Text( - DateFormat('yyyy-MM-dd').format(selectedDate), - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Color(0xFF1E293B), - ), - ), - const Spacer(), - const Icon( - LucideIcons.chevronDown, - size: 16, - color: Color(0xFF64748B), - ), - ], - ), - ), - ), - const SizedBox(height: 20), - - // Summary Stats - GridView.count( - padding: EdgeInsets.zero, - crossAxisCount: 2, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - mainAxisSpacing: 12, - crossAxisSpacing: 12, - childAspectRatio: 1.4, - children: const [ - _OpsStatCard( - icon: LucideIcons.calendar, - label: 'Scheduled', - value: '12', - subValue: 'shifts', - iconColor: Color(0xFF2563EB), - badgeColor: Color(0xFFDBEAFE), - badgeTextColor: Color(0xFF1D4ED8), - ), - _OpsStatCard( - icon: LucideIcons.users, - label: 'Workers', - value: '45/48', - subValue: 'confirmed', - iconColor: Color(0xFF7C3AED), - badgeColor: Color(0xFFF3E8FF), - badgeTextColor: Color(0xFF6D28D9), - ), - _OpsStatCard( - icon: LucideIcons.clock, - label: 'In Progress', - value: '4', - subValue: 'active now', - iconColor: Color(0xFFD97706), - badgeColor: Color(0xFFFEF3C7), - badgeTextColor: Color(0xFFB45309), - ), - _OpsStatCard( - icon: LucideIcons.checkCircle2, - label: 'Completed', - value: '8', - subValue: 'done today', - iconColor: Color(0xFF059669), - badgeColor: Color(0xFFD1FAE5), - badgeTextColor: Color(0xFF047857), - ), - ], - ), - - const SizedBox(height: 24), - - const Text( - 'ALL SHIFTS', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Color(0xFF64748B), - letterSpacing: 1.2, - ), - ), - const SizedBox(height: 12), - - // Shift List - const _ShiftListItem( - title: 'Night Shift - Logistics', - location: 'Hub 4, North Zone', - startTime: '22:00', - endTime: '06:00', - workersNeeded: '8', - filled: '8', - hourlyRate: '\$18', - status: 'IN_PROGRESS', - statusColor: Color(0xFFD97706), - statusBg: Color(0xFFFEF3C7), - ), - const _ShiftListItem( - title: 'Morning Delivery Support', - location: 'East Side Hub', - startTime: '08:00', - endTime: '16:00', - workersNeeded: '12', - filled: '12', - hourlyRate: '\$16', - status: 'COMPLETED', - statusColor: Color(0xFF059669), - statusBg: Color(0xFFD1FAE5), - ), - const _ShiftListItem( - title: 'Warehouse Sorting', - location: 'Hub 2, South', - startTime: '09:00', - endTime: '17:00', - workersNeeded: '15', - filled: '15', - hourlyRate: '\$17', - status: 'COMPLETED', - statusColor: Color(0xFF059669), - statusBg: Color(0xFFD1FAE5), - ), - const SizedBox(height: 100), - ], - ), - ), - ), - ], - ), - ), - ); - } -} - -class _OpsStatCard extends StatelessWidget { - final IconData icon; - final String label; - final String value; - final String subValue; - final Color iconColor; - final Color badgeColor; - final Color badgeTextColor; - - const _OpsStatCard({ - required this.icon, - required this.label, - required this.value, - required this.subValue, - required this.iconColor, - required this.badgeColor, - required this.badgeTextColor, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.06), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Icon(icon, size: 14, color: iconColor), - const SizedBox(width: 8), - Text( - label, - style: const TextStyle(fontSize: 10, color: Color(0xFF64748B)), - ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - value, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 4), - Container( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - decoration: BoxDecoration( - color: badgeColor, - borderRadius: BorderRadius.circular(4), - ), - child: Text( - subValue, - style: TextStyle( - fontSize: 8, - fontWeight: FontWeight.bold, - color: badgeTextColor, - ), - ), - ), - ], - ), - ], - ), - ); - } -} - -class _ShiftListItem extends StatelessWidget { - final String title; - final String location; - final String startTime; - final String endTime; - final String workersNeeded; - final String filled; - final String hourlyRate; - final String status; - final Color statusColor; - final Color statusBg; - - const _ShiftListItem({ - required this.title, - required this.location, - required this.startTime, - required this.endTime, - required this.workersNeeded, - required this.filled, - required this.hourlyRate, - required this.status, - required this.statusColor, - required this.statusBg, - }); - - @override - Widget build(BuildContext context) { - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 2), - ], - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - ), - ), - const SizedBox(height: 4), - Row( - children: [ - const Icon( - LucideIcons.mapPin, - size: 12, - color: Color(0xFF94A3B8), - ), - const SizedBox(width: 4), - Text( - location, - style: const TextStyle( - fontSize: 11, - color: Color(0xFF64748B), - ), - ), - ], - ), - ], - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: statusBg, - borderRadius: BorderRadius.circular(6), - ), - child: Text( - status, - style: TextStyle( - color: statusColor, - fontSize: 10, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _infoItem('Time', startTime + ' - ' + endTime), - _infoItem('Workers', workersNeeded + '/' + filled), - _infoItem('Rate', '$hourlyRate/hr'), - ], - ), - ], - ), - ); - } - - Widget _infoItem(String label, String value) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - label, - style: const TextStyle(fontSize: 10, color: Color(0xFF94A3B8)), - ), - const SizedBox(height: 2), - Text( - value, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Color(0xFF1E293B), - ), - ), - ], - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/forecast_report_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/forecast_report_screen.dart deleted file mode 100644 index d8050356..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/forecast_report_screen.dart +++ /dev/null @@ -1,587 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import 'package:fl_chart/fl_chart.dart'; - -class ForecastReportScreen extends StatelessWidget { - const ForecastReportScreen({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFF8FAFC), // slate-50 - body: SingleChildScrollView( - child: Column( - children: [ - // Header - Container( - padding: const EdgeInsets.only( - top: 60, - left: 20, - right: 20, - bottom: 32, - ), - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [Color(0xFF0A39DF), Color(0xFF121826)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Forecast Report', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - Text( - 'Next 4 weeks projection', - style: TextStyle( - fontSize: 12, - color: Colors.white70, - ), - ), - ], - ), - ], - ), - GestureDetector( - onTap: () { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Exporting Forecast Report (Placeholder)'), - duration: Duration(seconds: 2), - ), - ); - }, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), - child: const Row( - children: [ - Icon( - LucideIcons.download, - size: 14, - color: Color(0xFF0A39DF), - ), - SizedBox(width: 6), - Text( - 'Export', - style: TextStyle( - color: Color(0xFF0A39DF), - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - ), - ], - ), - ), - - // Content - Transform.translate( - offset: const Offset(0, -16), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Summary Cards Grid - GridView.count( - padding: EdgeInsets.zero, - crossAxisCount: 2, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - mainAxisSpacing: 12, - crossAxisSpacing: 12, - childAspectRatio: 1.4, - children: const [ - _ForecastStatCard( - label: '4-Week Forecast', - value: '\$45,200', - badge: 'Total projected', - icon: LucideIcons.dollarSign, - color: Color(0xFFD97706), // amber-600 - bgColor: Color(0xFFFEF3C7), // amber-100 - ), - _ForecastStatCard( - label: 'Avg Weekly', - value: '\$11,300', - badge: 'Per week', - icon: LucideIcons.trendingUp, - color: Color(0xFF2563EB), // blue-600 - bgColor: Color(0xFFDBEAFE), // blue-100 - ), - _ForecastStatCard( - label: 'Total Shifts', - value: '124', - badge: 'Scheduled', - icon: LucideIcons.calendar, - color: Color(0xFF7C3AED), // violet-600 - bgColor: Color(0xFFF3E8FF), // violet-100 - ), - _ForecastStatCard( - label: 'Total Hours', - value: '992', - badge: 'Worker hours', - icon: LucideIcons.users, - color: Color(0xFF059669), // emerald-600 - bgColor: Color(0xFFD1FAE5), // emerald-100 - ), - ], - ), - const SizedBox(height: 24), - - // Chart Card - Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.04), - blurRadius: 10, - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Spending Forecast', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 24), - SizedBox( - height: 180, - child: LineChart( - LineChartData( - gridData: FlGridData( - show: true, - drawVerticalLine: false, - horizontalInterval: 5000, - getDrawingHorizontalLine: (value) { - return FlLine( - color: const Color(0xFFE2E8F0), - strokeWidth: 1, - ); - }, - ), - titlesData: FlTitlesData( - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - getTitlesWidget: (value, meta) { - const titles = ['W1', 'W2', 'W3', 'W4']; - if (value.toInt() < titles.length) { - return Padding( - padding: const EdgeInsets.only( - top: 8, - ), - child: Text( - titles[value.toInt()], - style: const TextStyle( - color: Color(0xFF94A3B8), - fontSize: 10, - ), - ), - ); - } - return const SizedBox.shrink(); - }, - ), - ), - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 40, - getTitlesWidget: (value, meta) { - if (value % 5000 == 0 && value > 0) { - return Text( - '\$${(value / 1000).toInt()}k', - style: const TextStyle( - color: Color(0xFF94A3B8), - fontSize: 10, - ), - ); - } - return const SizedBox.shrink(); - }, - ), - ), - topTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - rightTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - ), - borderData: FlBorderData(show: false), - lineBarsData: [ - LineChartBarData( - spots: const [ - FlSpot(0, 10240), - FlSpot(1, 12480), - FlSpot(2, 11320), - FlSpot(3, 11160), - ], - isCurved: true, - color: const Color(0xFFF59E0B), - barWidth: 3, - dotData: const FlDotData(show: true), - belowBarData: BarAreaData( - show: true, - color: const Color( - 0xFFF59E0B, - ).withOpacity(0.1), - ), - ), - ], - minY: 5000, - maxY: 15000, - ), - ), - ), - ], - ), - ), - const SizedBox(height: 24), - - const Text( - 'WEEKLY BREAKDOWN', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Color(0xFF64748B), - letterSpacing: 1.2, - ), - ), - const SizedBox(height: 12), - - // Weekly Breakdown List - const _WeeklyBreakdownItem( - week: 'Week 1', - spend: '\$10,240', - shifts: '32', - hours: '256', - ), - const _WeeklyBreakdownItem( - week: 'Week 2', - spend: '\$12,480', - shifts: '38', - hours: '304', - ), - const _WeeklyBreakdownItem( - week: 'Week 3', - spend: '\$11,320', - shifts: '30', - hours: '240', - ), - const _WeeklyBreakdownItem( - week: 'Week 4', - spend: '\$11,160', - shifts: '24', - hours: '192', - ), - const SizedBox(height: 24), - - // Insights Card - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFFFEF3C7), Color(0xFFFFF7ED)], - ), - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: const Color(0xFFF59E0B).withOpacity(0.1), - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - '💡 Forecast Insights', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 12), - _insightRow( - 'Week 3 has ', - 'highest projected spend', - ' - plan ahead', - ), - _insightRow( - 'Average cost per shift is ', - '\$350', - '', - ), - _insightRow( - 'Consider bulk scheduling to save ', - '12%', - ' on booking fees', - ), - ], - ), - ), - const SizedBox(height: 100), - ], - ), - ), - ), - ], - ), - ), - ); - } - - Widget _insightRow(String prefix, String bold, String suffix) { - return Padding( - padding: const EdgeInsets.only(bottom: 8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text('• ', style: TextStyle(color: Color(0xFF334155))), - Expanded( - child: RichText( - text: TextSpan( - style: const TextStyle( - color: Color(0xFF334155), - fontSize: 13, - height: 1.4, - ), - children: [ - TextSpan(text: prefix), - TextSpan( - text: bold, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - TextSpan(text: suffix), - ], - ), - ), - ), - ], - ), - ); - } -} - -class _ForecastStatCard extends StatelessWidget { - final String label; - final String value; - final String badge; - final IconData icon; - final Color color; - final Color bgColor; - - const _ForecastStatCard({ - required this.label, - required this.value, - required this.badge, - required this.icon, - required this.color, - required this.bgColor, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.06), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Icon(icon, size: 14, color: color), - const SizedBox(width: 8), - Text( - label, - style: const TextStyle(fontSize: 10, color: Color(0xFF64748B)), - ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - value, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 4), - Container( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - decoration: BoxDecoration( - color: bgColor, - borderRadius: BorderRadius.circular(4), - ), - child: Text( - badge, - style: TextStyle( - fontSize: 8, - fontWeight: FontWeight.bold, - color: color, - ), - ), - ), - ], - ), - ], - ), - ); - } -} - -class _WeeklyBreakdownItem extends StatelessWidget { - final String week; - final String spend; - final String shifts; - final String hours; - - const _WeeklyBreakdownItem({ - required this.week, - required this.spend, - required this.shifts, - required this.hours, - }); - - @override - Widget build(BuildContext context) { - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 2), - ], - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - week, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: Color(0xFF0F172A), - ), - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: const Color(0xFFFEF3C7), // amber-100 - borderRadius: BorderRadius.circular(6), - ), - child: Text( - spend, - style: const TextStyle( - color: Color(0xFFB45309), // amber-700 - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _infoItem('Shifts', shifts), - _infoItem('Hours', hours), - _infoItem( - 'Avg/Shift', - '\$${(double.parse(spend.replaceAll('\$', '').replaceAll(',', '')) / double.parse(shifts)).toStringAsFixed(0)}', - ), - ], - ), - ], - ), - ); - } - - Widget _infoItem(String label, String value) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - label, - style: const TextStyle(fontSize: 10, color: Color(0xFF94A3B8)), - ), - const SizedBox(height: 2), - Text( - value, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Color(0xFF1E293B), - ), - ), - ], - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/no_show_report_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/no_show_report_screen.dart deleted file mode 100644 index 96d41ad3..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/no_show_report_screen.dart +++ /dev/null @@ -1,441 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; - -class NoShowReportScreen extends StatelessWidget { - const NoShowReportScreen({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFF8FAFC), // slate-50 - body: SingleChildScrollView( - child: Column( - children: [ - // Header - Container( - padding: const EdgeInsets.only( - top: 60, - left: 20, - right: 20, - bottom: 32, - ), - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [Color(0xFF121826), Color(0xFF2D3748)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'No-Show Report', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - Text( - 'Reliability tracking', - style: TextStyle( - fontSize: 12, - color: Colors.white70, - ), - ), - ], - ), - ], - ), - GestureDetector( - onTap: () { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Exporting No-Show Report (Placeholder)'), - duration: Duration(seconds: 2), - ), - ); - }, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), - child: const Row( - children: [ - Icon( - LucideIcons.download, - size: 14, - color: Color(0xFF121826), - ), - SizedBox(width: 6), - Text( - 'Export', - style: TextStyle( - color: Color(0xFF121826), - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - ), - ], - ), - ), - - // Content - Transform.translate( - offset: const Offset(0, -16), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Summary Cards - Row( - children: [ - const Expanded( - child: _NoShowStatCard( - label: 'No-Shows', - value: '4', - icon: LucideIcons.xCircle, - color: Color(0xFFDC2626), // red-600 - ), - ), - const SizedBox(width: 8), - const Expanded( - child: _NoShowStatCard( - label: 'Rate', - value: '1.2%', - icon: LucideIcons.trendingDown, - color: Color(0xFF059669), // emerald-600 - ), - ), - const SizedBox(width: 8), - const Expanded( - child: _NoShowStatCard( - label: 'Workers', - value: '3', - icon: LucideIcons.user, - color: Color(0xFF7C3AED), // violet-600 - ), - ), - ], - ), - const SizedBox(height: 24), - - const Text( - 'WORKERS WITH NO-SHOWS', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Color(0xFF64748B), - letterSpacing: 1.2, - ), - ), - const SizedBox(height: 12), - - // Workers List - const _WorkerNoShowItem( - name: 'James Wilson', - count: 2, - latestIncident: 'Dec 12, 2025', - risk: 'High Risk', - ), - const _WorkerNoShowItem( - name: 'Sarah Parker', - count: 1, - latestIncident: 'Dec 05, 2025', - risk: 'Medium Risk', - ), - const _WorkerNoShowItem( - name: 'Mike Ross', - count: 1, - latestIncident: 'Nov 28, 2025', - risk: 'Low Risk', - ), - - const SizedBox(height: 24), - - // Insights Card - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFFFEF2F2), Color(0xFFFFF1F2)], - ), - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: const Color(0xFFDC2626).withOpacity(0.1), - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - '💡 Reliability Insights', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 12), - _insightRow( - 'Your no-show rate of ', - '1.2%', - ' is below industry average', - ), - _insightRow( - '', - '1 worker', - ' has multiple incidents this month', - ), - _insightRow( - 'Consider implementing ', - 'confirmation reminders', - ' 24hrs before shifts', - ), - ], - ), - ), - const SizedBox(height: 100), - ], - ), - ), - ), - ], - ), - ), - ); - } - - Widget _insightRow(String prefix, String bold, String suffix) { - return Padding( - padding: const EdgeInsets.only(bottom: 8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text('• ', style: TextStyle(color: Color(0xFF334155))), - Expanded( - child: RichText( - text: TextSpan( - style: const TextStyle( - color: Color(0xFF334155), - fontSize: 13, - height: 1.4, - ), - children: [ - TextSpan(text: prefix), - TextSpan( - text: bold, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - TextSpan(text: suffix), - ], - ), - ), - ), - ], - ), - ); - } -} - -class _NoShowStatCard extends StatelessWidget { - final String label; - final String value; - final IconData icon; - final Color color; - - const _NoShowStatCard({ - required this.label, - required this.value, - required this.icon, - required this.color, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.06), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon(icon, size: 12, color: color), - const SizedBox(width: 4), - Text( - label, - style: const TextStyle(fontSize: 10, color: Color(0xFF64748B)), - ), - ], - ), - const SizedBox(height: 8), - Text( - value, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - ], - ), - ); - } -} - -class _WorkerNoShowItem extends StatelessWidget { - final String name; - final int count; - final String latestIncident; - final String risk; - - const _WorkerNoShowItem({ - required this.name, - required this.count, - required this.latestIncident, - required this.risk, - }); - - @override - Widget build(BuildContext context) { - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 2), - ], - ), - child: Column( - children: [ - Row( - children: [ - Container( - width: 40, - height: 40, - decoration: const BoxDecoration( - color: Color(0xFFFEE2E2), // red-100 - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.user, - size: 20, - color: Color(0xFFDC2626), // red-600 - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: Color(0xFF0F172A), - ), - ), - Text( - '$count no-show${count > 1 ? 's' : ''}', - style: const TextStyle( - fontSize: 12, - color: Color(0xFF64748B), - ), - ), - ], - ), - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: risk == 'High Risk' - ? const Color(0xFFFEE2E2) - : const Color(0xFFF1F5F9), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - risk, - style: TextStyle( - color: risk == 'High Risk' - ? const Color(0xFFDC2626) - : const Color(0xFF64748B), - fontSize: 10, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - const SizedBox(height: 12), - const Divider(height: 1, color: Color(0xFFF1F5F9)), - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'Latest incident', - style: TextStyle(fontSize: 11, color: Color(0xFF94A3B8)), - ), - Text( - latestIncident, - style: const TextStyle( - fontSize: 11, - fontWeight: FontWeight.bold, - color: Color(0xFF475569), - ), - ), - ], - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/performance_report_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/performance_report_screen.dart deleted file mode 100644 index a70e8a81..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/performance_report_screen.dart +++ /dev/null @@ -1,523 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; - -class PerformanceReportScreen extends StatelessWidget { - const PerformanceReportScreen({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFF8FAFC), // slate-50 - body: SingleChildScrollView( - child: Column( - children: [ - // Header - Container( - padding: const EdgeInsets.only( - top: 60, - left: 20, - right: 20, - bottom: 32, - ), - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [Color(0xFF0A39DF), Color(0xFF0830B8)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Performance Report', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - Text( - 'Key metrics & benchmarks', - style: TextStyle( - fontSize: 12, - color: Colors.white70, - ), - ), - ], - ), - ], - ), - GestureDetector( - onTap: () { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Exporting Performance Report (Placeholder)'), - duration: Duration(seconds: 2), - ), - ); - }, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), - child: const Row( - children: [ - Icon( - LucideIcons.download, - size: 14, - color: Color(0xFF0A39DF), - ), - SizedBox(width: 6), - Text( - 'Export', - style: TextStyle( - color: Color(0xFF0A39DF), - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - ), - ], - ), - ), - - // Content - Transform.translate( - offset: const Offset(0, 16), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Overall Score Card - Container( - width: double.infinity, - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: const Color(0xFF0A39DF).withOpacity(0.05), - blurRadius: 20, - offset: const Offset(0, 10), - ), - ], - gradient: LinearGradient( - colors: [ - const Color(0xFF0A39DF).withOpacity(0.05), - const Color(0xFF121826).withOpacity(0.05), - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - child: Column( - children: [ - const Icon( - LucideIcons.barChart3, - size: 32, - color: Color(0xFF0A39DF), - ), - const SizedBox(height: 12), - const Text( - 'Overall Performance Score', - style: TextStyle( - fontSize: 13, - color: Color(0xFF64748B), - fontWeight: FontWeight.w500, - ), - ), - const SizedBox(height: 4), - const Text( - '94/100', - style: TextStyle( - fontSize: 40, - fontWeight: FontWeight.bold, - color: Color(0xFF0A39DF), - letterSpacing: -1, - ), - ), - const SizedBox(height: 12), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 4, - ), - decoration: BoxDecoration( - color: const Color(0xFF0A39DF).withOpacity(0.1), - borderRadius: BorderRadius.circular(20), - ), - child: const Text( - 'Excellent', - style: TextStyle( - color: Color(0xFF0A39DF), - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - ), - const SizedBox(height: 24), - - const Text( - 'KEY PERFORMANCE INDICATORS', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Color(0xFF64748B), - letterSpacing: 1.2, - ), - ), - const SizedBox(height: 12), - - // KPIs List - const _PerformanceKPI( - label: 'Fill Rate', - value: '96%', - target: '95%', - icon: LucideIcons.target, - color: Color(0xFF2563EB), - bgColor: Color(0xFFDBEAFE), - ), - const _PerformanceKPI( - label: 'Completion Rate', - value: '98%', - target: '98%', - icon: LucideIcons.checkCircle2, - color: Color(0xFF059669), - bgColor: Color(0xFFD1FAE5), - ), - const _PerformanceKPI( - label: 'On-Time Rate', - value: '95%', - target: '97%', - icon: LucideIcons.clock, - color: Color(0xFF7C3AED), - bgColor: Color(0xFFF3E8FF), - ), - const _PerformanceKPI( - label: 'Avg Fill Time', - value: '2.4 hrs', - target: '3 hrs', - icon: LucideIcons.trendingUp, - color: Color(0xFFD97706), - bgColor: Color(0xFFFEF3C7), - ), - - const SizedBox(height: 24), - - const Text( - 'ADDITIONAL METRICS', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Color(0xFF64748B), - letterSpacing: 1.2, - ), - ), - const SizedBox(height: 12), - - // Small Metrics Grid - GridView.count( - padding: EdgeInsets.zero, - crossAxisCount: 2, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - mainAxisSpacing: 12, - crossAxisSpacing: 12, - childAspectRatio: 1.8, - children: const [ - _SmallMetric(label: 'Total Shifts', value: '156'), - _SmallMetric(label: 'No-Show Rate', value: '1.2%'), - _SmallMetric(label: 'Worker Pool', value: '450'), - _SmallMetric(label: 'Avg Rating', value: '4.8 ⭐'), - ], - ), - - const SizedBox(height: 24), - - // Insights Card - Container( - width: double.infinity, - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - const Color(0xFF0A39DF).withOpacity(0.05), - const Color(0xFF121826).withOpacity(0.05), - ], - ), - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: const Color(0xFF0A39DF).withOpacity(0.1), - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - '💡 Performance Insights', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 12), - _insightRow( - 'You\'re ', - 'outperforming 87%', - ' of similar businesses', - ), - _insightRow( - 'Fill rate is ', - 'above target', - ' - maintain practices', - ), - _insightRow( - '', - 'Worker bonuses', - ' could improve retention further', - ), - ], - ), - ), - const SizedBox(height: 100), - ], - ), - ), - ), - ], - ), - ), - ); - } - - Widget _insightRow(String prefix, String bold, String suffix) { - return Padding( - padding: const EdgeInsets.only(bottom: 8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text('• ', style: TextStyle(color: Color(0xFF334155))), - Expanded( - child: RichText( - text: TextSpan( - style: const TextStyle( - color: Color(0xFF334155), - fontSize: 13, - height: 1.4, - ), - children: [ - TextSpan(text: prefix), - TextSpan( - text: bold, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - TextSpan(text: suffix), - ], - ), - ), - ), - ], - ), - ); - } -} - -class _PerformanceKPI extends StatelessWidget { - final String label; - final String value; - final String target; - final IconData icon; - final Color color; - final Color bgColor; - - const _PerformanceKPI({ - required this.label, - required this.value, - required this.target, - required this.icon, - required this.color, - required this.bgColor, - }); - - @override - Widget build(BuildContext context) { - bool metTarget = true; // Simplified for demo - if (label == 'On-Time Rate') metTarget = false; - - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 2), - ], - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: bgColor, - borderRadius: BorderRadius.circular(12), - ), - child: Icon(icon, size: 20, color: color), - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - label, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - ), - ), - Text( - 'Target: $target', - style: const TextStyle( - fontSize: 11, - color: Color(0xFF64748B), - ), - ), - ], - ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - value, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 6, - vertical: 2, - ), - decoration: BoxDecoration( - color: metTarget - ? const Color(0xFFD1FAE5) - : const Color(0xFFFEF3C7), - borderRadius: BorderRadius.circular(4), - ), - child: Text( - metTarget ? '✓ Met' : '↗ Close', - style: TextStyle( - color: metTarget - ? const Color(0xFF059669) - : const Color(0xFFD97706), - fontSize: 8, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - ], - ), - const SizedBox(height: 12), - ClipRRect( - borderRadius: BorderRadius.circular(4), - child: LinearProgressIndicator( - value: metTarget ? 0.98 : 0.95, - backgroundColor: const Color(0xFFF1F5F9), - valueColor: AlwaysStoppedAnimation(color), - minHeight: 6, - ), - ), - ], - ), - ); - } -} - -class _SmallMetric extends StatelessWidget { - final String label; - final String value; - - const _SmallMetric({required this.label, required this.value}); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 2), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - label, - style: const TextStyle(fontSize: 11, color: Color(0xFF64748B)), - ), - const SizedBox(height: 4), - Text( - value, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - ], - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/spend_report_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/spend_report_screen.dart deleted file mode 100644 index 1f9f9acc..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/reports/spend_report_screen.dart +++ /dev/null @@ -1,563 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; -import 'package:fl_chart/fl_chart.dart'; - -class SpendReportScreen extends StatelessWidget { - const SpendReportScreen({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFFF8FAFC), // slate-50 - body: SingleChildScrollView( - child: Column( - children: [ - // Header - Container( - padding: const EdgeInsets.only( - top: 60, - left: 20, - right: 20, - bottom: 32, - ), - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [Color(0xFF0A39DF), Color(0xFF0830B8)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - GestureDetector( - onTap: () => context.pop(), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - shape: BoxShape.circle, - ), - child: const Icon( - LucideIcons.arrowLeft, - color: Colors.white, - size: 20, - ), - ), - ), - const SizedBox(width: 12), - const Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Spend Report', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - Text( - 'Cost analysis & breakdown', - style: TextStyle( - fontSize: 12, - color: Colors.white70, - ), - ), - ], - ), - ], - ), - GestureDetector( - onTap: () { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Exporting Spend Report (Placeholder)'), - duration: Duration(seconds: 2), - ), - ); - }, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), - child: const Row( - children: [ - Icon( - LucideIcons.download, - size: 14, - color: Color(0xFF0A39DF), - ), - SizedBox(width: 6), - Text( - 'Export', - style: TextStyle( - color: Color(0xFF0A39DF), - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - ), - ], - ), - ), - - // Content - Transform.translate( - offset: const Offset(0, -16), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - children: [ - // Summary Cards - Row( - children: [ - const Expanded( - child: _SpendSummaryCard( - label: 'Total Spend', - value: '\$17,200', - badge: 'This week', - icon: LucideIcons.dollarSign, - color: Color(0xFF059669), // emerald-600 - badgeBg: Color(0xFFD1FAE5), // emerald-100 - ), - ), - const SizedBox(width: 12), - const Expanded( - child: _SpendSummaryCard( - label: 'Avg Daily', - value: '\$2,457', - badge: 'Per day', - icon: LucideIcons.trendingUp, - color: Color(0xFF2563EB), // blue-600 - badgeBg: Color(0xFFDBEAFE), // blue-100 - ), - ), - ], - ), - const SizedBox(height: 20), - - // Chart Card - Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.04), - blurRadius: 10, - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Daily Spend Trend', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 24), - SizedBox( - height: 180, - child: BarChart( - BarChartData( - alignment: BarChartAlignment.spaceAround, - maxY: 5000, - barTouchData: BarTouchData(enabled: false), - titlesData: FlTitlesData( - show: true, - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - getTitlesWidget: (value, meta) { - const titles = [ - 'Mon', - 'Tue', - 'Wed', - 'Thu', - 'Fri', - 'Sat', - 'Sun', - ]; - if (value.toInt() < titles.length) { - return Padding( - padding: const EdgeInsets.only( - top: 8.0, - ), - child: Text( - titles[value.toInt()], - style: const TextStyle( - color: Color(0xFF64748B), - fontSize: 10, - ), - ), - ); - } - return const SizedBox.shrink(); - }, - ), - ), - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 40, - getTitlesWidget: (value, meta) { - if (value % 1000 == 0) { - return Text( - '\$${(value / 1000).toInt()}k', - style: const TextStyle( - color: Color(0xFF64748B), - fontSize: 10, - ), - ); - } - return const SizedBox.shrink(); - }, - ), - ), - topTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - rightTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - ), - gridData: FlGridData( - show: true, - drawVerticalLine: false, - horizontalInterval: 1000, - getDrawingHorizontalLine: (value) { - return FlLine( - color: const Color(0xFFE2E8F0), - strokeWidth: 1, - ); - }, - ), - borderData: FlBorderData(show: false), - barGroups: [ - _makeGroupData(0, 1200), - _makeGroupData(1, 1800), - _makeGroupData(2, 2400), - _makeGroupData(3, 1600), - _makeGroupData(4, 3200), - _makeGroupData(5, 4100), - _makeGroupData(6, 2800), - ], - ), - ), - ), - ], - ), - ), - const SizedBox(height: 20), - - // Industry Breakdown - Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.04), - blurRadius: 10, - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Spend by Industry', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 20), - _IndustryRow( - name: 'Hospitality', - value: '\$8,500', - percent: 49.4, - ), - const SizedBox(height: 16), - _IndustryRow( - name: 'Events', - value: '\$5,200', - percent: 30.2, - ), - const SizedBox(height: 16), - _IndustryRow( - name: 'Retail', - value: '\$3,500', - percent: 20.4, - ), - ], - ), - ), - const SizedBox(height: 20), - - // Insights Card - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFFDCFCE7), Color(0xFFF0FDF4)], - ), - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: const Color(0xFF059669).withOpacity(0.1), - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - '💡 Cost Insights', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - color: Color(0xFF065F46), - ), - ), - const SizedBox(height: 12), - _insightRow( - 'Spending is ', - '8.2% higher', - ' than last week', - ), - _insightRow( - 'Weekend shifts account for ', - '40%', - ' of total spend', - ), - _insightRow( - 'Book 48hrs ahead to save ', - '15%', - ' on average', - ), - ], - ), - ), - const SizedBox(height: 100), - ], - ), - ), - ), - ], - ), - ), - ); - } - - BarChartGroupData _makeGroupData(int x, double y) { - return BarChartGroupData( - x: x, - barRods: [ - BarChartRodData( - toY: y, - color: const Color(0xFF10B981), - width: 16, - borderRadius: const BorderRadius.vertical(top: Radius.circular(4)), - ), - ], - ); - } - - Widget _insightRow(String prefix, String bold, String suffix) { - return Padding( - padding: const EdgeInsets.only(bottom: 8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text('• ', style: TextStyle(color: Color(0xFF065F46))), - Expanded( - child: RichText( - text: TextSpan( - style: const TextStyle( - color: Color(0xFF065F46), - fontSize: 13, - height: 1.4, - ), - children: [ - TextSpan(text: prefix), - TextSpan( - text: bold, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - TextSpan(text: suffix), - ], - ), - ), - ), - ], - ), - ); - } -} - -class _SpendSummaryCard extends StatelessWidget { - final String label; - final String value; - final String badge; - final IconData icon; - final Color color; - final Color badgeBg; - - const _SpendSummaryCard({ - required this.label, - required this.value, - required this.badge, - required this.icon, - required this.color, - required this.badgeBg, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.06), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon(icon, size: 14, color: color), - const SizedBox(width: 8), - Text( - label, - style: const TextStyle(fontSize: 10, color: Color(0xFF64748B)), - ), - ], - ), - const SizedBox(height: 12), - Text( - value, - style: const TextStyle( - fontSize: 22, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - const SizedBox(height: 4), - Container( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - decoration: BoxDecoration( - color: badgeBg, - borderRadius: BorderRadius.circular(4), - ), - child: Text( - badge, - style: TextStyle( - fontSize: 8, - fontWeight: FontWeight.bold, - color: color, - ), - ), - ), - ], - ), - ); - } -} - -class _IndustryRow extends StatelessWidget { - final String name; - final String value; - final double percent; - - const _IndustryRow({ - required this.name, - required this.value, - required this.percent, - }); - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - name, - style: const TextStyle( - fontSize: 13, - fontWeight: FontWeight.w500, - color: Color(0xFF334155), - ), - ), - Text( - value, - style: const TextStyle( - fontSize: 13, - fontWeight: FontWeight.bold, - color: Color(0xFF0F172A), - ), - ), - ], - ), - const SizedBox(height: 8), - Stack( - children: [ - Container( - height: 8, - width: double.infinity, - decoration: BoxDecoration( - color: const Color(0xFFF1F5F9), - borderRadius: BorderRadius.circular(4), - ), - ), - FractionallySizedBox( - widthFactor: percent / 100, - child: Container( - height: 8, - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFF10B981), Color(0xFF059669)], - ), - borderRadius: BorderRadius.circular(4), - ), - ), - ), - ], - ), - const SizedBox(height: 4), - Text( - '$percent% of total', - style: const TextStyle(fontSize: 10, color: Color(0xFF64748B)), - ), - ], - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/verify_worker_attire_screen.dart b/apps/mobile/prototypes/client_mobile_application/lib/screens/client/verify_worker_attire_screen.dart deleted file mode 100644 index 0542cc1b..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/screens/client/verify_worker_attire_screen.dart +++ /dev/null @@ -1,228 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import 'package:go_router/go_router.dart'; - -class VerifyWorkerAttireScreen extends StatefulWidget { - const VerifyWorkerAttireScreen({super.key}); - - @override - State createState() => _VerifyWorkerAttireScreenState(); -} - -class _VerifyWorkerAttireScreenState extends State { - // Mock Data - final List> _staff = [ - { - 'id': '93673c8f-91aa-405d-8647-f1aac29cc191', - 'email': 'worker1@example.com', - 'itemsAttire': [ - {'id': 'non_slip_shoes', 'label': 'Non Slip Shoes', 'verified': false}, - {'id': 'black_pants', 'label': 'Black Pants', 'verified': false}, - ] - }, - { - 'id': '93673c8f-91aa-405d-8647-f1aac29cc192', - 'email': 'worker2@example.com', - 'itemsAttire': [ - {'id': 'white_polo', 'label': 'White Polo', 'verified': true, 'verified_date': '2023-10-25'}, - {'id': 'black_cap', 'label': 'Black Cap', 'verified': false}, - ] - } - ]; - - String _searchQuery = ''; - - void _verifyItem(String workerId, String itemId, bool verified) { - setState(() { - final worker = _staff.firstWhere((w) => w['id'] == workerId); - final item = worker['itemsAttire'].firstWhere((i) => i['id'] == itemId); - item['verified'] = verified; - if (verified) { - item['verified_date'] = DateTime.now().toString().split(' ')[0]; - } else { - item.remove('verified_date'); - } - }); - } - - @override - Widget build(BuildContext context) { - final filteredWorkers = _staff.where((w) => - w['email'].toLowerCase().contains(_searchQuery.toLowerCase()) - ).toList(); - - return Scaffold( - backgroundColor: const Color(0xFFFAFBFC), - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - leading: IconButton( - icon: const Icon(LucideIcons.chevronLeft, color: Color(0xFF64748B)), - onPressed: () => context.pop(), - ), - title: const Text( - 'Verify Worker Attire', - style: TextStyle(color: Color(0xFF121826), fontSize: 18, fontWeight: FontWeight.bold), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(60), - child: Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: TextField( - onChanged: (value) => setState(() => _searchQuery = value), - decoration: InputDecoration( - hintText: 'Search by worker email...', - prefixIcon: const Icon(LucideIcons.search, size: 20), - contentPadding: const EdgeInsets.symmetric(vertical: 0, horizontal: 16), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: const BorderSide(color: Color(0xFFE2E8F0)), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: const BorderSide(color: Color(0xFFE2E8F0)), - ), - filled: true, - fillColor: const Color(0xFFFAFBFC), - ), - ), - ), - ), - ), - body: filteredWorkers.isEmpty - ? const Center( - child: Text( - 'No workers with attire to verify', - style: TextStyle(color: Color(0xFF64748B)), - ), - ) - : ListView.builder( - padding: const EdgeInsets.all(16), - itemCount: filteredWorkers.length, - itemBuilder: (context, index) { - final worker = filteredWorkers[index]; - final items = worker['itemsAttire'] as List; - final pendingItems = items.where((i) => !i['verified']).toList(); - final verifiedItems = items.where((i) => i['verified']).toList(); - - if (pendingItems.isEmpty && verifiedItems.isEmpty) return const SizedBox.shrink(); - - return Card( - margin: const EdgeInsets.only(bottom: 16), - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - side: const BorderSide(color: Color(0xFFE2E8F0)), - ), - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - worker['email'], - style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), - ), - Text( - '${verifiedItems.length} verified · ${pendingItems.length} pending', - style: const TextStyle(color: Color(0xFF64748B), fontSize: 12), - ), - const SizedBox(height: 16), - ...pendingItems.map((item) => Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFFFAFBFC), - borderRadius: BorderRadius.circular(8), - ), - child: Row( - children: [ - Container( - width: 64, - height: 64, - decoration: BoxDecoration( - color: const Color(0xFFE2E8F0), - borderRadius: BorderRadius.circular(4), - ), - child: const Icon(LucideIcons.camera, color: Color(0xFF94A3B8)), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - item['label'], - style: const TextStyle(fontWeight: FontWeight.w500), - ), - const Text( - 'Pending verification', - style: TextStyle(fontSize: 12, color: Color(0xFF64748B)), - ), - ], - ), - ), - Row( - children: [ - InkWell( - onTap: () => _verifyItem(worker['id'], item['id'], false), // Reject acts same for now - child: Container( - width: 36, - height: 36, - decoration: BoxDecoration( - color: const Color(0xFFFEE2E2), - borderRadius: BorderRadius.circular(8), - ), - child: const Icon(LucideIcons.x, size: 16, color: Colors.red), - ), - ), - const SizedBox(width: 8), - InkWell( - onTap: () => _verifyItem(worker['id'], item['id'], true), - child: Container( - width: 36, - height: 36, - decoration: BoxDecoration( - color: const Color(0xFFD1FAE5), - borderRadius: BorderRadius.circular(8), - ), - child: const Icon(LucideIcons.check, size: 16, color: Colors.green), - ), - ), - ], - ), - ], - ), - )), - if (verifiedItems.isNotEmpty) - Theme( - data: Theme.of(context).copyWith(dividerColor: Colors.transparent), - child: ExpansionTile( - title: Text( - '${verifiedItems.length} verified items', - style: const TextStyle(fontSize: 12, color: Color(0xFF64748B)), - ), - children: verifiedItems.map((item) => Padding( - padding: const EdgeInsets.symmetric(vertical: 4), - child: Row( - children: [ - const Icon(LucideIcons.check, size: 12, color: Colors.green), - const SizedBox(width: 8), - Text( - '${item['label']} - ${item['verified_date']}', - style: const TextStyle(fontSize: 12, color: Color(0xFF64748B)), - ), - ], - ), - )).toList(), - ), - ), - ], - ), - ), - ); - }, - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/theme.dart b/apps/mobile/prototypes/client_mobile_application/lib/theme.dart deleted file mode 100644 index 2e5291b1..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/theme.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; - -class AppColors { - static const Color krowBlue = Color(0xFF0A39DF); - static const Color krowYellow = Color(0xFFFFED4A); - static const Color krowCharcoal = Color(0xFF121826); - static const Color krowMuted = Color(0xFF6A7382); - static const Color krowBorder = Color(0xFFE3E6E9); - static const Color krowBackground = Color(0xFFFAFBFC); - - static const Color white = Colors.white; - static const Color black = Colors.black; -} - -class AppTheme { - static ThemeData get lightTheme { - return ThemeData( - useMaterial3: true, - scaffoldBackgroundColor: AppColors.krowBackground, - colorScheme: ColorScheme.fromSeed( - seedColor: AppColors.krowBlue, - primary: AppColors.krowBlue, - secondary: AppColors.krowYellow, - surface: AppColors.white, - background: AppColors.krowBackground, - ), - textTheme: GoogleFonts.instrumentSansTextTheme().apply( - bodyColor: AppColors.krowCharcoal, - displayColor: AppColors.krowCharcoal, - ), - appBarTheme: const AppBarTheme( - backgroundColor: AppColors.krowBackground, - elevation: 0, - iconTheme: IconThemeData(color: AppColors.krowCharcoal), - titleTextStyle: TextStyle( - color: AppColors.krowCharcoal, - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/widgets/scaffold_with_nav_bar.dart b/apps/mobile/prototypes/client_mobile_application/lib/widgets/scaffold_with_nav_bar.dart deleted file mode 100644 index 1d2cba53..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/widgets/scaffold_with_nav_bar.dart +++ /dev/null @@ -1,137 +0,0 @@ -import 'dart:ui'; -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:lucide_icons/lucide_icons.dart'; -import '../theme.dart'; - -class ScaffoldWithNavBar extends StatelessWidget { - const ScaffoldWithNavBar({required this.navigationShell, super.key}); - - final StatefulNavigationShell navigationShell; - - @override - Widget build(BuildContext context) { - return Scaffold( - body: navigationShell, - extendBody: true, - bottomNavigationBar: _buildBottomBar(context), - ); - } - - Widget _buildBottomBar(BuildContext context) { - bool isWorker = false; // This is the Client App - final activeColor = isWorker ? AppColors.krowBlue : AppColors.krowCharcoal; - final inactiveColor = const Color(0xFF8E8E93); - - return Stack( - clipBehavior: Clip.none, - children: [ - Positioned.fill( - child: ClipRect( - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), - child: Container( - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.85), - border: const Border( - top: BorderSide(color: Color.fromRGBO(0, 0, 0, 0.1)), - ), - ), - ), - ), - ), - ), - Container( - padding: EdgeInsets.only( - bottom: MediaQuery.of(context).padding.bottom + 8, - top: 16, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - _buildNavItem( - 0, - LucideIcons.calendar, - 'Coverage', - activeColor, - inactiveColor, - ), - _buildNavItem( - 1, - LucideIcons.dollarSign, - 'Billing', - activeColor, - inactiveColor, - ), - _buildNavItem( - 2, - LucideIcons.building2, - 'Home', - activeColor, - inactiveColor, - ), - _buildNavItem( - 3, - LucideIcons.fileText, - 'Orders', - activeColor, - inactiveColor, - ), - _buildNavItem( - 4, - LucideIcons.barChart3, - 'Reports', - activeColor, - inactiveColor, - ), - ], - ), - ), - ], - ); - } - - Widget _buildNavItem( - int index, - IconData icon, - String label, - Color activeColor, - Color inactiveColor, - ) { - final isSelected = navigationShell.currentIndex == index; - return Expanded( - child: GestureDetector( - onTap: () => _onTap(index), - behavior: HitTestBehavior.opaque, - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Icon( - icon, - color: isSelected ? activeColor : inactiveColor, - size: 24, - ), - const SizedBox(height: 2), - Text( - label, - style: TextStyle( - color: isSelected ? activeColor : inactiveColor, - fontSize: 10, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ), - ); - } - - void _onTap(int index) { - navigationShell.goBranch( - index, - initialLocation: index == navigationShell.currentIndex, - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/lib/widgets/web_mobile_frame.dart b/apps/mobile/prototypes/client_mobile_application/lib/widgets/web_mobile_frame.dart deleted file mode 100644 index 796eb5ba..00000000 --- a/apps/mobile/prototypes/client_mobile_application/lib/widgets/web_mobile_frame.dart +++ /dev/null @@ -1,271 +0,0 @@ -import 'dart:ui'; - -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:google_fonts/google_fonts.dart'; - -/// A wrapper widget that renders the application inside an iPhone 14 Pro Max-like frame -/// specifically for Flutter Web. On other platforms, it simply returns the child. -class WebMobileFrame extends StatelessWidget { - final Widget child; - - const WebMobileFrame({super.key, required this.child}); - - @override - Widget build(BuildContext context) { - if (!kIsWeb) return child; - - return MaterialApp( - debugShowCheckedModeBanner: false, - theme: ThemeData.dark(), - home: _WebFrameContent(child: child), - ); - } -} - -class _WebFrameContent extends StatefulWidget { - final Widget child; - const _WebFrameContent({required this.child}); - - @override - State<_WebFrameContent> createState() => _WebFrameContentState(); -} - -class _WebFrameContentState extends State<_WebFrameContent> { - Offset _cursorPosition = Offset.zero; - bool _isHovering = false; - - @override - Widget build(BuildContext context) { - // iPhone 14 Pro Max-ish dimensions (scaled for frame look) - const double frameWidth = 390 * 1.2; - const double frameHeight = 844 * 1.3; - const double borderRadius = 54.0; - const double borderThickness = 12.0; - - return Scaffold( - backgroundColor: const Color(0xFF121212), - body: MouseRegion( - cursor: SystemMouseCursors.none, - onHover: (event) { - setState(() { - _cursorPosition = event.position; - _isHovering = true; - }); - }, - onExit: (_) => setState(() => _isHovering = false), - child: Stack( - children: [ - // Logo and Title on the left (Web only) - Positioned( - left: 60, - top: 0, - bottom: 0, - child: Center( - child: Opacity( - opacity: 0.5, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset('assets/logo.png', width: 140), - const SizedBox(height: 12), - Text( - 'KROW Client \nApplication', - textAlign: TextAlign.left, - style: GoogleFonts.instrumentSans( - color: Colors.white, - fontSize: 28, - fontWeight: FontWeight.bold, - letterSpacing: -0.5, - ), - ), - const SizedBox(height: 4), - Container( - height: 2, - width: 40, - color: Colors.white.withOpacity(0.3), - ), - ], - ), - ), - ), - ), - - // Frame and Content - Center( - child: LayoutBuilder( - builder: (context, constraints) { - // Scale down if screen is too small - double scaleX = constraints.maxWidth / (frameWidth + 80); - double scaleY = constraints.maxHeight / (frameHeight + 80); - double scale = (scaleX < 1 || scaleY < 1) - ? (scaleX < scaleY ? scaleX : scaleY) - : 1.0; - - return Transform.scale( - scale: scale, - child: Container( - width: frameWidth, - height: frameHeight, - decoration: BoxDecoration( - color: Colors.black, - borderRadius: BorderRadius.circular(borderRadius), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.6), - blurRadius: 40, - spreadRadius: 10, - ), - ], - border: Border.all( - color: const Color(0xFF2C2C2C), - width: borderThickness, - ), - ), - child: ClipRRect( - borderRadius: BorderRadius.circular( - borderRadius - borderThickness, - ), - child: Stack( - children: [ - // The actual app + status bar - Column( - children: [ - // Mock iOS Status Bar - Container( - height: 48, - padding: const EdgeInsets.symmetric( - horizontal: 24, - ), - decoration: const BoxDecoration( - color: Color(0xFFF9F6EE), - border: Border( - bottom: BorderSide( - color: Color(0xFFEEEEEE), - width: 0.5, - ), - ), - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - // Time side - const SizedBox( - width: 80, - child: Text( - '3:12 PM', - textAlign: TextAlign.center, - style: TextStyle( - color: Colors.black54, - fontWeight: FontWeight.w700, - fontSize: 14, - letterSpacing: -0.2, - ), - ), - ), - // Status Icons side - SizedBox( - width: 80, - child: Row( - mainAxisAlignment: - MainAxisAlignment.end, - spacing: 12, - children: [ - const Icon( - FontAwesomeIcons.signal, - size: 12, - color: Colors.black54, - ), - const Icon( - FontAwesomeIcons.wifi, - size: 12, - color: Colors.black54, - ), - const Icon( - FontAwesomeIcons.batteryFull, - size: 12, - color: Colors.black54, - ), - ], - ), - ), - ], - ), - ), - // The main app content content - Expanded(child: widget.child), - ], - ), - - // Notch / Dynamic Island - Align( - alignment: Alignment.topCenter, - child: Padding( - padding: const EdgeInsets.only(top: 8), - child: Container( - width: 125, - height: 35, - decoration: BoxDecoration( - color: Colors.black, - borderRadius: BorderRadius.circular(20), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Container( - width: 8, - height: 8, - margin: const EdgeInsets.only( - right: 20, - ), - decoration: const BoxDecoration( - color: Color(0xFF0F0F0F), - shape: BoxShape.circle, - ), - ), - ], - ), - ), - ), - ), - ], - ), - ), - ), - ); - }, - ), - ), - - // Custom Circle Cursor - if (_isHovering) - Positioned( - left: _cursorPosition.dx - 20, - top: _cursorPosition.dy - 20, - child: IgnorePointer( - child: ClipRRect( - borderRadius: BorderRadius.circular(25), - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 2.5, sigmaY: 2.5), - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.grey.withAlpha(50), - shape: BoxShape.circle, - border: Border.all(color: Colors.white, width: 1.5), - ), - ), - ), - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/linux/.gitignore b/apps/mobile/prototypes/client_mobile_application/linux/.gitignore deleted file mode 100644 index d3896c98..00000000 --- a/apps/mobile/prototypes/client_mobile_application/linux/.gitignore +++ /dev/null @@ -1 +0,0 @@ -flutter/ephemeral diff --git a/apps/mobile/prototypes/client_mobile_application/linux/CMakeLists.txt b/apps/mobile/prototypes/client_mobile_application/linux/CMakeLists.txt deleted file mode 100644 index b5ca6f2c..00000000 --- a/apps/mobile/prototypes/client_mobile_application/linux/CMakeLists.txt +++ /dev/null @@ -1,128 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.13) -project(runner LANGUAGES CXX) - -# The name of the executable created for the application. Change this to change -# the on-disk name of your application. -set(BINARY_NAME "client_app_mvp") -# The unique GTK application identifier for this application. See: -# https://wiki.gnome.org/HowDoI/ChooseApplicationID -set(APPLICATION_ID "com.example.client_app_mvp") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(SET CMP0063 NEW) - -# Load bundled libraries from the lib/ directory relative to the binary. -set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") - -# Root filesystem for cross-building. -if(FLUTTER_TARGET_PLATFORM_SYSROOT) - set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) - set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -endif() - -# Define build configuration options. -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") -endif() - -# Compilation settings that should be applied to most targets. -# -# Be cautious about adding new options here, as plugins use this function by -# default. In most cases, you should add new options to specific targets instead -# of modifying this function. -function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror) - target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") - target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") -endfunction() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# System-level dependencies. -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) - -# Application build; see runner/CMakeLists.txt. -add_subdirectory("runner") - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble) - -# Only the install-generated bundle's copy of the executable will launch -# correctly, since the resources must in the right relative locations. To avoid -# people trying to run the unbundled copy, put it in a subdirectory instead of -# the default top-level location. -set_target_properties(${BINARY_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" -) - - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# By default, "installing" just makes a relocatable bundle in the build -# directory. -set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() - -# Start with a clean build bundle directory every time. -install(CODE " - file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") - " COMPONENT Runtime) - -set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") -set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") - -install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) - install(FILES "${bundled_library}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endforeach(bundled_library) - -# Copy the native assets provided by the build.dart from all packages. -set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") -install(DIRECTORY "${NATIVE_ASSETS_DIR}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -# Fully re-copy the assets directory on each build to avoid having stale files -# from a previous install. -set(FLUTTER_ASSET_DIR_NAME "flutter_assets") -install(CODE " - file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") - " COMPONENT Runtime) -install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) - -# Install the AOT library on non-Debug builds only. -if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") - install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() diff --git a/apps/mobile/prototypes/client_mobile_application/linux/flutter/CMakeLists.txt b/apps/mobile/prototypes/client_mobile_application/linux/flutter/CMakeLists.txt deleted file mode 100644 index d5bd0164..00000000 --- a/apps/mobile/prototypes/client_mobile_application/linux/flutter/CMakeLists.txt +++ /dev/null @@ -1,88 +0,0 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.10) - -set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") - -# Configuration provided via flutter tool. -include(${EPHEMERAL_DIR}/generated_config.cmake) - -# TODO: Move the rest of this into files in ephemeral. See -# https://github.com/flutter/flutter/issues/57146. - -# Serves the same purpose as list(TRANSFORM ... PREPEND ...), -# which isn't available in 3.10. -function(list_prepend LIST_NAME PREFIX) - set(NEW_LIST "") - foreach(element ${${LIST_NAME}}) - list(APPEND NEW_LIST "${PREFIX}${element}") - endforeach(element) - set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) -endfunction() - -# === Flutter Library === -# System-level dependencies. -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) -pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) -pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) - -set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") - -# Published to parent scope for install step. -set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) -set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) -set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) -set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) - -list(APPEND FLUTTER_LIBRARY_HEADERS - "fl_basic_message_channel.h" - "fl_binary_codec.h" - "fl_binary_messenger.h" - "fl_dart_project.h" - "fl_engine.h" - "fl_json_message_codec.h" - "fl_json_method_codec.h" - "fl_message_codec.h" - "fl_method_call.h" - "fl_method_channel.h" - "fl_method_codec.h" - "fl_method_response.h" - "fl_plugin_registrar.h" - "fl_plugin_registry.h" - "fl_standard_message_codec.h" - "fl_standard_method_codec.h" - "fl_string_codec.h" - "fl_value.h" - "fl_view.h" - "flutter_linux.h" -) -list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") -add_library(flutter INTERFACE) -target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" -) -target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") -target_link_libraries(flutter INTERFACE - PkgConfig::GTK - PkgConfig::GLIB - PkgConfig::GIO -) -add_dependencies(flutter flutter_assemble) - -# === Flutter tool backend === -# _phony_ is a non-existent file to force this command to run every time, -# since currently there's no way to get a full input/output list from the -# flutter tool. -add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CMAKE_CURRENT_BINARY_DIR}/_phony_ - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} - VERBATIM -) -add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} -) diff --git a/apps/mobile/prototypes/client_mobile_application/linux/flutter/generated_plugin_registrant.cc b/apps/mobile/prototypes/client_mobile_application/linux/flutter/generated_plugin_registrant.cc deleted file mode 100644 index f6f23bfe..00000000 --- a/apps/mobile/prototypes/client_mobile_application/linux/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include - -void fl_register_plugins(FlPluginRegistry* registry) { - g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); - url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); -} diff --git a/apps/mobile/prototypes/client_mobile_application/linux/flutter/generated_plugin_registrant.h b/apps/mobile/prototypes/client_mobile_application/linux/flutter/generated_plugin_registrant.h deleted file mode 100644 index e0f0a47b..00000000 --- a/apps/mobile/prototypes/client_mobile_application/linux/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void fl_register_plugins(FlPluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/apps/mobile/prototypes/client_mobile_application/linux/flutter/generated_plugins.cmake b/apps/mobile/prototypes/client_mobile_application/linux/flutter/generated_plugins.cmake deleted file mode 100644 index f16b4c34..00000000 --- a/apps/mobile/prototypes/client_mobile_application/linux/flutter/generated_plugins.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - url_launcher_linux -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/apps/mobile/prototypes/client_mobile_application/linux/runner/CMakeLists.txt b/apps/mobile/prototypes/client_mobile_application/linux/runner/CMakeLists.txt deleted file mode 100644 index e97dabc7..00000000 --- a/apps/mobile/prototypes/client_mobile_application/linux/runner/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -cmake_minimum_required(VERSION 3.13) -project(runner LANGUAGES CXX) - -# Define the application target. To change its name, change BINARY_NAME in the -# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer -# work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add preprocessor definitions for the application ID. -add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") - -# Add dependency libraries. Add any application-specific dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter) -target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) - -target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/apps/mobile/prototypes/client_mobile_application/linux/runner/main.cc b/apps/mobile/prototypes/client_mobile_application/linux/runner/main.cc deleted file mode 100644 index e7c5c543..00000000 --- a/apps/mobile/prototypes/client_mobile_application/linux/runner/main.cc +++ /dev/null @@ -1,6 +0,0 @@ -#include "my_application.h" - -int main(int argc, char** argv) { - g_autoptr(MyApplication) app = my_application_new(); - return g_application_run(G_APPLICATION(app), argc, argv); -} diff --git a/apps/mobile/prototypes/client_mobile_application/linux/runner/my_application.cc b/apps/mobile/prototypes/client_mobile_application/linux/runner/my_application.cc deleted file mode 100644 index bcbdacaf..00000000 --- a/apps/mobile/prototypes/client_mobile_application/linux/runner/my_application.cc +++ /dev/null @@ -1,148 +0,0 @@ -#include "my_application.h" - -#include -#ifdef GDK_WINDOWING_X11 -#include -#endif - -#include "flutter/generated_plugin_registrant.h" - -struct _MyApplication { - GtkApplication parent_instance; - char** dart_entrypoint_arguments; -}; - -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) - -// Called when first Flutter frame received. -static void first_frame_cb(MyApplication* self, FlView* view) { - gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view))); -} - -// Implements GApplication::activate. -static void my_application_activate(GApplication* application) { - MyApplication* self = MY_APPLICATION(application); - GtkWindow* window = - GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - - // Use a header bar when running in GNOME as this is the common style used - // by applications and is the setup most users will be using (e.g. Ubuntu - // desktop). - // If running on X and not using GNOME then just use a traditional title bar - // in case the window manager does more exotic layout, e.g. tiling. - // If running on Wayland assume the header bar will work (may need changing - // if future cases occur). - gboolean use_header_bar = TRUE; -#ifdef GDK_WINDOWING_X11 - GdkScreen* screen = gtk_window_get_screen(window); - if (GDK_IS_X11_SCREEN(screen)) { - const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); - if (g_strcmp0(wm_name, "GNOME Shell") != 0) { - use_header_bar = FALSE; - } - } -#endif - if (use_header_bar) { - GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_widget_show(GTK_WIDGET(header_bar)); - gtk_header_bar_set_title(header_bar, "client_app_mvp"); - gtk_header_bar_set_show_close_button(header_bar, TRUE); - gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); - } else { - gtk_window_set_title(window, "client_app_mvp"); - } - - gtk_window_set_default_size(window, 1280, 720); - - g_autoptr(FlDartProject) project = fl_dart_project_new(); - fl_dart_project_set_dart_entrypoint_arguments( - project, self->dart_entrypoint_arguments); - - FlView* view = fl_view_new(project); - GdkRGBA background_color; - // Background defaults to black, override it here if necessary, e.g. #00000000 - // for transparent. - gdk_rgba_parse(&background_color, "#000000"); - fl_view_set_background_color(view, &background_color); - gtk_widget_show(GTK_WIDGET(view)); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); - - // Show the window when Flutter renders. - // Requires the view to be realized so we can start rendering. - g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), - self); - gtk_widget_realize(GTK_WIDGET(view)); - - fl_register_plugins(FL_PLUGIN_REGISTRY(view)); - - gtk_widget_grab_focus(GTK_WIDGET(view)); -} - -// Implements GApplication::local_command_line. -static gboolean my_application_local_command_line(GApplication* application, - gchar*** arguments, - int* exit_status) { - MyApplication* self = MY_APPLICATION(application); - // Strip out the first argument as it is the binary name. - self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); - - g_autoptr(GError) error = nullptr; - if (!g_application_register(application, nullptr, &error)) { - g_warning("Failed to register: %s", error->message); - *exit_status = 1; - return TRUE; - } - - g_application_activate(application); - *exit_status = 0; - - return TRUE; -} - -// Implements GApplication::startup. -static void my_application_startup(GApplication* application) { - // MyApplication* self = MY_APPLICATION(object); - - // Perform any actions required at application startup. - - G_APPLICATION_CLASS(my_application_parent_class)->startup(application); -} - -// Implements GApplication::shutdown. -static void my_application_shutdown(GApplication* application) { - // MyApplication* self = MY_APPLICATION(object); - - // Perform any actions required at application shutdown. - - G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); -} - -// Implements GObject::dispose. -static void my_application_dispose(GObject* object) { - MyApplication* self = MY_APPLICATION(object); - g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); - G_OBJECT_CLASS(my_application_parent_class)->dispose(object); -} - -static void my_application_class_init(MyApplicationClass* klass) { - G_APPLICATION_CLASS(klass)->activate = my_application_activate; - G_APPLICATION_CLASS(klass)->local_command_line = - my_application_local_command_line; - G_APPLICATION_CLASS(klass)->startup = my_application_startup; - G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; - G_OBJECT_CLASS(klass)->dispose = my_application_dispose; -} - -static void my_application_init(MyApplication* self) {} - -MyApplication* my_application_new() { - // Set the program name to the application ID, which helps various systems - // like GTK and desktop environments map this running application to its - // corresponding .desktop file. This ensures better integration by allowing - // the application to be recognized beyond its binary name. - g_set_prgname(APPLICATION_ID); - - return MY_APPLICATION(g_object_new(my_application_get_type(), - "application-id", APPLICATION_ID, "flags", - G_APPLICATION_NON_UNIQUE, nullptr)); -} diff --git a/apps/mobile/prototypes/client_mobile_application/linux/runner/my_application.h b/apps/mobile/prototypes/client_mobile_application/linux/runner/my_application.h deleted file mode 100644 index db16367a..00000000 --- a/apps/mobile/prototypes/client_mobile_application/linux/runner/my_application.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef FLUTTER_MY_APPLICATION_H_ -#define FLUTTER_MY_APPLICATION_H_ - -#include - -G_DECLARE_FINAL_TYPE(MyApplication, - my_application, - MY, - APPLICATION, - GtkApplication) - -/** - * my_application_new: - * - * Creates a new Flutter-based application. - * - * Returns: a new #MyApplication. - */ -MyApplication* my_application_new(); - -#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/apps/mobile/prototypes/client_mobile_application/macos/.gitignore b/apps/mobile/prototypes/client_mobile_application/macos/.gitignore deleted file mode 100644 index 746adbb6..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Flutter-related -**/Flutter/ephemeral/ -**/Pods/ - -# Xcode-related -**/dgph -**/xcuserdata/ diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Flutter/Flutter-Debug.xcconfig b/apps/mobile/prototypes/client_mobile_application/macos/Flutter/Flutter-Debug.xcconfig deleted file mode 100644 index 4b81f9b2..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Flutter/Flutter-Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Flutter/Flutter-Release.xcconfig b/apps/mobile/prototypes/client_mobile_application/macos/Flutter/Flutter-Release.xcconfig deleted file mode 100644 index 5caa9d15..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Flutter/Flutter-Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Flutter/GeneratedPluginRegistrant.swift b/apps/mobile/prototypes/client_mobile_application/macos/Flutter/GeneratedPluginRegistrant.swift deleted file mode 100644 index 4f908931..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Flutter/GeneratedPluginRegistrant.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// Generated file. Do not edit. -// - -import FlutterMacOS -import Foundation - -import firebase_core -import path_provider_foundation -import url_launcher_macos - -func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) - UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) -} diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Podfile b/apps/mobile/prototypes/client_mobile_application/macos/Podfile deleted file mode 100644 index ff5ddb3b..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Podfile +++ /dev/null @@ -1,42 +0,0 @@ -platform :osx, '10.15' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_macos_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_macos_build_settings(target) - end -end diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcodeproj/project.pbxproj b/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 7a9ccf1c..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,705 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXAggregateTarget section */ - 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; - buildPhases = ( - 33CC111E2044C6BF0003C045 /* ShellScript */, - ); - dependencies = ( - ); - name = "Flutter Assemble"; - productName = FLX; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC10EC2044A3C60003C045; - remoteInfo = Runner; - }; - 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC111A2044C6BA0003C045; - remoteInfo = FLX; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 33CC110E2044A8840003C045 /* Bundle Framework */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Bundle Framework"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* client_app_mvp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "client_app_mvp.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; - 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; - 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; - 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; - 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 331C80D2294CF70F00263BE5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EA2044A3C60003C045 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C80D6294CF71000263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C80D7294CF71000263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 33BA886A226E78AF003329D5 /* Configs */ = { - isa = PBXGroup; - children = ( - 33E5194F232828860026EE4D /* AppInfo.xcconfig */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, - ); - path = Configs; - sourceTree = ""; - }; - 33CC10E42044A3C60003C045 = { - isa = PBXGroup; - children = ( - 33FAB671232836740065AC1E /* Runner */, - 33CEB47122A05771004F2AC0 /* Flutter */, - 331C80D6294CF71000263BE5 /* RunnerTests */, - 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, - ); - sourceTree = ""; - }; - 33CC10EE2044A3C60003C045 /* Products */ = { - isa = PBXGroup; - children = ( - 33CC10ED2044A3C60003C045 /* client_app_mvp.app */, - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 33CC11242044D66E0003C045 /* Resources */ = { - isa = PBXGroup; - children = ( - 33CC10F22044A3C60003C045 /* Assets.xcassets */, - 33CC10F42044A3C60003C045 /* MainMenu.xib */, - 33CC10F72044A3C60003C045 /* Info.plist */, - ); - name = Resources; - path = ..; - sourceTree = ""; - }; - 33CEB47122A05771004F2AC0 /* Flutter */ = { - isa = PBXGroup; - children = ( - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, - ); - path = Flutter; - sourceTree = ""; - }; - 33FAB671232836740065AC1E /* Runner */ = { - isa = PBXGroup; - children = ( - 33CC10F02044A3C60003C045 /* AppDelegate.swift */, - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, - 33E51913231747F40026EE4D /* DebugProfile.entitlements */, - 33E51914231749380026EE4D /* Release.entitlements */, - 33CC11242044D66E0003C045 /* Resources */, - 33BA886A226E78AF003329D5 /* Configs */, - ); - path = Runner; - sourceTree = ""; - }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { - isa = PBXGroup; - children = ( - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C80D4294CF70F00263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 331C80D1294CF70F00263BE5 /* Sources */, - 331C80D2294CF70F00263BE5 /* Frameworks */, - 331C80D3294CF70F00263BE5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 331C80DA294CF71000263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 33CC10EC2044A3C60003C045 /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 33CC10E92044A3C60003C045 /* Sources */, - 33CC10EA2044A3C60003C045 /* Frameworks */, - 33CC10EB2044A3C60003C045 /* Resources */, - 33CC110E2044A8840003C045 /* Bundle Framework */, - 3399D490228B24CF009A79C7 /* ShellScript */, - ); - buildRules = ( - ); - dependencies = ( - 33CC11202044C79F0003C045 /* PBXTargetDependency */, - ); - name = Runner; - productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* client_app_mvp.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 33CC10E52044A3C60003C045 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C80D4294CF70F00263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 33CC10EC2044A3C60003C045; - }; - 33CC10EC2044A3C60003C045 = { - CreatedOnToolsVersion = 9.2; - LastSwiftMigration = 1100; - ProvisioningStyle = Automatic; - SystemCapabilities = { - com.apple.Sandbox = { - enabled = 1; - }; - }; - }; - 33CC111A2044C6BA0003C045 = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Manual; - }; - }; - }; - buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 33CC10E42044A3C60003C045; - productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 33CC10EC2044A3C60003C045 /* Runner */, - 331C80D4294CF70F00263BE5 /* RunnerTests */, - 33CC111A2044C6BA0003C045 /* Flutter Assemble */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C80D3294CF70F00263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EB2044A3C60003C045 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3399D490228B24CF009A79C7 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; - }; - 33CC111E2044C6BF0003C045 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - Flutter/ephemeral/FlutterInputs.xcfilelist, - ); - inputPaths = ( - Flutter/ephemeral/tripwire, - ); - outputFileListPaths = ( - Flutter/ephemeral/FlutterOutputs.xcfilelist, - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C80D1294CF70F00263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10E92044A3C60003C045 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC10EC2044A3C60003C045 /* Runner */; - targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; - }; - 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; - targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 33CC10F52044A3C60003C045 /* Base */, - ); - name = MainMenu.xib; - path = Runner; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 331C80DB294CF71000263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.clientAppMvp.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/client_app_mvp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/client_app_mvp"; - }; - name = Debug; - }; - 331C80DC294CF71000263BE5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.clientAppMvp.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/client_app_mvp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/client_app_mvp"; - }; - name = Release; - }; - 331C80DD294CF71000263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.clientAppMvp.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/client_app_mvp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/client_app_mvp"; - }; - name = Profile; - }; - 338D0CE9231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Profile; - }; - 338D0CEA231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; - }; - name = Profile; - }; - 338D0CEB231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Profile; - }; - 33CC10F92044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 33CC10FA2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Release; - }; - 33CC10FC2044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 33CC10FD2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 33CC111C2044C6BA0003C045 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 33CC111D2044C6BA0003C045 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C80DB294CF71000263BE5 /* Debug */, - 331C80DC294CF71000263BE5 /* Release */, - 331C80DD294CF71000263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10F92044A3C60003C045 /* Debug */, - 33CC10FA2044A3C60003C045 /* Release */, - 338D0CE9231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10FC2044A3C60003C045 /* Debug */, - 33CC10FD2044A3C60003C045 /* Release */, - 338D0CEA231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC111C2044C6BA0003C045 /* Debug */, - 33CC111D2044C6BA0003C045 /* Release */, - 338D0CEB231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 33CC10E52044A3C60003C045 /* Project object */; -} diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index 732dbe0c..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcworkspace/contents.xcworkspacedata b/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 1d526a16..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/AppDelegate.swift b/apps/mobile/prototypes/client_mobile_application/macos/Runner/AppDelegate.swift deleted file mode 100644 index b3c17614..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Cocoa -import FlutterMacOS - -@main -class AppDelegate: FlutterAppDelegate { - override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { - return true - } - - override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { - return true - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a2ec33f1..00000000 --- a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "images" : [ - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" - }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png deleted file mode 100644 index 82b6f9d9a33e198f5747104729e1fcef999772a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102994 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ⅅ8MglG&ER{i5lN315cO?EdHNLrg? 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 z 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 Pe7HEdAEg|=c=LY&YVNkY diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png deleted file mode 100644 index 13b35eba55c6dabc3aac36f33d859266c18fa0d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5680 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 diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png deleted file mode 100644 index 0a3f5fa40fb3d1e0710331a48de5d256da3f275d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 520 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 diff --git a/apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/apps/mobile/prototypes/client_mobile_application/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png deleted file mode 100644 index 2f1632cfddf3d9dade342351e627a0a75609fb46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2218 zcmV;b2vzrqP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91K%fHv1ONa40RR91KmY&$07g+lumAuE6iGxuRCodHTWf3-RTMruyW6Fu zQYeUM04eX6D5c0FCjKKPrco1(K`<0SL=crI{PC3-^hZU0kQie$gh-5!7z6SH6Q0J% zqot*`H1q{R5fHFYS}dje@;kG=v$L0(yY0?wY2%*c?A&{2?!D*x?m71{of2gv!$5|C z3>qG_BW}7K_yUcT3A5C6QD<+{aq?x;MAUyAiJn#Jv8_zZtQ{P zTRzbL3U9!qVuZzS$xKU10KiW~Bgdcv1-!uAhQxf3a7q+dU6lj?yoO4Lq4TUN4}h{N z*fIM=SS8|C2$(T>w$`t@3Tka!(r!7W`x z-isCVgQD^mG-MJ;XtJuK3V{Vy72GQ83KRWsHU?e*wrhKk=ApIYeDqLi;JI1e zuvv}5^Dc=k7F7?nm3nIw$NVmU-+R>> zyqOR$-2SDpJ}Pt;^RkJytDVXNTsu|mI1`~G7yw`EJR?VkGfNdqK9^^8P`JdtTV&tX4CNcV4 z&N06nZa??Fw1AgQOUSE2AmPE@WO(Fvo`%m`cDgiv(fAeRA%3AGXUbsGw{7Q`cY;1BI#ac3iN$$Hw z0LT0;xc%=q)me?Y*$xI@GRAw?+}>=9D+KTk??-HJ4=A>`V&vKFS75@MKdSF1JTq{S zc1!^8?YA|t+uKigaq!sT;Z!&0F2=k7F0PIU;F$leJLaw2UI6FL^w}OG&!;+b%ya1c z1n+6-inU<0VM-Y_s5iTElq)ThyF?StVcebpGI znw#+zLx2@ah{$_2jn+@}(zJZ{+}_N9BM;z)0yr|gF-4=Iyu@hI*Lk=-A8f#bAzc9f z`Kd6K--x@t04swJVC3JK1cHY-Hq+=|PN-VO;?^_C#;coU6TDP7Bt`;{JTG;!+jj(` zw5cLQ-(Cz-Tlb`A^w7|R56Ce;Wmr0)$KWOUZ6ai0PhzPeHwdl0H(etP zUV`va_i0s-4#DkNM8lUlqI7>YQLf)(lz9Q3Uw`)nc(z3{m5ZE77Ul$V%m)E}3&8L0 z-XaU|eB~Is08eORPk;=<>!1w)Kf}FOVS2l&9~A+@R#koFJ$Czd%Y(ENTV&A~U(IPI z;UY+gf+&6ioZ=roly<0Yst8ck>(M=S?B-ys3mLdM&)ex!hbt+ol|T6CTS+Sc0jv(& z7ijdvFwBq;0a{%3GGwkDKTeG`b+lyj0jjS1OMkYnepCdoosNY`*zmBIo*981BU%%U z@~$z0V`OVtIbEx5pa|Tct|Lg#ZQf5OYMUMRD>Wdxm5SAqV2}3!ceE-M2 z@O~lQ0OiKQp}o9I;?uxCgYVV?FH|?Riri*U$Zi_`V2eiA>l zdSm6;SEm6#T+SpcE8Ro_f2AwxzI z44hfe^WE3!h@W3RDyA_H440cpmYkv*)6m1XazTqw%=E5Xv7^@^^T7Q2wxr+Z2kVYr - - - - - - - - - - - - - - - - - - - - - -