From cfedff5a5ce196b37b1b1062075c191369d0279c Mon Sep 17 00:00:00 2001 From: Miguel Beltran Date: Tue, 9 Jul 2024 15:05:47 +0200 Subject: [PATCH] Create compass-app first feature (#2342) As part of the work for the compass-app / architecture examples This PR is considerably large, so apologies for that, but as it contains the first feature there is a lot of set up work involved. Could be easier to review by opening the project on the IDE. **Merge to `compass-app` not `main`** cc. @ericwindmill ### Details #### Folder structure The project follows this folder structure: - `lib/config/`: Put here any configuration files. - `lib/config/dependencies.dart`: Configures the dependency tree (i.e. Provider) - `lib/data/models/`: Data classes - `lib/data/repositories/`: Data repositories - `lib/data/services/`: Data services (e.g. network API client) - `lib/routing`: Everything related to navigation (could be moved to `common`) - `lib/ui/core/themes`: several theming classes are here: colors, text styles and the app theme. - `lib/ui/core/ui`: widget components to use across the app - `lib/ui//view_models`: ViewModels for the feature. - `lib/ui//widgets`: Widgets for the feature. Unit tests also follow the same structure. #### State Management Most importantly, the project uses MVVM approach using `ChangeNotifier` with the help of Provider. This could be implemented without Provider or using any other way to inject the VM into the UI classes. #### Architecture approach - Data follows a unidirectional flow from Repository -> Usecase -> ViewModel -> Widgets -> User. - The provided data Repository is using local data from the `assets` folder, an abstract class is provided to hide this implementation detail to the Usecase, and also to allow multiple implementations in the future. ### Screenshots ![image](https://github.com/flutter/samples/assets/2494376/64c08c73-1f2c-4edd-82f6-3c9065f5995f) ### Extra notes: - Moved the app code to the `app` folder. We need to create a `server` project eventually. ### TODO: - Integrate a logging framework instead of using `print()`. - Do proper error handling. - Improve image loading and caching. - Complete tests with edge-cases and errors. - Better Desktop UI. ## Pre-launch Checklist - [x] I read the [Flutter Style Guide] _recently_, and have followed its advice. - [x] I signed the [CLA]. - [x] I read the [Contributors Guide]. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-devrel channel on [Discord]. [Flutter Style Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md [CLA]: https://cla.developers.google.com/ [Discord]: https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md [Contributors Guide]: https://github.com/flutter/samples/blob/main/CONTRIBUTING.md --- compass_app/analysis_options.yaml | 1 - compass_app/{ => app}/.gitignore | 0 compass_app/{ => app}/.metadata | 0 compass_app/{ => app}/README.md | 0 compass_app/app/analysis_options.yaml | 5 + compass_app/{ => app}/android/.gitignore | 0 .../{ => app}/android/app/build.gradle | 0 .../android/app/src/debug/AndroidManifest.xml | 0 .../android/app/src/main/AndroidManifest.xml | 0 .../com/example/compass_app/MainActivity.kt | 0 .../res/drawable-v21/launch_background.xml | 0 .../main/res/drawable/launch_background.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin .../app/src/main/res/values-night/styles.xml | 0 .../app/src/main/res/values/styles.xml | 0 .../app/src/profile/AndroidManifest.xml | 0 compass_app/{ => app}/android/build.gradle | 0 .../{ => app}/android/gradle.properties | 0 .../gradle/wrapper/gradle-wrapper.properties | 0 compass_app/{ => app}/android/settings.gradle | 0 compass_app/app/assets/destinations.json | 1235 +++++++++++++++++ compass_app/app/devtools_options.yaml | 3 + compass_app/{ => app}/ios/.gitignore | 0 .../ios/Flutter/AppFrameworkInfo.plist | 0 .../{ => app}/ios/Flutter/Debug.xcconfig | 0 .../{ => app}/ios/Flutter/Release.xcconfig | 0 .../ios/Runner.xcodeproj/project.pbxproj | 0 .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/WorkspaceSettings.xcsettings | 0 .../xcshareddata/xcschemes/Runner.xcscheme | 0 .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/WorkspaceSettings.xcsettings | 0 .../{ => app}/ios/Runner/AppDelegate.swift | 0 .../AppIcon.appiconset/Contents.json | 0 .../Icon-App-1024x1024@1x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin .../Icon-App-83.5x83.5@2x.png | Bin .../LaunchImage.imageset/Contents.json | 0 .../LaunchImage.imageset/LaunchImage.png | Bin .../LaunchImage.imageset/LaunchImage@2x.png | Bin .../LaunchImage.imageset/LaunchImage@3x.png | Bin .../LaunchImage.imageset/README.md | 0 .../Runner/Base.lproj/LaunchScreen.storyboard | 0 .../ios/Runner/Base.lproj/Main.storyboard | 0 compass_app/{ => app}/ios/Runner/Info.plist | 0 .../ios/Runner/Runner-Bridging-Header.h | 0 .../ios/RunnerTests/RunnerTests.swift | 0 compass_app/app/lib/config/dependencies.dart | 14 + .../app/lib/data/models/destination.dart | 50 + .../destination/destination_repository.dart | 8 + .../destination_repository_local.dart | 35 + compass_app/app/lib/data/services/placeholder | 0 compass_app/app/lib/main.dart | 30 + compass_app/app/lib/routing/router.dart | 21 + .../app/lib/ui/core/themes/colors.dart | 36 + .../app/lib/ui/core/themes/text_styles.dart | 24 + compass_app/app/lib/ui/core/themes/theme.dart | 27 + compass_app/app/lib/ui/core/ui/tag_chip.dart | 127 ++ .../view_models/results_viewmodel.dart | 65 + .../lib/ui/results/widgets/result_card.dart | 57 + .../ui/results/widgets/results_screen.dart | 105 ++ compass_app/app/lib/utils/result.dart | 50 + compass_app/{ => app}/linux/.gitignore | 0 compass_app/{ => app}/linux/CMakeLists.txt | 0 .../{ => app}/linux/flutter/CMakeLists.txt | 0 .../flutter/generated_plugin_registrant.cc | 0 .../flutter/generated_plugin_registrant.h | 0 .../linux/flutter/generated_plugins.cmake | 0 compass_app/{ => app}/linux/main.cc | 0 compass_app/{ => app}/linux/my_application.cc | 0 compass_app/{ => app}/linux/my_application.h | 0 compass_app/{ => app}/macos/.gitignore | 0 .../macos/Flutter/Flutter-Debug.xcconfig | 0 .../macos/Flutter/Flutter-Release.xcconfig | 0 .../Flutter/GeneratedPluginRegistrant.swift | 14 + .../macos/Runner.xcodeproj/project.pbxproj | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/xcschemes/Runner.xcscheme | 0 .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../{ => app}/macos/Runner/AppDelegate.swift | 0 .../AppIcon.appiconset/Contents.json | 0 .../AppIcon.appiconset/app_icon_1024.png | Bin .../AppIcon.appiconset/app_icon_128.png | Bin .../AppIcon.appiconset/app_icon_16.png | Bin .../AppIcon.appiconset/app_icon_256.png | Bin .../AppIcon.appiconset/app_icon_32.png | Bin .../AppIcon.appiconset/app_icon_512.png | Bin .../AppIcon.appiconset/app_icon_64.png | Bin .../macos/Runner/Base.lproj/MainMenu.xib | 0 .../macos/Runner/Configs/AppInfo.xcconfig | 0 .../macos/Runner/Configs/Debug.xcconfig | 0 .../macos/Runner/Configs/Release.xcconfig | 0 .../macos/Runner/Configs/Warnings.xcconfig | 0 .../macos/Runner/DebugProfile.entitlements | 2 + compass_app/{ => app}/macos/Runner/Info.plist | 0 .../macos/Runner/MainFlutterWindow.swift | 0 .../macos/Runner/Release.entitlements | 0 .../macos/RunnerTests/RunnerTests.swift | 0 compass_app/{ => app}/pubspec.yaml | 9 +- .../destination_repository_local_test.dart | 26 + .../results/fake_destination_repository.dart | 34 + .../test/ui/results/results_screen_test.dart | 46 + .../ui/results/results_viewmodel_test.dart | 19 + compass_app/{ => app}/web/favicon.png | Bin compass_app/{ => app}/web/icons/Icon-192.png | Bin compass_app/{ => app}/web/icons/Icon-512.png | Bin .../{ => app}/web/icons/Icon-maskable-192.png | Bin .../{ => app}/web/icons/Icon-maskable-512.png | Bin compass_app/{ => app}/web/index.html | 0 compass_app/{ => app}/web/manifest.json | 0 compass_app/{ => app}/windows/.gitignore | 0 compass_app/{ => app}/windows/CMakeLists.txt | 0 .../{ => app}/windows/flutter/CMakeLists.txt | 0 .../flutter/generated_plugin_registrant.cc | 0 .../flutter/generated_plugin_registrant.h | 0 .../windows/flutter/generated_plugins.cmake | 0 .../{ => app}/windows/runner/CMakeLists.txt | 0 .../{ => app}/windows/runner/Runner.rc | 0 .../windows/runner/flutter_window.cpp | 0 .../{ => app}/windows/runner/flutter_window.h | 0 compass_app/{ => app}/windows/runner/main.cpp | 0 .../{ => app}/windows/runner/resource.h | 0 .../windows/runner/resources/app_icon.ico | Bin .../windows/runner/runner.exe.manifest | 0 .../{ => app}/windows/runner/utils.cpp | 0 compass_app/{ => app}/windows/runner/utils.h | 0 .../{ => app}/windows/runner/win32_window.cpp | 0 .../{ => app}/windows/runner/win32_window.h | 0 compass_app/lib/main.dart | 20 - .../Flutter/GeneratedPluginRegistrant.swift | 10 - 149 files changed, 2041 insertions(+), 32 deletions(-) delete mode 100644 compass_app/analysis_options.yaml rename compass_app/{ => app}/.gitignore (100%) rename compass_app/{ => app}/.metadata (100%) rename compass_app/{ => app}/README.md (100%) create mode 100644 compass_app/app/analysis_options.yaml rename compass_app/{ => app}/android/.gitignore (100%) rename compass_app/{ => app}/android/app/build.gradle (100%) rename compass_app/{ => app}/android/app/src/debug/AndroidManifest.xml (100%) rename compass_app/{ => app}/android/app/src/main/AndroidManifest.xml (100%) rename compass_app/{ => app}/android/app/src/main/kotlin/com/example/compass_app/MainActivity.kt (100%) rename compass_app/{ => app}/android/app/src/main/res/drawable-v21/launch_background.xml (100%) rename compass_app/{ => app}/android/app/src/main/res/drawable/launch_background.xml (100%) rename compass_app/{ => app}/android/app/src/main/res/mipmap-hdpi/ic_launcher.png (100%) rename compass_app/{ => app}/android/app/src/main/res/mipmap-mdpi/ic_launcher.png (100%) rename compass_app/{ => app}/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png (100%) rename compass_app/{ => app}/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png (100%) rename compass_app/{ => app}/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png (100%) rename compass_app/{ => app}/android/app/src/main/res/values-night/styles.xml (100%) rename compass_app/{ => app}/android/app/src/main/res/values/styles.xml (100%) rename compass_app/{ => app}/android/app/src/profile/AndroidManifest.xml (100%) rename compass_app/{ => app}/android/build.gradle (100%) rename compass_app/{ => app}/android/gradle.properties (100%) rename compass_app/{ => app}/android/gradle/wrapper/gradle-wrapper.properties (100%) rename compass_app/{ => app}/android/settings.gradle (100%) create mode 100644 compass_app/app/assets/destinations.json create mode 100644 compass_app/app/devtools_options.yaml rename compass_app/{ => app}/ios/.gitignore (100%) rename compass_app/{ => app}/ios/Flutter/AppFrameworkInfo.plist (100%) rename compass_app/{ => app}/ios/Flutter/Debug.xcconfig (100%) rename compass_app/{ => app}/ios/Flutter/Release.xcconfig (100%) rename compass_app/{ => app}/ios/Runner.xcodeproj/project.pbxproj (100%) rename compass_app/{ => app}/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename compass_app/{ => app}/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename compass_app/{ => app}/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (100%) rename compass_app/{ => app}/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (100%) rename compass_app/{ => app}/ios/Runner.xcworkspace/contents.xcworkspacedata (100%) rename compass_app/{ => app}/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename compass_app/{ => app}/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (100%) rename compass_app/{ => app}/ios/Runner/AppDelegate.swift (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png (100%) rename compass_app/{ => app}/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md (100%) rename compass_app/{ => app}/ios/Runner/Base.lproj/LaunchScreen.storyboard (100%) rename compass_app/{ => app}/ios/Runner/Base.lproj/Main.storyboard (100%) rename compass_app/{ => app}/ios/Runner/Info.plist (100%) rename compass_app/{ => app}/ios/Runner/Runner-Bridging-Header.h (100%) rename compass_app/{ => app}/ios/RunnerTests/RunnerTests.swift (100%) create mode 100644 compass_app/app/lib/config/dependencies.dart create mode 100644 compass_app/app/lib/data/models/destination.dart create mode 100644 compass_app/app/lib/data/repositories/destination/destination_repository.dart create mode 100644 compass_app/app/lib/data/repositories/destination/destination_repository_local.dart create mode 100644 compass_app/app/lib/data/services/placeholder create mode 100644 compass_app/app/lib/main.dart create mode 100644 compass_app/app/lib/routing/router.dart create mode 100644 compass_app/app/lib/ui/core/themes/colors.dart create mode 100644 compass_app/app/lib/ui/core/themes/text_styles.dart create mode 100644 compass_app/app/lib/ui/core/themes/theme.dart create mode 100644 compass_app/app/lib/ui/core/ui/tag_chip.dart create mode 100644 compass_app/app/lib/ui/results/view_models/results_viewmodel.dart create mode 100644 compass_app/app/lib/ui/results/widgets/result_card.dart create mode 100644 compass_app/app/lib/ui/results/widgets/results_screen.dart create mode 100644 compass_app/app/lib/utils/result.dart rename compass_app/{ => app}/linux/.gitignore (100%) rename compass_app/{ => app}/linux/CMakeLists.txt (100%) rename compass_app/{ => app}/linux/flutter/CMakeLists.txt (100%) rename compass_app/{ => app}/linux/flutter/generated_plugin_registrant.cc (100%) rename compass_app/{ => app}/linux/flutter/generated_plugin_registrant.h (100%) rename compass_app/{ => app}/linux/flutter/generated_plugins.cmake (100%) rename compass_app/{ => app}/linux/main.cc (100%) rename compass_app/{ => app}/linux/my_application.cc (100%) rename compass_app/{ => app}/linux/my_application.h (100%) rename compass_app/{ => app}/macos/.gitignore (100%) rename compass_app/{ => app}/macos/Flutter/Flutter-Debug.xcconfig (100%) rename compass_app/{ => app}/macos/Flutter/Flutter-Release.xcconfig (100%) create mode 100644 compass_app/app/macos/Flutter/GeneratedPluginRegistrant.swift rename compass_app/{ => app}/macos/Runner.xcodeproj/project.pbxproj (100%) rename compass_app/{ => app}/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename compass_app/{ => app}/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (100%) rename compass_app/{ => app}/macos/Runner.xcworkspace/contents.xcworkspacedata (100%) rename compass_app/{ => app}/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename compass_app/{ => app}/macos/Runner/AppDelegate.swift (100%) rename compass_app/{ => app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename compass_app/{ => app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png (100%) rename compass_app/{ => app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png (100%) rename compass_app/{ => app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png (100%) rename compass_app/{ => app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png (100%) rename compass_app/{ => app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png (100%) rename compass_app/{ => app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png (100%) rename compass_app/{ => app}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png (100%) rename compass_app/{ => app}/macos/Runner/Base.lproj/MainMenu.xib (100%) rename compass_app/{ => app}/macos/Runner/Configs/AppInfo.xcconfig (100%) rename compass_app/{ => app}/macos/Runner/Configs/Debug.xcconfig (100%) rename compass_app/{ => app}/macos/Runner/Configs/Release.xcconfig (100%) rename compass_app/{ => app}/macos/Runner/Configs/Warnings.xcconfig (100%) rename compass_app/{ => app}/macos/Runner/DebugProfile.entitlements (85%) rename compass_app/{ => app}/macos/Runner/Info.plist (100%) rename compass_app/{ => app}/macos/Runner/MainFlutterWindow.swift (100%) rename compass_app/{ => app}/macos/Runner/Release.entitlements (100%) rename compass_app/{ => app}/macos/RunnerTests/RunnerTests.swift (100%) rename compass_app/{ => app}/pubspec.yaml (57%) create mode 100644 compass_app/app/test/data/repositories/destination/destination_repository_local_test.dart create mode 100644 compass_app/app/test/ui/results/fake_destination_repository.dart create mode 100644 compass_app/app/test/ui/results/results_screen_test.dart create mode 100644 compass_app/app/test/ui/results/results_viewmodel_test.dart rename compass_app/{ => app}/web/favicon.png (100%) rename compass_app/{ => app}/web/icons/Icon-192.png (100%) rename compass_app/{ => app}/web/icons/Icon-512.png (100%) rename compass_app/{ => app}/web/icons/Icon-maskable-192.png (100%) rename compass_app/{ => app}/web/icons/Icon-maskable-512.png (100%) rename compass_app/{ => app}/web/index.html (100%) rename compass_app/{ => app}/web/manifest.json (100%) rename compass_app/{ => app}/windows/.gitignore (100%) rename compass_app/{ => app}/windows/CMakeLists.txt (100%) rename compass_app/{ => app}/windows/flutter/CMakeLists.txt (100%) rename compass_app/{ => app}/windows/flutter/generated_plugin_registrant.cc (100%) rename compass_app/{ => app}/windows/flutter/generated_plugin_registrant.h (100%) rename compass_app/{ => app}/windows/flutter/generated_plugins.cmake (100%) rename compass_app/{ => app}/windows/runner/CMakeLists.txt (100%) rename compass_app/{ => app}/windows/runner/Runner.rc (100%) rename compass_app/{ => app}/windows/runner/flutter_window.cpp (100%) rename compass_app/{ => app}/windows/runner/flutter_window.h (100%) rename compass_app/{ => app}/windows/runner/main.cpp (100%) rename compass_app/{ => app}/windows/runner/resource.h (100%) rename compass_app/{ => app}/windows/runner/resources/app_icon.ico (100%) rename compass_app/{ => app}/windows/runner/runner.exe.manifest (100%) rename compass_app/{ => app}/windows/runner/utils.cpp (100%) rename compass_app/{ => app}/windows/runner/utils.h (100%) rename compass_app/{ => app}/windows/runner/win32_window.cpp (100%) rename compass_app/{ => app}/windows/runner/win32_window.h (100%) delete mode 100644 compass_app/lib/main.dart delete mode 100644 compass_app/macos/Flutter/GeneratedPluginRegistrant.swift diff --git a/compass_app/analysis_options.yaml b/compass_app/analysis_options.yaml deleted file mode 100644 index f9b303465..000000000 --- a/compass_app/analysis_options.yaml +++ /dev/null @@ -1 +0,0 @@ -include: package:flutter_lints/flutter.yaml diff --git a/compass_app/.gitignore b/compass_app/app/.gitignore similarity index 100% rename from compass_app/.gitignore rename to compass_app/app/.gitignore diff --git a/compass_app/.metadata b/compass_app/app/.metadata similarity index 100% rename from compass_app/.metadata rename to compass_app/app/.metadata diff --git a/compass_app/README.md b/compass_app/app/README.md similarity index 100% rename from compass_app/README.md rename to compass_app/app/README.md diff --git a/compass_app/app/analysis_options.yaml b/compass_app/app/analysis_options.yaml new file mode 100644 index 000000000..a6f303cb9 --- /dev/null +++ b/compass_app/app/analysis_options.yaml @@ -0,0 +1,5 @@ +include: package:flutter_lints/flutter.yaml + +linter: + rules: + - prefer_relative_imports \ No newline at end of file diff --git a/compass_app/android/.gitignore b/compass_app/app/android/.gitignore similarity index 100% rename from compass_app/android/.gitignore rename to compass_app/app/android/.gitignore diff --git a/compass_app/android/app/build.gradle b/compass_app/app/android/app/build.gradle similarity index 100% rename from compass_app/android/app/build.gradle rename to compass_app/app/android/app/build.gradle diff --git a/compass_app/android/app/src/debug/AndroidManifest.xml b/compass_app/app/android/app/src/debug/AndroidManifest.xml similarity index 100% rename from compass_app/android/app/src/debug/AndroidManifest.xml rename to compass_app/app/android/app/src/debug/AndroidManifest.xml diff --git a/compass_app/android/app/src/main/AndroidManifest.xml b/compass_app/app/android/app/src/main/AndroidManifest.xml similarity index 100% rename from compass_app/android/app/src/main/AndroidManifest.xml rename to compass_app/app/android/app/src/main/AndroidManifest.xml diff --git a/compass_app/android/app/src/main/kotlin/com/example/compass_app/MainActivity.kt b/compass_app/app/android/app/src/main/kotlin/com/example/compass_app/MainActivity.kt similarity index 100% rename from compass_app/android/app/src/main/kotlin/com/example/compass_app/MainActivity.kt rename to compass_app/app/android/app/src/main/kotlin/com/example/compass_app/MainActivity.kt diff --git a/compass_app/android/app/src/main/res/drawable-v21/launch_background.xml b/compass_app/app/android/app/src/main/res/drawable-v21/launch_background.xml similarity index 100% rename from compass_app/android/app/src/main/res/drawable-v21/launch_background.xml rename to compass_app/app/android/app/src/main/res/drawable-v21/launch_background.xml diff --git a/compass_app/android/app/src/main/res/drawable/launch_background.xml b/compass_app/app/android/app/src/main/res/drawable/launch_background.xml similarity index 100% rename from compass_app/android/app/src/main/res/drawable/launch_background.xml rename to compass_app/app/android/app/src/main/res/drawable/launch_background.xml diff --git a/compass_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/compass_app/app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from compass_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png rename to compass_app/app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/compass_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/compass_app/app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from compass_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png rename to compass_app/app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/compass_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/compass_app/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from compass_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to compass_app/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/compass_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/compass_app/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from compass_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to compass_app/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/compass_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/compass_app/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from compass_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to compass_app/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/compass_app/android/app/src/main/res/values-night/styles.xml b/compass_app/app/android/app/src/main/res/values-night/styles.xml similarity index 100% rename from compass_app/android/app/src/main/res/values-night/styles.xml rename to compass_app/app/android/app/src/main/res/values-night/styles.xml diff --git a/compass_app/android/app/src/main/res/values/styles.xml b/compass_app/app/android/app/src/main/res/values/styles.xml similarity index 100% rename from compass_app/android/app/src/main/res/values/styles.xml rename to compass_app/app/android/app/src/main/res/values/styles.xml diff --git a/compass_app/android/app/src/profile/AndroidManifest.xml b/compass_app/app/android/app/src/profile/AndroidManifest.xml similarity index 100% rename from compass_app/android/app/src/profile/AndroidManifest.xml rename to compass_app/app/android/app/src/profile/AndroidManifest.xml diff --git a/compass_app/android/build.gradle b/compass_app/app/android/build.gradle similarity index 100% rename from compass_app/android/build.gradle rename to compass_app/app/android/build.gradle diff --git a/compass_app/android/gradle.properties b/compass_app/app/android/gradle.properties similarity index 100% rename from compass_app/android/gradle.properties rename to compass_app/app/android/gradle.properties diff --git a/compass_app/android/gradle/wrapper/gradle-wrapper.properties b/compass_app/app/android/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from compass_app/android/gradle/wrapper/gradle-wrapper.properties rename to compass_app/app/android/gradle/wrapper/gradle-wrapper.properties diff --git a/compass_app/android/settings.gradle b/compass_app/app/android/settings.gradle similarity index 100% rename from compass_app/android/settings.gradle rename to compass_app/app/android/settings.gradle diff --git a/compass_app/app/assets/destinations.json b/compass_app/app/assets/destinations.json new file mode 100644 index 000000000..be1f233c5 --- /dev/null +++ b/compass_app/app/assets/destinations.json @@ -0,0 +1,1235 @@ +[ + { + "ref": "alaska", + "name": "Alaska", + "country": "United States", + "continent": "North America", + "knownFor": "Alaska is a haven for outdoor enthusiasts and nature lovers. Visitors can experience glaciers, mountains, and wildlife, making it ideal for hiking, kayaking, and wildlife viewing. Alaska also offers a unique cultural experience with its rich Native American heritage and frontier spirit.", + "tags": ["Mountain", "Off-the-beaten-path", "Wildlife watching"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/alaska.jpg" + }, + { + "ref": "amalfi-coast", + "name": "Amalfi Coast", + "country": "Italy", + "continent": "Europe", + "knownFor": "Experience the breathtaking beauty of the Amalfi Coast, with its dramatic cliffs, colorful villages, and turquoise waters. Indulge in delicious Italian cuisine, explore charming towns like Positano and Amalfi, and soak up the sun on picturesque beaches.", + "tags": ["Beach", "Romantic", "Foodie"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/amalfi-coast.jpg" + }, + { + "ref": "amazon-rainforest", + "name": "Amazon Rainforest", + "country": "Brazil", + "continent": "South America", + "knownFor": "Immerse yourself in the biodiversity of the world's largest rainforest. Embark on jungle treks, spot exotic wildlife, and discover indigenous cultures. Take a boat trip down the Amazon River, explore the canopy on a zipline, and experience the unique ecosystem.", + "tags": ["Jungle", "Wildlife watching", "Adventure sports"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/amazon-rainforest.jpg" + }, + { + "ref": "andes-mountains", + "name": "The Andes Mountains", + "country": "South America", + "continent": "South America", + "knownFor": "The Andes Mountains, stretching along the western coast of South America, offer diverse landscapes and experiences. Visitors can trek to Machu Picchu in Peru, explore the salt flats of Salar de Uyuni in Bolivia, or visit the glaciers of Patagonia. The Andes also provide opportunities for skiing, mountaineering, and cultural encounters with indigenous communities.", + "tags": ["Mountain", "Hiking", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/andes-mountains.jpg" + }, + { + "ref": "angkor-wat", + "name": "Angkor Wat", + "country": "Cambodia", + "continent": "Asia", + "knownFor": "Angkor Wat, a vast temple complex in Cambodia, is the largest religious monument in the world and a UNESCO World Heritage site. Visitors can explore the intricate carvings, towering spires, and vast courtyards, marveling at the architectural grandeur and rich history of the Khmer Empire.", + "tags": ["Historic", "Cultural experiences", "Sightseeing"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/angkor-wat.jpg" + }, + { + "ref": "antelope-canyon", + "name": "Antelope Canyon", + "country": "United States", + "continent": "North America", + "knownFor": "Experience the awe-inspiring beauty of Antelope Canyon, a slot canyon renowned for its flowing sandstone formations and mesmerizing light beams. Embark on guided tours to navigate the narrow passageways and capture stunning photographs. Learn about the Navajo Nation's history and culture, as the canyon is located on their land.", + "tags": ["Off-the-beaten-path", "Hiking", "Sightseeing"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/antelope-canyon.jpg" + }, + { + "ref": "aruba", + "name": "Aruba", + "country": "Aruba", + "continent": "South America", + "knownFor": "Indulge in the beauty of Aruba, a Caribbean paradise known for its pristine beaches, turquoise waters, and year-round sunshine. Relax on the white sands of Eagle Beach, explore the vibrant capital of Oranjestad, and discover hidden coves and natural wonders. Aruba offers a perfect escape for beach lovers and water sports enthusiasts.", + "tags": ["Beach", "Island", "Scuba diving"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/aruba.jpg" + }, + { + "ref": "asheville", + "name": "Asheville", + "country": "USA", + "continent": "North America", + "knownFor": "Asheville, nestled in the Blue Ridge Mountains of North Carolina, is a vibrant city known for its arts scene, craft breweries, and outdoor activities. Visitors can explore the historic Biltmore Estate, hike in the surrounding mountains, sample local beers, and enjoy the city's eclectic shops and restaurants.", + "tags": ["City", "Hiking", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/asheville.jpg" + }, + { + "ref": "azores", + "name": "Azores", + "country": "Portugal", + "continent": "Europe", + "knownFor": "This archipelago in the mid-Atlantic boasts stunning volcanic landscapes, lush green hills, and dramatic coastlines. Hike to crater lakes, soak in natural hot springs, or go whale watching in the surrounding waters. With its relaxed atmosphere and unique culture, the Azores is a perfect destination for nature lovers and adventurers seeking an off-the-beaten-path experience.", + "tags": ["Island", "Off-the-beaten-path", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/azores.jpg" + }, + { + "ref": "bali", + "name": "Bali", + "country": "Indonesia", + "continent": "Asia", + "knownFor": "Discover the cultural heart of Indonesia on the island of Bali. Explore ancient temples, experience vibrant Hindu traditions, and relax on beautiful beaches. Practice yoga and meditation, indulge in spa treatments, and enjoy the island's lush natural beauty.", + "tags": ["Island", "Cultural experiences", "Wellness retreats"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/bali.jpg" + }, + { + "ref": "banff-national-park", + "name": "Banff National Park", + "country": "Canada", + "continent": "North America", + "knownFor": "Nestled in the Canadian Rockies, Banff National Park offers stunning mountain scenery, turquoise lakes, and abundant wildlife. Hike to Lake Louise, explore Johnston Canyon, and enjoy outdoor activities year-round.", + "tags": ["Mountain", "Hiking", "Wildlife watching"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/banff-national-park.jpg" + }, + { + "ref": "belize", + "name": "Belize", + "country": "Belize", + "continent": "North America", + "knownFor": "Embark on an unforgettable adventure in Belize, a Central American gem boasting lush rainforests, ancient Maya ruins, and the world's second-largest barrier reef. Explore the mysteries of Caracol and Xunantunich, dive into the Great Blue Hole, and discover diverse marine life. Belize offers a unique blend of cultural exploration and eco-tourism.", + "tags": ["Jungle", "Historic", "Scuba diving"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/belize.jpg" + }, + { + "ref": "bhutan", + "name": "Bhutan", + "country": "Bhutan", + "continent": "Asia", + "knownFor": "Discover the mystical kingdom of Bhutan, nestled in the Himalayas. Explore ancient monasteries, hike through pristine valleys, and experience the unique culture and traditions. Immerse yourself in the spiritual atmosphere and embrace the concept of Gross National Happiness.", + "tags": ["Mountain", "Cultural experiences", "Off-the-beaten-path"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/bhutan.jpg" + }, + { + "ref": "big-island-hawaii", + "name": "Big Island", + "country": "United States", + "continent": "North America", + "knownFor": "The Big Island of Hawaii offers diverse landscapes, from volcanic craters and black sand beaches to lush rainforests and snow-capped mountains. Visitors can witness the fiery glow of Kilauea volcano, snorkel with manta rays, and stargaze atop Mauna Kea.", + "tags": ["Island", "Hiking", "Snorkeling"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/big-island-hawaii.jpg" + }, + { + "ref": "big-sur", + "name": "Big Sur", + "country": "United States", + "continent": "North America", + "knownFor": "Experience the breathtaking beauty of California's rugged coastline along Big Sur. Drive the iconic Pacific Coast Highway, stopping at dramatic cliffs, hidden coves, and redwood forests. Enjoy hiking, camping, or simply soaking up the awe-inspiring views of this natural wonderland.", + "tags": ["Road trip destination", "Secluded", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/big-sur.jpg" + }, + { + "ref": "bora-bora", + "name": "Bora Bora", + "country": "French Polynesia", + "continent": "Oceania", + "knownFor": "Bora Bora is synonymous with luxury and tranquility. Overwater bungalows perched above turquoise lagoons offer a unique and indulgent experience. Visitors can enjoy snorkeling, diving, and swimming amidst vibrant coral reefs and diverse marine life. The island's lush interior provides opportunities for hiking and exploring, while Polynesian culture adds a touch of exotic charm.", + "tags": ["Island", "Luxury", "Secluded"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/bora-bora.jpg" + }, + { + "ref": "botswana", + "name": "Okavango Delta", + "country": "Botswana", + "continent": "Africa", + "knownFor": "The Okavango Delta, a unique inland delta in Botswana, is a haven for wildlife enthusiasts. Visitors can embark on safari adventures, encountering elephants, lions, hippos, and a diverse array of birds. The delta's waterways offer opportunities for mokoro (canoe) excursions and boat tours, providing a close-up view of the abundant wildlife and stunning landscapes.", + "tags": ["Wildlife watching", "Adventure sports", "Luxury"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/botswana.jpg" + }, + { + "ref": "bruges", + "name": "Bruges", + "country": "Belgium", + "continent": "Europe", + "knownFor": "Step back in time in this charming medieval city with its cobblestone streets, canals, and well-preserved architecture. Explore the historic Markt square, indulge in delicious Belgian chocolate and beer, or take a boat tour through the canals. Bruges offers a romantic and picturesque escape for history buffs and those seeking a quintessential European experience.", + "tags": ["City", "Historic", "Romantic"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/bruges.jpg" + }, + { + "ref": "brunei", + "name": "Brunei", + "country": "Brunei", + "continent": "Asia", + "knownFor": "This small sultanate on the island of Borneo offers a fascinating blend of culture and nature. Visitors can explore the opulent Sultan Omar Ali Saifuddin Mosque, delve into the lush rainforests, and discover the unique water village of Kampong Ayer.", + "tags": ["Secluded", "Cultural experiences", "Island"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/brunei.jpg" + }, + { + "ref": "budapest", + "name": "Budapest", + "country": "Hungary", + "continent": "Europe", + "knownFor": "Discover the charm of Budapest, a historic city divided by the Danube River. Explore Buda's Castle District with its medieval streets and Fisherman's Bastion, offering panoramic views. Relax in the thermal baths, a legacy of the Ottoman era, or visit the Hungarian Parliament Building, a stunning example of Gothic Revival architecture.", + "tags": ["City", "Historic", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/budapest.jpg" + }, + { + "ref": "burgundy", + "name": "Burgundy", + "country": "France", + "continent": "Europe", + "knownFor": "Burgundy, a region in eastern France, is renowned for its world-class wines, charming villages, and rich history. Explore vineyards, indulge in wine tastings, and visit medieval castles and abbeys. Cycle through rolling hills, savor gourmet cuisine, and experience the art de vivre of this picturesque region.", + "tags": ["Rural", "Wine tasting", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/burgundy.jpg" + }, + { + "ref": "cambodia", + "name": "Cambodia", + "country": "Cambodia", + "continent": "Asia", + "knownFor": "Cambodia, a Southeast Asian nation, is a captivating blend of ancient wonders, natural beauty, and vibrant culture. Explore the magnificent temples of Angkor, relax on pristine beaches, and cruise along the Mekong River. Experience the warmth of the Cambodian people, savor delicious cuisine, and discover the rich history of this fascinating country.", + "tags": ["Historic", "Cultural experiences", "Beach"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/cambodia.jpg" + }, + { + "ref": "canadian-rockies", + "name": "Canadian Rockies", + "country": "Canada", + "continent": "North America", + "knownFor": "Embark on an adventure through the majestic Canadian Rockies, where towering mountains, turquoise lakes, and glaciers create a breathtaking landscape. Hike through scenic trails, go skiing or snowboarding in world-class resorts, and encounter diverse wildlife. Experience the thrill of outdoor activities and the beauty of untouched nature.", + "tags": ["Mountain", "Hiking", "Adventure sports"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/canadian-rockies.jpg" + }, + { + "ref": "canary-islands", + "name": "Canary Islands", + "country": "Spain", + "continent": "Europe", + "knownFor": "Discover the volcanic beauty of the Canary Islands, a Spanish archipelago off the coast of Africa. Explore diverse landscapes, from the dramatic volcanic peaks of Tenerife and Mount Teide to the golden beaches of Gran Canaria and Fuerteventura. Enjoy water sports, hiking, and stargazing in this island paradise.", + "tags": ["Island", "Beach", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/canary-islands.jpg" + }, + { + "ref": "cappadocia", + "name": "Cappadocia", + "country": "Turkey", + "continent": "Asia", + "knownFor": "Embark on a magical journey through a surreal landscape of fairy chimneys, cave dwellings, and underground cities. Soar above the valleys in a hot air balloon, explore ancient rock-cut churches, and experience the unique culture and hospitality of the region.", + "tags": ["Historic", "Off-the-beaten-path", "Adventure sports"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/cappadocia.jpg" + }, + { + "ref": "chilean-lake-district", + "name": "Chilean Lake District", + "country": "Chile", + "continent": "South America", + "knownFor": "The Chilean Lake District is a paradise for nature lovers, with snow-capped volcanoes, turquoise lakes, and lush forests. Hike in national parks, go kayaking on the lakes, and enjoy the tranquility of the surroundings. The region's German heritage adds a unique cultural element.", + "tags": ["Lake", "Mountain", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/chilean-lake-district.jpg" + }, + { + "ref": "cinque-terre", + "name": "Cinque Terre", + "country": "Italy", + "continent": "Europe", + "knownFor": "Explore the picturesque villages of Cinque Terre, perched on the rugged Italian Riviera coastline. Hike the scenic trails connecting the five colorful towns, each with its unique character. Enjoy fresh seafood, local wines, and breathtaking views of the Mediterranean Sea.", + "tags": ["Hiking", "Coastal", "Foodie"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/cinque-terre.jpg" + }, + { + "ref": "colombia", + "name": "Colombia", + "country": "Colombia", + "continent": "South America", + "knownFor": "Colombia is a vibrant country with a diverse landscape, ranging from the Andes Mountains to the Caribbean coast. Explore the colonial city of Cartagena, hike in the Cocora Valley, or dance the night away in Medellín. Discover the coffee region, learn about the indigenous cultures, and experience the warmth of the Colombian people.", + "tags": ["City", "Mountain", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/colombia.jpg" + }, + { + "ref": "corsica", + "name": "Corsica", + "country": "France", + "continent": "Europe", + "knownFor": "This mountainous Mediterranean island offers a diverse landscape of rugged mountains, pristine beaches, and charming villages. Visitors can enjoy hiking, water sports, exploring historical sites, and experiencing the unique Corsican culture.", + "tags": ["Mountain", "Beach", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/corsica.jpg" + }, + { + "ref": "costa-rica", + "name": "Osa Peninsula", + "country": "Costa Rica", + "continent": "North America", + "knownFor": "A haven for eco-tourism, the Osa Peninsula boasts incredible biodiversity, lush rainforests, and pristine beaches. Adventure seekers can go zip-lining, kayaking, and hiking, while nature enthusiasts can spot monkeys, sloths, and exotic birds. The Corcovado National Park, known as one of the most biodiverse places on Earth, is a must-visit for wildlife watching.", + "tags": ["Jungle", "Secluded", "Wildlife watching"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/costa-rica.jpg" + }, + { + "ref": "dubai", + "name": "Dubai", + "country": "United Arab Emirates", + "continent": "Asia", + "knownFor": "Dubai is a modern metropolis known for its towering skyscrapers, luxurious shopping malls, and extravagant attractions. Visitors can experience the thrill of the Burj Khalifa, the world's tallest building, shop at the Dubai Mall, or enjoy a desert safari. With its vibrant nightlife and world-class dining scene, Dubai offers a truly cosmopolitan experience.", + "tags": ["City", "Luxury", "Shopping"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/dubai.jpg" + }, + { + "ref": "dubrovnik", + "name": "Dubrovnik", + "country": "Croatia", + "continent": "Europe", + "knownFor": "Dubrovnik, the \"Pearl of the Adriatic\", is a historic walled city renowned for its stunning architecture, ancient city walls, and breathtaking coastal views. Visitors can explore historical sites, enjoy boat trips, and experience the vibrant cultural scene.", + "tags": ["Historic", "Sightseeing", "City"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/dubrovnik.jpg" + }, + { + "ref": "ethiopia", + "name": "Ethiopia", + "country": "Ethiopia", + "continent": "Africa", + "knownFor": "Ethiopia, a landlocked country in the Horn of Africa, is a unique destination with ancient history, diverse landscapes, and rich culture. Explore the rock-hewn churches of Lalibela, trek through the Simien Mountains, and witness the vibrant tribal traditions. From bustling cities to remote villages, Ethiopia offers an unforgettable journey.", + "tags": ["Off-the-beaten-path", "Cultural experiences", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/ethiopia.jpg" + }, + { + "ref": "fiesole", + "name": "Fiesole", + "country": "Italy", + "continent": "Europe", + "knownFor": "Step back in time in Fiesole, a charming hilltop town overlooking Florence, Italy. Explore Etruscan and Roman ruins, visit the beautiful Fiesole Cathedral, and wander through quaint streets lined with historic buildings. Enjoy breathtaking views of the Tuscan countryside and escape the hustle and bustle of Florence.", + "tags": ["Historic", "Rural", "Romantic"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/fiesole.jpg" + }, + { + "ref": "fiji", + "name": "Fiji", + "country": "Fiji", + "continent": "Oceania", + "knownFor": "Fiji, an archipelago in the South Pacific, is renowned for its pristine beaches, crystal-clear waters, and lush rainforests. Visitors can indulge in water activities like snorkeling, scuba diving, and surfing, or explore the islands' rich cultural heritage and traditions. Fiji is also a popular destination for honeymoons and romantic getaways.", + "tags": ["Island", "Beach", "Scuba diving"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/fiji.jpg" + }, + { + "ref": "french-alps", + "name": "French Alps", + "country": "France", + "continent": "Europe", + "knownFor": "The French Alps offer stunning mountain scenery, charming villages, and world-class skiing. During the winter months, hit the slopes in renowned resorts like Chamonix and Val d'Isère. In the summer, enjoy hiking, mountain biking, and paragliding.", + "tags": ["Mountain", "Skiing", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/french-alps.jpg" + }, + { + "ref": "french-polynesia", + "name": "French Polynesia", + "country": "France", + "continent": "Oceania", + "knownFor": "Escape to the paradise of French Polynesia, where overwater bungalows, turquoise lagoons, and pristine beaches await. Dive into the vibrant underwater world, explore volcanic landscapes, and experience Polynesian culture. Indulge in luxury resorts, romantic getaways, and unforgettable island hopping adventures.", + "tags": ["Tropical", "Island", "Luxury"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/french-polynesia.jpg" + }, + { + "ref": "french-riviera", + "name": "French Riviera", + "country": "France", + "continent": "Europe", + "knownFor": "Discover the glamour of the French Riviera, where glamorous beaches, luxury yachts, and charming coastal towns line the Mediterranean coast. Explore the vibrant city of Nice, visit the iconic Monte Carlo casino, and soak up the sun on the beaches of Cannes. Experience the region's luxurious lifestyle, stunning scenery, and vibrant nightlife.", + "tags": ["Beach", "Luxury", "Nightlife"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/french-riviera.jpg" + }, + { + "ref": "galapagos-islands", + "name": "Galapagos Islands", + "country": "Ecuador", + "continent": "South America", + "knownFor": "Embark on a once-in-a-lifetime adventure to the Galapagos Islands, a living laboratory of evolution. Observe unique wildlife, including giant tortoises, marine iguanas, and blue-footed boobies. Go snorkeling or diving among vibrant coral reefs and explore volcanic landscapes.", + "tags": ["Island", "Wildlife watching", "Scuba diving"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/galapagos-islands.jpg" + }, + { + "ref": "galicia", + "name": "Galicia", + "country": "Spain", + "continent": "Europe", + "knownFor": "This region in northwestern Spain boasts rugged coastlines, green landscapes, and a rich Celtic heritage. Visitors can enjoy fresh seafood, explore charming towns, embark on the Camino de Santiago pilgrimage, and discover the unique Galician culture.", + "tags": ["Hiking", "Cultural experiences", "Foodie"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/galicia.jpg" + }, + { + "ref": "grand-canyon", + "name": "Grand Canyon", + "country": "United States", + "continent": "North America", + "knownFor": "Witness the awe-inspiring vastness and natural beauty of the Grand Canyon, a UNESCO World Heritage Site. Hike along the rim for breathtaking panoramic views, descend into the canyon for a challenging adventure, or raft down the Colorado River. The Grand Canyon offers an unforgettable experience for nature enthusiasts and adventure seekers.", + "tags": ["Mountain", "Hiking", "Adventure sports"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/grand-canyon.jpg" + }, + { + "ref": "great-barrier-reef", + "name": "Great Barrier Reef", + "country": "Australia", + "continent": "Australia", + "knownFor": "The Great Barrier Reef is the world's largest coral reef system, teeming with marine life. Snorkel or scuba dive among colorful corals, spot tropical fish, and experience the underwater wonders of this natural treasure.", + "tags": ["Snorkeling", "Scuba diving", "Adventure sports"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/great-barrier-reef.jpg" + }, + { + "ref": "great-bear-rainforest", + "name": "Great Bear Rainforest", + "country": "Canada", + "continent": "North America", + "knownFor": "The Great Bear Rainforest is a vast and pristine wilderness area on the Pacific coast of British Columbia. It is home to a diverse array of wildlife, including grizzly bears, black bears, wolves, and whales. Visitors can explore the rainforest by boat, kayak, or on foot, and experience the magic of this untouched ecosystem.", + "tags": ["Wildlife watching", "Hiking", "Eco-conscious"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/great-bear-rainforest.jpg" + }, + { + "ref": "greek-islands", + "name": "Greek Islands", + "country": "Greece", + "continent": "Europe", + "knownFor": "Island hop through the Greek Islands, each with its own unique charm and allure. Explore ancient ruins, relax on pristine beaches, and indulge in delicious Greek cuisine. Experience the vibrant nightlife of Mykonos, the romantic sunsets of Santorini, and the historical treasures of Crete. Discover a world of crystal-clear waters, whitewashed villages, and endless sunshine.", + "tags": ["Island", "Beach", "Historic"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/greek-islands.jpg" + }, + { + "ref": "greenland", + "name": "Ilulissat Icefjord", + "country": "Greenland", + "continent": "North America", + "knownFor": "Ilulissat Icefjord is a UNESCO World Heritage site and a breathtaking natural wonder with massive icebergs calving from the Sermeq Kujalleq glacier. Visitors can take boat tours to witness the stunning ice formations, go hiking in the surrounding area, and experience the unique culture of Greenland.", + "tags": ["Off-the-beaten-path", "Adventure sports", "Wildlife watching"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/greenland.jpg" + }, + { + "ref": "guadeloupe", + "name": "Guadeloupe", + "country": "France", + "continent": "North America", + "knownFor": "Guadeloupe, a butterfly-shaped archipelago in the Caribbean, is a French overseas territory boasting stunning natural landscapes. With its lush rainforests, volcanic peaks, and white-sand beaches, it's a paradise for outdoor enthusiasts. Hike to cascading waterfalls, explore vibrant coral reefs, and savor the unique blend of French and Creole culture.", + "tags": ["Island", "Tropical", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/guadeloupe.jpg" + }, + { + "ref": "guatemala", + "name": "Lake Atitlán", + "country": "Guatemala", + "continent": "North America", + "knownFor": "Lake Atitlán, surrounded by volcanoes and traditional Mayan villages, offers a scenic and cultural experience in Guatemala. Visitors can explore the lakeside towns, hike to viewpoints, visit Mayan ruins, and learn about local traditions. The lake also provides opportunities for kayaking, swimming, and boat trips.", + "tags": ["Lake", "Cultural experiences", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/guatemala.jpg" + }, + { + "ref": "ha-long-bay", + "name": "Ha Long Bay", + "country": "Vietnam", + "continent": "Asia", + "knownFor": "Ha Long Bay is a breathtaking UNESCO World Heritage Site, featuring thousands of limestone islands and islets rising from emerald waters. Visitors can cruise through the bay, explore hidden caves, kayak among the karst formations, and experience the unique beauty of this natural wonder.", + "tags": ["Island", "Secluded", "Sightseeing"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/ha-long-bay.jpg" + }, + { + "ref": "harrisburg", + "name": "Harrisburg", + "country": "USA", + "continent": "North America", + "knownFor": "Discover the charm of Harrisburg, Pennsylvania's historic capital city. Explore the impressive Pennsylvania State Capitol Building, delve into history at the National Civil War Museum, and enjoy family fun at City Island. With its scenic riverfront location, Harrisburg offers a blend of cultural attractions and outdoor activities.", + "tags": ["City", "Historic", "Family-friendly"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/harrisburg.jpg" + }, + { + "ref": "havana", + "name": "Havana", + "country": "Cuba", + "continent": "North America", + "knownFor": "Step back in time in Havana, the vibrant capital of Cuba. Stroll along the Malecón, a seaside promenade, and admire the colorful vintage cars. Explore Old Havana, a UNESCO World Heritage Site, with its colonial architecture and lively squares. Immerse yourself in Cuban culture, music, and dance.", + "tags": ["City", "Historic", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/havana.jpg" + }, + { + "ref": "ho-chi-minh-city", + "name": "Ho Chi Minh City", + "country": "Vietnam", + "continent": "Asia", + "knownFor": "Ho Chi Minh City is a vibrant metropolis with a rich history and delicious street food. Explore the bustling markets, visit historical landmarks like the Cu Chi Tunnels, and immerse yourself in the city's energetic atmosphere. The blend of French colonial architecture and modern skyscrapers creates a unique cityscape.", + "tags": ["City", "Cultural experiences", "Food tours"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/ho-chi-minh-city.jpg" + }, + { + "ref": "iceland", + "name": "Iceland", + "country": "Iceland", + "continent": "Europe", + "knownFor": "Iceland's dramatic landscapes include glaciers, volcanoes, geysers, and waterfalls. Explore the Golden Circle, relax in geothermal pools, and witness the Northern Lights in winter.", + "tags": ["Secluded", "Adventure sports", "Winter destination"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/iceland.jpg" + }, + { + "ref": "japan-alps", + "name": "Japanese Alps", + "country": "Japan", + "continent": "Asia", + "knownFor": "The Japanese Alps offer stunning mountain scenery, traditional villages, and outdoor adventures. Hike through the Kamikochi Valley, ski in Hakuba, or soak in the onsen hot springs. Visit Matsumoto Castle, a historic landmark, and experience the unique culture of the mountain communities.", + "tags": ["Mountain", "Hiking", "Skiing"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/japan-alps.jpg" + }, + { + "ref": "jeju-island", + "name": "Jeju Island", + "country": "South Korea", + "continent": "Asia", + "knownFor": "Escape to the volcanic paradise of Jeju Island, a popular destination off the coast of South Korea. Discover stunning natural landscapes, from volcanic craters and lava tubes to pristine beaches and waterfalls. Explore unique museums, hike Mount Hallasan, and relax in charming coastal towns.", + "tags": ["Island", "Hiking", "Secluded"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/jeju-island.jpg" + }, + { + "ref": "jordan", + "name": "Petra", + "country": "Jordan", + "continent": "Asia", + "knownFor": "Petra, an ancient city carved into rose-colored sandstone cliffs, is a UNESCO World Heritage site and one of the New Seven Wonders of the World. Visitors can marvel at the Treasury, explore the Siq, and discover hidden tombs and temples. Petra offers a glimpse into the fascinating history and culture of the Nabataean civilization.", + "tags": ["Historic", "Cultural experiences", "Off-the-beaten-path"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/jordan.jpg" + }, + { + "ref": "kauai", + "name": "Kauai", + "country": "United States", + "continent": "North America", + "knownFor": "Escape to the Garden Isle of Kauai, a paradise of lush rainforests, dramatic cliffs, and pristine beaches. Hike the challenging Kalalau Trail along the Na Pali Coast, kayak the Wailua River, or relax on Poipu Beach. Discover hidden waterfalls, explore Waimea Canyon, and experience the island's laid-back atmosphere.", + "tags": ["Island", "Hiking", "Beach"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/kauai.jpg" + }, + { + "ref": "kenya", + "name": "Kenya", + "country": "Kenya", + "continent": "Africa", + "knownFor": "Embark on an unforgettable safari adventure in Kenya, home to diverse wildlife and stunning landscapes. Witness the Great Migration, encounter lions, elephants, and rhinos, and experience the rich culture of the Maasai people.", + "tags": ["Wildlife watching", "Safari", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/kenya.jpg" + }, + { + "ref": "kyoto", + "name": "Kyoto", + "country": "Japan", + "continent": "Asia", + "knownFor": "Kyoto, Japan's former capital, is a cultural treasure trove with numerous temples, shrines, and gardens. Experience traditional tea ceremonies, stroll through the Arashiyama Bamboo Grove, and immerse yourself in Japanese history and spirituality.", + "tags": ["Historic", "Cultural experiences", "City"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/kyoto.jpg" + }, + { + "ref": "lake-bled", + "name": "Lake Bled", + "country": "Slovenia", + "continent": "Europe", + "knownFor": "Nestled in the Julian Alps, Lake Bled is a fairytale-like destination with a stunning glacial lake, a charming island church, and a medieval castle perched on a cliff. Visitors can enjoy swimming, boating, hiking, and exploring the surrounding mountains. Bled is also known for its delicious cream cake and thermal springs.", + "tags": ["Lake", "Mountain", "Romantic"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/lake-bled.jpg" + }, + { + "ref": "lake-como", + "name": "Lake Como", + "country": "Italy", + "continent": "Europe", + "knownFor": "Escape to the picturesque shores of Lake Como, surrounded by charming villages, luxurious villas, and stunning mountain scenery. Take a boat tour on the lake, explore historic gardens, and indulge in fine dining and Italian wines. Enjoy hiking, biking, and water sports in the surrounding area.", + "tags": ["Lake", "Romantic", "Luxury"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/lake-como.jpg" + }, + { + "ref": "lake-district", + "name": "Lake District National Park", + "country": "England", + "continent": "Europe", + "knownFor": "Nestled in the heart of Cumbria, the Lake District offers breathtaking landscapes with rolling hills, shimmering lakes, and charming villages. Visitors can enjoy hiking, boating, and exploring the literary legacy of Beatrix Potter and William Wordsworth. The region is also known for its delicious local produce and cozy pubs.", + "tags": ["Lake", "Hiking", "Rural"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/lake-district.jpg" + }, + { + "ref": "lake-garda", + "name": "Lake Garda", + "country": "Italy", + "continent": "Europe", + "knownFor": "Lake Garda is the largest lake in Italy, known for its stunning scenery, charming towns, and historic sites. Visitors can enjoy swimming, sailing, windsurfing, and hiking in the surrounding mountains. The area is also famous for its lemon groves and olive oil production, offering delicious local cuisine and wine tasting experiences.", + "tags": ["Lake", "Mountain", "Food tours"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/lake-garda.jpg" + }, + { + "ref": "lake-tahoe", + "name": "Lake Tahoe", + "country": "USA", + "continent": "North America", + "knownFor": "Lake Tahoe offers a blend of outdoor adventure and stunning natural beauty. Visitors enjoy skiing in the winter and water sports like kayaking and paddleboarding in the summer. The crystal-clear lake, surrounded by mountains, provides breathtaking scenery and a relaxing atmosphere.", + "tags": ["Lake", "Mountain", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/lake-tahoe.jpg" + }, + { + "ref": "laos", + "name": "Laos", + "country": "Laos", + "continent": "Asia", + "knownFor": "Laos is a landlocked country in Southeast Asia, known for its laid-back atmosphere, stunning natural beauty, and ancient temples. Explore the UNESCO World Heritage city of Luang Prabang, kayak down the Mekong River, discover the Kuang Si Falls, and visit the Pak Ou Caves filled with thousands of Buddha statues.", + "tags": ["Off-the-beaten-path", "Cultural experiences", "River"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/laos.jpg" + }, + { + "ref": "lofoten-islands", + "name": "Lofoten Islands", + "country": "Norway", + "continent": "Europe", + "knownFor": "Experience the breathtaking beauty of the Arctic Circle with dramatic landscapes, towering mountains, and charming fishing villages. Hike scenic trails, kayak along pristine fjords, and marvel at the Northern Lights. Explore Viking history and indulge in fresh seafood delicacies.", + "tags": ["Island", "Secluded", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/lofoten-islands.jpg" + }, + { + "ref": "lombok", + "name": "Lombok", + "country": "Indonesia", + "continent": "Asia", + "knownFor": "Lombok, Bali's less-crowded neighbor, offers pristine beaches, lush rainforests, and the majestic Mount Rinjani volcano. Visitors can enjoy surfing, diving, hiking, and exploring the island's cultural attractions.", + "tags": ["Beach", "Mountain", "Adventure sports"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/lombok.jpg" + }, + { + "ref": "luang-prabang", + "name": "Luang Prabang", + "country": "Laos", + "continent": "Asia", + "knownFor": "Immerse yourself in the tranquility of Luang Prabang, a UNESCO World Heritage town in Laos. Visit ornate temples like Wat Xieng Thong, witness the alms-giving ceremony at dawn, and explore the night market. Cruise down the Mekong River, discover Kuang Si Falls, and experience the town's spiritual atmosphere.", + "tags": ["Off-the-beaten-path", "Cultural experiences", "River"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/luang-prabang.jpg" + }, + { + "ref": "madagascar", + "name": "Madagascar", + "country": "Madagascar", + "continent": "Africa", + "knownFor": "Madagascar, an island nation off the southeast coast of Africa, is a biodiversity hotspot with unique flora and fauna. Explore rainforests, baobab-lined avenues, and pristine beaches. Encounter lemurs, chameleons, and other endemic species, and discover the rich cultural heritage of the Malagasy people. Madagascar offers an unforgettable adventure for nature lovers.", + "tags": ["Island", "Wildlife watching", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/madagascar.jpg" + }, + { + "ref": "maldives", + "name": "Maldives", + "country": "Maldives", + "continent": "Asia", + "knownFor": "The Maldives, a tropical island nation, offers luxurious overwater bungalows, pristine beaches, and world-class diving. Relax on the white sand, swim in the crystal-clear waters, and explore the vibrant coral reefs. The Maldives is the perfect destination for a romantic getaway or a relaxing beach vacation.", + "tags": ["Island", "Beach", "Scuba diving"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/maldives.jpg" + }, + { + "ref": "mallorca", + "name": "Mallorca", + "country": "Spain", + "continent": "Europe", + "knownFor": "Mallorca offers a diverse experience, from stunning beaches and turquoise waters to charming villages and rugged mountains. Visitors can explore historic Palma, hike the Serra de Tramuntana, or simply relax on the beach and enjoy the Mediterranean sunshine.", + "tags": ["Beach", "Island", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/mallorca.jpg" + }, + { + "ref": "malta", + "name": "Malta", + "country": "Malta", + "continent": "Europe", + "knownFor": "Malta, an archipelago in the central Mediterranean, is a captivating blend of history, culture, and stunning natural beauty. Its ancient temples, fortified cities, and hidden coves attract history buffs and adventurers alike. From exploring the UNESCO-listed capital Valletta to diving in crystal-clear waters, Malta offers a diverse experience for every traveler.", + "tags": ["Island", "Historic", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/malta.jpg" + }, + { + "ref": "marrakech", + "name": "Marrakech", + "country": "Morocco", + "continent": "Africa", + "knownFor": "Step into a world of vibrant colours and bustling souks in Marrakech. Explore the historic Medina, with its maze-like alleys and hidden treasures, or marvel at the intricate architecture of mosques and palaces. Indulge in the rich flavours of Moroccan cuisine and experience the unique culture of this magical city.", + "tags": ["Cultural experiences", "City", "Shopping"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/marrakech.jpg" + }, + { + "ref": "maui", + "name": "Maui", + "country": "United States", + "continent": "North America", + "knownFor": "Experience the diverse landscapes of Maui, from volcanic craters to lush rainforests and stunning beaches. Drive the scenic Road to Hana, watch the sunrise from Haleakala Crater, or snorkel in Molokini Crater. Enjoy water sports, whale watching, and the island's relaxed vibes.", + "tags": ["Island", "Road trip", "Beach"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/maui.jpg" + }, + { + "ref": "milford-sound", + "name": "Milford Sound", + "country": "New Zealand", + "continent": "Oceania", + "knownFor": "Milford Sound, nestled in Fiordland National Park, offers breathtaking landscapes with towering cliffs, cascading waterfalls, and pristine waters. Visitors can cruise the fiord, kayak among the peaks, or hike the Milford Track for a multi-day adventure. The area is also known for its rich biodiversity, including dolphins, seals, and penguins.", + "tags": ["Secluded", "Hiking", "Wildlife watching"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/milford-sound.jpg" + }, + { + "ref": "moab", + "name": "Moab", + "country": "United States", + "continent": "North America", + "knownFor": "Moab is an adventurer's paradise, renowned for its stunning red rock formations and world-class outdoor activities. Hiking, mountain biking, and off-roading are popular pursuits in Arches and Canyonlands National Parks. The Colorado River offers white-water rafting and kayaking, while the surrounding desert landscapes provide endless opportunities for exploration and discovery.", + "tags": ["Desert", "Adventure sports", "Off-the-beaten-path"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/moab.jpg" + }, + { + "ref": "montenegro", + "name": "Montenegro", + "country": "Montenegro", + "continent": "Europe", + "knownFor": "Montenegro is a small Balkan country with a dramatic coastline, soaring mountains, and charming towns. Explore the Bay of Kotor, a UNESCO World Heritage Site, hike in Durmitor National Park, or relax on the beaches of Budva. Discover the historic cities of Kotor and Cetinje and enjoy the local seafood specialties.", + "tags": ["Beach", "Mountain", "Historic"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/montenegro.jpg" + }, + { + "ref": "mosel-valley", + "name": "Mosel Valley", + "country": "Germany", + "continent": "Europe", + "knownFor": "Embark on a journey through picturesque vineyards and charming villages along the Mosel River. Explore medieval castles, indulge in world-renowned Riesling wines, and savor authentic German cuisine. Hike or bike along scenic trails, or take a leisurely river cruise to soak in the breathtaking landscapes.", + "tags": ["River", "Wine tasting", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/mosel-valley.jpg" + }, + { + "ref": "myanmar", + "name": "Myanmar", + "country": "Myanmar", + "continent": "Asia", + "knownFor": "Myanmar (formerly Burma) is a country rich in culture and history, with ancient temples, stunning landscapes, and friendly people. Explore the iconic Shwedagon Pagoda in Yangon, visit the temple complex of Bagan, and cruise along the Irrawaddy River.", + "tags": ["Secluded", "Cultural experiences", "Off-the-beaten-path"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/myanmar.jpg" + }, + { + "ref": "mykonos", + "name": "Mykonos", + "country": "Greece", + "continent": "Europe", + "knownFor": "Mykonos is a glamorous Greek island famous for its whitewashed houses, iconic windmills, and vibrant nightlife. Visitors can relax on beautiful beaches, explore charming towns, and indulge in delicious Greek cuisine. Mykonos is also known for its luxury hotels, designer boutiques, and lively beach clubs.", + "tags": ["Island", "Beach", "Nightlife"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/mykonos.jpg" + }, + { + "ref": "nairobi", + "name": "Nairobi", + "country": "Kenya", + "continent": "Africa", + "knownFor": "Nairobi, the bustling capital of Kenya, serves as a gateway to the country's renowned safari destinations. Visit the David Sheldrick Elephant Orphanage, explore the Karen Blixen Museum, and experience the vibrant nightlife and cultural scene.", + "tags": ["City", "Wildlife watching", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/nairobi.jpg" + }, + { + "ref": "namibia", + "name": "Sossusvlei", + "country": "Namibia", + "continent": "Africa", + "knownFor": "Sossusvlei is a mesmerizing salt and clay pan surrounded by towering red sand dunes in the Namib Desert. Visitors can embark on scenic drives, climb the dunes for panoramic views, and capture breathtaking photos of the unique landscape. Sossusvlei is a photographer's paradise and a must-visit for desert enthusiasts.", + "tags": ["Desert", "Off-the-beaten-path", "Photography"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/namibia.jpg" + }, + { + "ref": "napa-valley", + "name": "Napa Valley", + "country": "United States", + "continent": "North America", + "knownFor": "Indulge in the world-renowned wine region of Napa Valley, California. Visit picturesque vineyards, sample exquisite wines, and savor gourmet cuisine at Michelin-starred restaurants. Explore charming towns like St. Helena and Yountville, or relax in luxurious spa resorts. Napa Valley offers a sophisticated and relaxing getaway for wine lovers and foodies.", + "tags": ["Wine tasting", "Food tours", "Luxury"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/napa-valley.jpg" + }, + { + "ref": "new-orleans", + "name": "New Orleans", + "country": "United States", + "continent": "North America", + "knownFor": "New Orleans is a vibrant city with a unique culture, known for its jazz music, Mardi Gras celebrations, and Creole cuisine. Explore the French Quarter, listen to live music on Frenchmen Street, or visit the historic cemeteries. Experience the nightlife, enjoy the local food, and immerse yourself in the spirit of New Orleans.", + "tags": ["City", "Cultural experiences", "Foodie"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/new-orleans.jpg" + }, + { + "ref": "new-zealand", + "name": "New Zealand", + "country": "New Zealand", + "continent": "Oceania", + "knownFor": "Embark on an adventure in New Zealand, a land of diverse landscapes, from snow-capped mountains and glaciers to geothermal wonders and lush rainforests. Hike through Fiordland National Park, explore the Waitomo Caves, and experience the thrill of bungee jumping and white-water rafting. Discover the Maori culture, indulge in delicious local cuisine, and marvel at the country's natural beauty.", + "tags": ["Adventure sports", "Hiking", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/new-zealand.jpg" + }, + { + "ref": "newfoundland", + "name": "Newfoundland", + "country": "Canada", + "continent": "North America", + "knownFor": "Newfoundland boasts rugged coastlines, charming fishing villages, and abundant wildlife. Hike along scenic trails, go whale watching, and experience the unique local culture. The island's friendly people and lively music scene add to its appeal.", + "tags": ["Island", "Wildlife watching", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/newfoundland.jpg" + }, + { + "ref": "nicaragua", + "name": "Nicaragua", + "country": "Nicaragua", + "continent": "North America", + "knownFor": "Nicaragua offers a diverse landscape of volcanoes, lakes, beaches, and rainforests. Visitors can enjoy adventure activities like surfing, volcano boarding, and zip-lining, as well as exploring colonial cities and experiencing the rich Nicaraguan culture.", + "tags": ["Adventure sports", "Beach", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/nicaragua.jpg" + }, + { + "ref": "northern-territory", + "name": "Kakadu National Park", + "country": "Australia", + "continent": "Oceania", + "knownFor": "Kakadu National Park is a UNESCO World Heritage site with diverse landscapes, including wetlands, sandstone escarpments, and ancient rock art sites. Visitors can explore Aboriginal culture, go bird watching, take boat tours through wetlands, and admire cascading waterfalls. Kakadu is a haven for wildlife, with crocodiles, wallabies, and numerous bird species.", + "tags": ["National Park", "Wildlife watching", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/northern-territory.jpg" + }, + { + "ref": "oaxaca", + "name": "Oaxaca", + "country": "Mexico", + "continent": "North America", + "knownFor": "Immerse yourself in the vibrant culture and rich history of Oaxaca, Mexico. Explore ancient Zapotec ruins, visit colorful markets filled with handicrafts, and experience traditional festivals. Sample the region's renowned cuisine, including mole sauces and mezcal. Oaxaca offers a unique and authentic travel experience for culture enthusiasts and foodies.", + "tags": ["Cultural experiences", "Food tours", "Historic"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/oaxaca.jpg" + }, + { + "ref": "okavango-delta", + "name": "Okavango Delta", + "country": "Botswana", + "continent": "Africa", + "knownFor": "The Okavango Delta, a vast inland delta in Botswana, is a haven for wildlife. Explore the waterways by mokoro (traditional canoe) and witness elephants, lions, hippos, and an array of bird species in their natural habitat.", + "tags": ["River", "Wildlife watching", "Adventure sports"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/okavango-delta.jpg" + }, + { + "ref": "oman", + "name": "Oman", + "country": "Oman", + "continent": "Asia", + "knownFor": "Oman, a country on the Arabian Peninsula, is a hidden gem with dramatic landscapes, ancient forts, and warm hospitality. Explore the vast deserts, swim in turquoise wadis, and hike through rugged mountains. Visit traditional souks, experience Bedouin culture, and discover the unique blend of modernity and tradition in this captivating destination.", + "tags": ["Desert", "Secluded", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/oman.jpg" + }, + { + "ref": "pagos-islands", + "name": "Galápagos Islands", + "country": "Ecuador", + "continent": "South America", + "knownFor": "A unique archipelago off the coast of Ecuador, the Galápagos Islands is a haven for wildlife enthusiasts. Encounter giant tortoises, marine iguanas, blue-footed boobies, and sea lions in their natural habitat. Snorkeling and diving opportunities reveal a vibrant underwater world.", + "tags": ["Island", "Wildlife watching", "Snorkeling"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/pagos-islands.jpg" + }, + { + "ref": "patagonia", + "name": "Patagonia", + "country": "Argentina and Chile", + "continent": "South America", + "knownFor": "Patagonia is a vast region at the southern tip of South America, known for its glaciers, mountains, and diverse wildlife. Visitors can embark on trekking adventures, witness the Perito Moreno Glacier, go kayaking, and spot penguins, whales, and other animals.", + "tags": ["Hiking", "Adventure sports", "Wildlife watching"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/patagonia.jpg" + }, + { + "ref": "peru", + "name": "Arequipa", + "country": "Peru", + "continent": "South America", + "knownFor": "Arequipa, known as the \"White City\" due to its buildings made of white volcanic stone, is a beautiful colonial city in southern Peru. Visitors can explore the historic center, visit the Santa Catalina Monastery, and enjoy stunning views of the surrounding volcanoes. Arequipa is also a gateway to the Colca Canyon, one of the deepest canyons in the world.", + "tags": ["City", "Historic", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/peru.jpg" + }, + { + "ref": "peruvian-amazon", + "name": "Peruvian Amazon", + "country": "Peru", + "continent": "South America", + "knownFor": "Venture into the heart of the Amazon rainforest, a biodiversity hotspot teeming with exotic wildlife and indigenous cultures. Embark on jungle treks, navigate the Amazon River, and spot unique flora and fauna. Experience the thrill of adventure travel and connect with nature in its purest form.", + "tags": ["Jungle", "Adventure sports", "Wildlife watching"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/peruvian-amazon.jpg" + }, + { + "ref": "phnom-penh", + "name": "Phnom Penh", + "country": "Cambodia", + "continent": "Asia", + "knownFor": "Immerse yourself in the vibrant culture and rich history of Phnom Penh, Cambodia's bustling capital. Visit the Royal Palace, explore ancient temples like Wat Phnom, and delve into the poignant history at the Tuol Sleng Genocide Museum. Experience the city's energetic nightlife and savor delicious Khmer cuisine.", + "tags": ["City", "Historic", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/phnom-penh.jpg" + }, + { + "ref": "phuket", + "name": "Phuket", + "country": "Thailand", + "continent": "Asia", + "knownFor": "Relax on the stunning beaches of Phuket, Thailand's largest island. Explore the turquoise waters of the Andaman Sea, go snorkeling or scuba diving among coral reefs, or visit nearby islands like Phi Phi. Enjoy the vibrant nightlife, indulge in Thai massages, and experience the local culture. Phuket offers a perfect blend of relaxation and adventure for beach lovers and those seeking a tropical escape.", + "tags": ["Beach", "Island", "Snorkeling"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/phuket.jpg" + }, + { + "ref": "positano", + "name": "Positano", + "country": "Italy", + "continent": "Europe", + "knownFor": "Nestled along the Amalfi Coast, Positano enchants with its colorful cliffside houses, pebble beaches, and luxury boutiques. Explore the narrow streets, indulge in delicious Italian cuisine, and soak up the romantic atmosphere.", + "tags": ["Beach", "Romantic", "Luxury"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/positano.jpg" + }, + { + "ref": "prague", + "name": "Prague", + "country": "Czech Republic", + "continent": "Europe", + "knownFor": "Prague, with its stunning architecture and rich history, is a fairytale city. Explore the Prague Castle, wander through the Old Town Square, and enjoy a traditional Czech meal. The city's charming atmosphere and affordable prices make it a popular destination.", + "tags": ["City", "Historic", "Sightseeing"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/prague.jpg" + }, + { + "ref": "puerto-rico", + "name": "Puerto Rico", + "country": "United States", + "continent": "North America", + "knownFor": "Puerto Rico is a Caribbean island with a rich history, vibrant culture, and stunning natural beauty. Explore the historic forts of Old San Juan, relax on the beaches of Vieques, or hike in El Yunque National Forest. Experience the bioluminescent bays, go salsa dancing, and enjoy the local cuisine.", + "tags": ["Island", "Beach", "Historic"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/puerto-rico.jpg" + }, + { + "ref": "punta-cana", + "name": "Punta Cana", + "country": "Dominican Republic", + "continent": "North America", + "knownFor": "Punta Cana is a renowned beach destination with pristine white sand, crystal-clear waters, and luxurious resorts. Enjoy water sports, golf, or simply unwind by the ocean and experience the vibrant Dominican culture.", + "tags": ["Beach", "All-inclusive", "Family-friendly"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/punta-cana.jpg" + }, + { + "ref": "quebec-city", + "name": "Quebec City", + "country": "Canada", + "continent": "North America", + "knownFor": "Experience the European charm of Quebec City, a UNESCO World Heritage Site. Wander through the historic Old Town with its cobblestone streets and fortified walls, visit the iconic Chateau Frontenac, and admire the stunning views of the St. Lawrence River. Quebec City offers a unique blend of history, culture, and French Canadian charm for a memorable getaway.", + "tags": ["City", "Historic", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/quebec-city.jpg" + }, + { + "ref": "queenstown", + "name": "Queenstown", + "country": "New Zealand", + "continent": "Oceania", + "knownFor": "Experience the adventure capital of the world in Queenstown, New Zealand. Surrounded by stunning mountains and Lake Wakatipu, this town offers everything from bungy jumping and skydiving to skiing and hiking.", + "tags": ["Adventure sports", "Lake", "Mountain"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/queenstown.jpg" + }, + { + "ref": "rajasthan", + "name": "Rajasthan", + "country": "India", + "continent": "Asia", + "knownFor": "Rajasthan, a state in northwestern India, is known for its opulent palaces, vibrant culture, and desert landscapes. Visitors can explore the cities of Jaipur, Jodhpur, and Udaipur, with their magnificent forts and palaces. The region also offers camel safaris, desert camping, and opportunities to experience traditional Rajasthani music and dance.", + "tags": ["Historic", "Desert", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/rajasthan.jpg" + }, + { + "ref": "reunion-island", + "name": "Réunion Island", + "country": "France", + "continent": "Africa", + "knownFor": "This volcanic island boasts dramatic landscapes, including Piton de la Fournaise, one of the world's most active volcanoes. Hike through lush rainforests, relax on black sand beaches, and experience the unique Creole culture.", + "tags": ["Secluded", "Hiking", "Tropical"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/reunion-island.jpg" + }, + { + "ref": "rio-de-janeiro", + "name": "Rio de Janeiro", + "country": "Brazil", + "continent": "South America", + "knownFor": "Rio de Janeiro is a vibrant city known for its stunning beaches, iconic landmarks like Christ the Redeemer and Sugarloaf Mountain, and lively Carnival celebrations. Visitors can enjoy sunbathing, surfing, and exploring the city's diverse neighborhoods, experiencing the infectious energy and cultural richness of Brazil.", + "tags": ["City", "Beach", "Party"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/rio-de-janeiro.jpg" + }, + { + "ref": "salar-de-uyuni", + "name": "Salar de Uyuni", + "country": "Bolivia", + "continent": "South America", + "knownFor": "Witness the surreal beauty of the world's largest salt flats, a mesmerizing landscape that transforms into a giant mirror during the rainy season. Capture incredible photos, explore unique rock formations, and visit nearby lagoons teeming with flamingos.", + "tags": ["Desert", "Off-the-beaten-path", "Photography"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/salar-de-uyuni.jpg" + }, + { + "ref": "san-diego", + "name": "San Diego", + "country": "United States", + "continent": "North America", + "knownFor": "San Diego, a sunny coastal city in Southern California, boasts beautiful beaches, a world-famous zoo, and a vibrant cultural scene. Explore Balboa Park, visit the historic Gaslamp Quarter, and enjoy water sports along the Pacific coast.", + "tags": ["City", "Beach", "Family-friendly"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/san-diego.jpg" + }, + { + "ref": "san-miguel-de-allende", + "name": "San Miguel de Allende", + "country": "Mexico", + "continent": "North America", + "knownFor": "This colonial city in central Mexico is a UNESCO World Heritage site with stunning Spanish architecture, vibrant cultural events, and a thriving arts scene. Visitors can explore historic churches, wander through cobbled streets lined with colorful houses, and enjoy delicious Mexican cuisine. San Miguel de Allende is also a popular destination for art classes and workshops.", + "tags": ["City", "Historic", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/san-miguel-de-allende.jpg" + }, + { + "ref": "san-sebastian", + "name": "San Sebastian", + "country": "Spain", + "continent": "Europe", + "knownFor": "Indulge in the culinary delights of this coastal paradise, renowned for its Michelin-starred restaurants and pintxos bars. Relax on the beautiful beaches, explore the charming Old Town, and hike or bike in the surrounding hills. Experience the vibrant culture and lively festivals of the Basque region.", + "tags": ["Beach", "City", "Foodie"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/san-sebastian.jpg" + }, + { + "ref": "santorini", + "name": "Santorini", + "country": "Greece", + "continent": "Europe", + "knownFor": "Santorini's iconic whitewashed villages perched on volcanic cliffs offer breathtaking views of the Aegean Sea. Explore charming Oia, visit ancient Akrotiri, and enjoy romantic sunsets with caldera views.", + "tags": ["Island", "Romantic", "Luxury"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/santorini.jpg" + }, + { + "ref": "sardinia", + "name": "Sardinia", + "country": "Italy", + "continent": "Europe", + "knownFor": "Experience the allure of Sardinia, a Mediterranean island boasting stunning coastlines, turquoise waters, and rugged mountains. Explore charming villages, ancient ruins, and secluded coves. Indulge in delicious Sardinian cuisine, hike scenic trails, and discover the island's rich history and culture.", + "tags": ["Island", "Beach", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/sardinia.jpg" + }, + { + "ref": "scotland", + "name": "Scotland", + "country": "United Kingdom", + "continent": "Europe", + "knownFor": "Scotland is known for its dramatic landscapes, historic castles, and vibrant cities. Explore the Scottish Highlands, visit Edinburgh Castle, and sample Scotch whisky. The country's rich history and culture, along with its friendly people, make it a captivating destination.", + "tags": ["Mountain", "Historic", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/scotland.jpg" + }, + { + "ref": "scottish-highlands", + "name": "Scottish Highlands", + "country": "Scotland", + "continent": "Europe", + "knownFor": "The Scottish Highlands, a mountainous region in northern Scotland, is renowned for its rugged beauty, ancient castles, and rich history. Visitors can explore the dramatic landscapes through hiking, climbing, and scenic drives, or visit historic sites like Loch Ness and Eilean Donan Castle. The region is also famous for its whisky distilleries and traditional Highland culture.", + "tags": ["Mountain", "Historic", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/scottish-highlands.jpg" + }, + { + "ref": "seoul", + "name": "Seoul", + "country": "South Korea", + "continent": "Asia", + "knownFor": "Seoul is a vibrant metropolis blending modern skyscrapers with ancient palaces and temples. Visitors can explore historical landmarks, experience K-pop culture, indulge in delicious Korean cuisine, and enjoy the city's bustling nightlife.", + "tags": ["City", "Cultural experiences", "Nightlife"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/seoul.jpg" + }, + { + "ref": "serengeti-national-park", + "name": "Serengeti National Park", + "country": "Tanzania", + "continent": "Africa", + "knownFor": "Serengeti National Park is renowned for its incredible wildlife and the annual Great Migration, where millions of wildebeest, zebras, and other animals traverse the plains in search of fresh grazing. Visitors can embark on thrilling safari adventures, witness predator-prey interactions, and marvel at the diversity of the African savanna.", + "tags": ["Wildlife watching", "Safari", "Adventure"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/serengeti-national-park.jpg" + }, + { + "ref": "seville", + "name": "Seville", + "country": "Spain", + "continent": "Europe", + "knownFor": "Seville, the vibrant capital of Andalusia, is renowned for its flamenco dancing, Moorish architecture, and lively tapas bars. Explore the stunning Alcázar palace, witness a passionate flamenco performance, and wander through the charming Santa Cruz district.", + "tags": ["City", "Cultural experiences", "Food tours"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/seville.jpg" + }, + { + "ref": "singapore", + "name": "Singapore", + "country": "Singapore", + "continent": "Asia", + "knownFor": "Experience a vibrant mix of cultures, cutting-edge architecture, and lush green spaces in this dynamic city-state. Discover futuristic Gardens by the Bay, indulge in diverse culinary delights, and explore world-class shopping and entertainment options.", + "tags": ["City", "Cultural experiences", "Foodie"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/singapore.jpg" + }, + { + "ref": "slovenia", + "name": "Slovenia", + "country": "Slovenia", + "continent": "Europe", + "knownFor": "Slovenia is a small country in Central Europe with stunning alpine scenery, charming towns, and a rich history. Visit Lake Bled, a picturesque lake with a church on an island, explore the Postojna Cave, or hike in Triglav National Park. Discover the capital city of Ljubljana, enjoy the local wines, and experience the Slovenian hospitality.", + "tags": ["Lake", "Mountain", "City"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/slovenia.jpg" + }, + { + "ref": "sri-lanka", + "name": "Sri Lanka", + "country": "Sri Lanka", + "continent": "Asia", + "knownFor": "Sri Lanka is an island nation off the southern coast of India, known for its ancient ruins, beautiful beaches, and diverse wildlife. Visit the Sigiriya rock fortress, relax on the beaches of Bentota, or go on a safari in Yala National Park. Explore the tea plantations, experience the local culture, and enjoy the delicious Sri Lankan cuisine.", + "tags": ["Island", "Beach", "Wildlife watching"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/sri-lanka.jpg" + }, + { + "ref": "svalbard", + "name": "Svalbard", + "country": "Norway", + "continent": "Europe", + "knownFor": "Svalbard, an Arctic archipelago under Norwegian sovereignty, is a remote and captivating destination for adventurers and nature enthusiasts. Witness glaciers, fjords, and ice-covered landscapes. Spot polar bears, walruses, and reindeer, and experience the midnight sun or the northern lights. Svalbard offers a unique opportunity to explore the Arctic wilderness.", + "tags": ["Off-the-beaten-path", "Wildlife watching", "Winter destination"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/svalbard.jpg" + }, + { + "ref": "swiss-alps", + "name": "Swiss Alps", + "country": "Switzerland", + "continent": "Europe", + "knownFor": "Discover the breathtaking beauty of the Swiss Alps, a paradise for outdoor enthusiasts. Hike through scenic mountain trails, go skiing or snowboarding in world-class resorts, or take a scenic train ride through the mountains. Enjoy the fresh air, charming villages, and stunning scenery. The Swiss Alps offer an unforgettable experience for nature lovers and adventure seekers.", + "tags": ["Mountain", "Hiking", "Skiing"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/swiss-alps.jpg" + }, + { + "ref": "tasmania", + "name": "Tasmania", + "country": "Australia", + "continent": "Oceania", + "knownFor": "Discover the wild beauty of Tasmania, an island state off the coast of Australia. Explore Cradle Mountain-Lake St Clair National Park, with its rugged mountains and pristine lakes. Visit Port Arthur Historic Site, a former penal colony, or encounter unique wildlife like Tasmanian devils and quolls.", + "tags": ["Island", "Hiking", "Wildlife watching"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/tasmania.jpg" + }, + { + "ref": "tel-aviv", + "name": "Tel Aviv", + "country": "Israel", + "continent": "Asia", + "knownFor": "Experience the vibrant and cosmopolitan city of Tel Aviv, known for its beaches, Bauhaus architecture, and thriving nightlife. Relax on the sandy shores of the Mediterranean Sea, explore the trendy neighborhoods of Neve Tzedek and Florentin, and enjoy the city's diverse culinary scene. Tel Aviv offers a perfect blend of beach relaxation, cultural experiences, and exciting nightlife.", + "tags": ["City", "Beach", "Nightlife"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/tel-aviv.jpg" + }, + { + "ref": "trans-siberian-railway", + "name": "Trans-Siberian Railway", + "country": "Russia", + "continent": "Asia", + "knownFor": "The Trans-Siberian Railway is the longest railway line in the world, stretching over 9,000 kilometers from Moscow to Vladivostok. This epic journey offers travelers a unique opportunity to experience the vastness and diversity of Russia, passing through bustling cities, remote villages, and stunning natural landscapes.", + "tags": ["Adventure sports", "Cultural experiences", "Long-haul vacation"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/trans-siberian-railway.jpg" + }, + { + "ref": "transylvania", + "name": "Transylvania", + "country": "Romania", + "continent": "Europe", + "knownFor": "Transylvania, a region in Romania, is famous for its medieval towns, fortified churches, and stunning Carpathian Mountain scenery. Visitors can explore Bran Castle, associated with the Dracula legend, visit historic cities like Brasov and Sibiu, and hike or ski in the mountains. The region also offers opportunities to experience traditional Romanian culture and cuisine.", + "tags": ["Historic", "Mountain", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/transylvania.jpg" + }, + { + "ref": "tulum", + "name": "Tulum", + "country": "Mexico", + "continent": "North America", + "knownFor": "Tulum seamlessly blends ancient Mayan history with modern bohemian vibes. Visitors can explore the Tulum Archaeological Site, perched on cliffs overlooking the Caribbean Sea, and discover well-preserved ruins. Pristine beaches offer relaxation and water activities, while the town's eco-chic atmosphere provides yoga retreats, wellness centers, and sustainable dining options.", + "tags": ["Beach", "Cultural experiences", "Wellness retreats"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/tulum.jpg" + }, + { + "ref": "turkish-riviera", + "name": "Turkish Riviera", + "country": "Turkey", + "continent": "Asia", + "knownFor": "The Turkish Riviera offers a mix of ancient ruins, stunning beaches, and turquoise waters. Explore the historical sites of Ephesus and Antalya, relax on the sandy shores, and enjoy water sports like sailing and snorkeling. The region's delicious cuisine and affordable prices add to its appeal.", + "tags": ["Beach", "Historic", "Sightseeing"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/turkish-riviera.jpg" + }, + { + "ref": "tuscany", + "name": "Tuscany", + "country": "Italy", + "continent": "Europe", + "knownFor": "Explore the rolling hills and vineyards of Tuscany, indulging in wine tastings and farm-to-table cuisine. Discover charming medieval towns, Renaissance art, and historic cities like Florence and Siena. Immerse yourself in the region's rich culture and art scene, or simply relax and soak up the idyllic scenery.", + "tags": ["Cultural experiences", "Food tours", "Wine tasting"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/tuscany.jpg" + }, + { + "ref": "us-virgin-islands", + "name": "US Virgin Islands", + "country": "United States", + "continent": "North America", + "knownFor": "Escape to the Caribbean paradise of the US Virgin Islands, where you can relax on pristine beaches, explore coral reefs, and experience the laid-back island lifestyle. Visit the historic towns of Charlotte Amalie and Christiansted, go sailing or snorkeling in crystal-clear waters, or simply soak up the sun. The US Virgin Islands offer a perfect tropical getaway for beach lovers and those seeking a relaxing escape.", + "tags": ["Island", "Beach", "Relaxing"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/us-virgin-islands.jpg" + }, + { + "ref": "vancouver-island", + "name": "Vancouver Island", + "country": "Canada", + "continent": "North America", + "knownFor": "Vancouver Island, located off Canada's Pacific coast, is a haven for nature lovers and adventure seekers. Explore the rugged coastline, ancient rainforests, and snow-capped mountains. Go whale watching, kayaking, or surfing, and discover charming towns and vibrant cities like Victoria. Vancouver Island offers a perfect blend of wilderness and urban experiences.", + "tags": ["Island", "Adventure sports", "Wildlife watching"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/vancouver-island.jpg" + }, + { + "ref": "vienna", + "name": "Vienna", + "country": "Austria", + "continent": "Europe", + "knownFor": "Step into the imperial city of Vienna, where grand palaces, historical landmarks, and elegant cafes exude charm and sophistication. Explore museums, art galleries, and renowned opera houses, or visit Schönbrunn Palace and delve into Habsburg history. Enjoy classical music concerts, indulge in Viennese pastries, and experience the city's rich cultural heritage.", + "tags": ["City", "Historic", "Cultural experiences"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/vienna.jpg" + }, + { + "ref": "vietnam", + "name": "Vietnam", + "country": "Vietnam", + "continent": "Asia", + "knownFor": "Vietnam offers a rich tapestry of culture, history, and natural beauty. Explore the bustling streets of Hanoi, cruise through the scenic Ha Long Bay, and discover the ancient town of Hoi An. From delicious street food to stunning landscapes, Vietnam is a destination that will captivate your senses.", + "tags": ["Cultural experiences", "Food tours", "Sightseeing"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/vietnam.jpg" + }, + { + "ref": "western-australia", + "name": "Western Australia", + "country": "Australia", + "continent": "Australia", + "knownFor": "Western Australia, the largest state in Australia, is a land of vast landscapes, stunning coastlines, and unique wildlife. Explore the vibrant city of Perth, swim with whale sharks at Ningaloo Reef, and discover the ancient rock formations of the Kimberley region. From wineries to deserts, Western Australia offers a diverse and unforgettable experience.", + "tags": ["Beach", "Road trip destination", "Wildlife watching"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/western-australia.jpg" + }, + { + "ref": "yellowstone-national-park", + "name": "Yellowstone National Park", + "country": "United States", + "continent": "North America", + "knownFor": "Witness the geothermal wonders of Yellowstone, with its geysers, hot springs, and mudpots. Observe abundant wildlife, including bison, elk, and wolves. Explore the Grand Canyon of the Yellowstone, go hiking or camping, and enjoy winter sports.", + "tags": ["National Park", "Wildlife watching", "Hiking"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/yellowstone-national-park.jpg" + }, + { + "ref": "yosemite-national-park", + "name": "Yosemite National Park", + "country": "United States", + "continent": "North America", + "knownFor": "Yosemite National Park, located in California's Sierra Nevada mountains, is renowned for its towering granite cliffs, giant sequoia trees, and stunning waterfalls. Visitors can enjoy hiking, camping, rock climbing, and exploring the park's natural wonders, including Yosemite Valley, Half Dome, and Glacier Point.", + "tags": ["Mountain", "Hiking", "Sightseeing"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/yosemite-national-park.jpg" + }, + { + "ref": "yucatan-peninsula", + "name": "Yucatan Peninsula", + "country": "Mexico", + "continent": "North America", + "knownFor": "Discover ancient Mayan ruins, explore vibrant coral reefs, and relax on pristine beaches in the Yucatan Peninsula. Dive into cenotes, swim with whale sharks, and experience the rich culture and history of this captivating region.", + "tags": ["Beach", "Historic", "Scuba diving"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/yucatan-peninsula.jpg" + }, + { + "ref": "zanzibar", + "name": "Zanzibar", + "country": "Tanzania", + "continent": "Africa", + "knownFor": "Zanzibar is a Tanzanian archipelago off the coast of East Africa, known for its stunning beaches, turquoise waters, and historical Stone Town. Visitors can relax on the beach, explore the UNESCO-listed Stone Town, go diving or snorkeling, and experience the island's unique blend of African, Arab, and European influences.", + "tags": ["Beach", "Cultural experiences", "Scuba diving"], + "imageUrl": "https://storage.googleapis.com/tripedia-images/destinations/zanzibar.jpg" + } +] diff --git a/compass_app/app/devtools_options.yaml b/compass_app/app/devtools_options.yaml new file mode 100644 index 000000000..fa0b357c4 --- /dev/null +++ b/compass_app/app/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/compass_app/ios/.gitignore b/compass_app/app/ios/.gitignore similarity index 100% rename from compass_app/ios/.gitignore rename to compass_app/app/ios/.gitignore diff --git a/compass_app/ios/Flutter/AppFrameworkInfo.plist b/compass_app/app/ios/Flutter/AppFrameworkInfo.plist similarity index 100% rename from compass_app/ios/Flutter/AppFrameworkInfo.plist rename to compass_app/app/ios/Flutter/AppFrameworkInfo.plist diff --git a/compass_app/ios/Flutter/Debug.xcconfig b/compass_app/app/ios/Flutter/Debug.xcconfig similarity index 100% rename from compass_app/ios/Flutter/Debug.xcconfig rename to compass_app/app/ios/Flutter/Debug.xcconfig diff --git a/compass_app/ios/Flutter/Release.xcconfig b/compass_app/app/ios/Flutter/Release.xcconfig similarity index 100% rename from compass_app/ios/Flutter/Release.xcconfig rename to compass_app/app/ios/Flutter/Release.xcconfig diff --git a/compass_app/ios/Runner.xcodeproj/project.pbxproj b/compass_app/app/ios/Runner.xcodeproj/project.pbxproj similarity index 100% rename from compass_app/ios/Runner.xcodeproj/project.pbxproj rename to compass_app/app/ios/Runner.xcodeproj/project.pbxproj diff --git a/compass_app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/compass_app/app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from compass_app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to compass_app/app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/compass_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/compass_app/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from compass_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to compass_app/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/compass_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/compass_app/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from compass_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to compass_app/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/compass_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/compass_app/app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme similarity index 100% rename from compass_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme rename to compass_app/app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme diff --git a/compass_app/ios/Runner.xcworkspace/contents.xcworkspacedata b/compass_app/app/ios/Runner.xcworkspace/contents.xcworkspacedata similarity index 100% rename from compass_app/ios/Runner.xcworkspace/contents.xcworkspacedata rename to compass_app/app/ios/Runner.xcworkspace/contents.xcworkspacedata diff --git a/compass_app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/compass_app/app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from compass_app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to compass_app/app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/compass_app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/compass_app/app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from compass_app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to compass_app/app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/compass_app/ios/Runner/AppDelegate.swift b/compass_app/app/ios/Runner/AppDelegate.swift similarity index 100% rename from compass_app/ios/Runner/AppDelegate.swift rename to compass_app/app/ios/Runner/AppDelegate.swift diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png rename to compass_app/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/compass_app/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json rename to compass_app/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json diff --git a/compass_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/compass_app/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png rename to compass_app/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png diff --git a/compass_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/compass_app/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png rename to compass_app/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/compass_app/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png rename to compass_app/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png diff --git a/compass_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/compass_app/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md similarity index 100% rename from compass_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md rename to compass_app/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md diff --git a/compass_app/ios/Runner/Base.lproj/LaunchScreen.storyboard b/compass_app/app/ios/Runner/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from compass_app/ios/Runner/Base.lproj/LaunchScreen.storyboard rename to compass_app/app/ios/Runner/Base.lproj/LaunchScreen.storyboard diff --git a/compass_app/ios/Runner/Base.lproj/Main.storyboard b/compass_app/app/ios/Runner/Base.lproj/Main.storyboard similarity index 100% rename from compass_app/ios/Runner/Base.lproj/Main.storyboard rename to compass_app/app/ios/Runner/Base.lproj/Main.storyboard diff --git a/compass_app/ios/Runner/Info.plist b/compass_app/app/ios/Runner/Info.plist similarity index 100% rename from compass_app/ios/Runner/Info.plist rename to compass_app/app/ios/Runner/Info.plist diff --git a/compass_app/ios/Runner/Runner-Bridging-Header.h b/compass_app/app/ios/Runner/Runner-Bridging-Header.h similarity index 100% rename from compass_app/ios/Runner/Runner-Bridging-Header.h rename to compass_app/app/ios/Runner/Runner-Bridging-Header.h diff --git a/compass_app/ios/RunnerTests/RunnerTests.swift b/compass_app/app/ios/RunnerTests/RunnerTests.swift similarity index 100% rename from compass_app/ios/RunnerTests/RunnerTests.swift rename to compass_app/app/ios/RunnerTests/RunnerTests.swift diff --git a/compass_app/app/lib/config/dependencies.dart b/compass_app/app/lib/config/dependencies.dart new file mode 100644 index 000000000..0d9f29b54 --- /dev/null +++ b/compass_app/app/lib/config/dependencies.dart @@ -0,0 +1,14 @@ +import '../data/repositories/destination/destination_repository.dart'; +import '../data/repositories/destination/destination_repository_local.dart'; +import 'package:provider/single_child_widget.dart'; +import 'package:provider/provider.dart'; + +/// Configure dependencies as a list of Providers +List get providers { + // List of Providers + return [ + Provider.value( + value: DestinationRepositoryLocal() as DestinationRepository, + ), + ]; +} diff --git a/compass_app/app/lib/data/models/destination.dart b/compass_app/app/lib/data/models/destination.dart new file mode 100644 index 000000000..d22b560c5 --- /dev/null +++ b/compass_app/app/lib/data/models/destination.dart @@ -0,0 +1,50 @@ +/// Model class for Destination data +class Destination { + Destination({ + required this.ref, + required this.name, + required this.country, + required this.continent, + required this.knownFor, + required this.tags, + required this.imageUrl, + }); + + /// e.g. 'alaska' + final String ref; + + /// e.g. 'Alaska' + final String name; + + /// e.g. 'United States' + final String country; + + /// e.g. 'North America' + final String continent; + + /// e.g. 'Alaska is a haven for outdoor enthusiasts ...' + final String knownFor; + + /// e.g. ['Mountain', 'Off-the-beaten-path', 'Wildlife watching'] + final List tags; + + /// e.g. 'https://storage.googleapis.com/tripedia-images/destinations/alaska.jpg' + final String imageUrl; + + @override + String toString() { + return 'Destination{ref: $ref, name: $name, country: $country, continent: $continent, knownFor: $knownFor, tags: $tags, imageUrl: $imageUrl}'; + } + + factory Destination.fromJson(Map json) { + return Destination( + ref: json['ref'] as String, + name: json['name'] as String, + country: json['country'] as String, + continent: json['continent'] as String, + knownFor: json['knownFor'] as String, + tags: (json['tags'] as List).map((e) => e as String).toList(), + imageUrl: json['imageUrl'] as String, + ); + } +} diff --git a/compass_app/app/lib/data/repositories/destination/destination_repository.dart b/compass_app/app/lib/data/repositories/destination/destination_repository.dart new file mode 100644 index 000000000..01bba9181 --- /dev/null +++ b/compass_app/app/lib/data/repositories/destination/destination_repository.dart @@ -0,0 +1,8 @@ +import '../../../utils/result.dart'; +import '../../models/destination.dart'; + +/// Data source with all possible destinations +abstract class DestinationRepository { + /// Get complete list of destinations + Future>> getDestinations(); +} diff --git a/compass_app/app/lib/data/repositories/destination/destination_repository_local.dart b/compass_app/app/lib/data/repositories/destination/destination_repository_local.dart new file mode 100644 index 000000000..5d587c982 --- /dev/null +++ b/compass_app/app/lib/data/repositories/destination/destination_repository_local.dart @@ -0,0 +1,35 @@ +import 'dart:convert'; + +import '../../../utils/result.dart'; +import '../../models/destination.dart'; +import 'destination_repository.dart'; + +import 'package:flutter/services.dart' show rootBundle; + +/// Local implementation of DestinationRepository +/// Uses data from assets folder +class DestinationRepositoryLocal implements DestinationRepository { + /// Obtain list of destinations from local assets + @override + Future>> getDestinations() async { + try { + final localData = await _loadAsset(); + final list = _parse(localData); + return Result.ok(list); + } on Exception catch (error) { + return Result.error(error); + } + } + + Future _loadAsset() async { + return await rootBundle.loadString('assets/destinations.json'); + } + + List _parse(String localData) { + final parsed = (jsonDecode(localData) as List).cast>(); + + return parsed + .map((json) => Destination.fromJson(json)) + .toList(); + } +} diff --git a/compass_app/app/lib/data/services/placeholder b/compass_app/app/lib/data/services/placeholder new file mode 100644 index 000000000..e69de29bb diff --git a/compass_app/app/lib/main.dart b/compass_app/app/lib/main.dart new file mode 100644 index 000000000..4950a914c --- /dev/null +++ b/compass_app/app/lib/main.dart @@ -0,0 +1,30 @@ +import 'config/dependencies.dart'; +import 'ui/core/themes/theme.dart'; +import 'routing/router.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +void main() { + runApp( + MultiProvider( + // Loading the default providers + // NOTE: We can load different configurations e.g. fakes + providers: providers, + child: const MainApp(), + ), + ); +} + +class MainApp extends StatelessWidget { + const MainApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp.router( + theme: AppTheme.lightTheme, + darkTheme: AppTheme.darkTheme, + themeMode: ThemeMode.system, + routerConfig: router, + ); + } +} diff --git a/compass_app/app/lib/routing/router.dart b/compass_app/app/lib/routing/router.dart new file mode 100644 index 000000000..ddc1d0935 --- /dev/null +++ b/compass_app/app/lib/routing/router.dart @@ -0,0 +1,21 @@ +import '../ui/results/widgets/results_screen.dart'; +import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; + +import '../ui/results/view_models/results_viewmodel.dart'; + +/// Top go_router entry point +final router = GoRouter( + initialLocation: '/results', + routes: [ + GoRoute( + path: '/results', + builder: (context, state) { + final viewModel = ResultsViewModel( + destinationRepository: context.read(), + ); + return ResultsScreen(viewModel: viewModel); + }, + ), + ], +); diff --git a/compass_app/app/lib/ui/core/themes/colors.dart b/compass_app/app/lib/ui/core/themes/colors.dart new file mode 100644 index 000000000..48440a362 --- /dev/null +++ b/compass_app/app/lib/ui/core/themes/colors.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; + +class AppColors { + static const black1 = Color(0xFF101010); + static const white1 = Color(0xFFFFF7FA); + static const grey1 = Color(0xFFF2F2F2); + static const grey2 = Color(0xFF4D4D4D); + static const whiteTransparent = + Color(0x4DFFFFFF); // Figma rgba(255, 255, 255, 0.3) + static const blackTransparent = + Color(0x4D000000); // Figma rgba(255, 255, 255, 0.3) + + static const lightColorScheme = ColorScheme( + brightness: Brightness.light, + primary: AppColors.black1, + onPrimary: AppColors.white1, + secondary: AppColors.black1, + onSecondary: AppColors.white1, + surface: Colors.white, + onSurface: AppColors.black1, + error: Colors.red, + onError: Colors.white, + ); + + static const darkColorScheme = ColorScheme( + brightness: Brightness.dark, + primary: AppColors.white1, + onPrimary: AppColors.black1, + secondary: AppColors.white1, + onSecondary: AppColors.black1, + surface: AppColors.black1, + onSurface: Colors.white, + error: Colors.red, + onError: Colors.white, + ); +} diff --git a/compass_app/app/lib/ui/core/themes/text_styles.dart b/compass_app/app/lib/ui/core/themes/text_styles.dart new file mode 100644 index 000000000..daeb5f834 --- /dev/null +++ b/compass_app/app/lib/ui/core/themes/text_styles.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +// TODO: Maybe the text styles here should be moved to the respective widgets +class TextStyles { + // Note: original Figma file uses Nikkei Maru + // which is not available on GoogleFonts + // Note: Card title theme doesn't change based on light/dark mode + static final cardTitleStyle = GoogleFonts.rubik( + textStyle: const TextStyle( + fontWeight: FontWeight.w800, + fontSize: 15.0, + color: Colors.white, + letterSpacing: 1, + shadows: [ + // Helps to read the text a bit better + Shadow( + blurRadius: 3.0, + color: Colors.black, + ) + ], + ), + ); +} diff --git a/compass_app/app/lib/ui/core/themes/theme.dart b/compass_app/app/lib/ui/core/themes/theme.dart new file mode 100644 index 000000000..e9954bc76 --- /dev/null +++ b/compass_app/app/lib/ui/core/themes/theme.dart @@ -0,0 +1,27 @@ +import 'colors.dart'; +import '../ui/tag_chip.dart'; +import 'package:flutter/material.dart'; + +class AppTheme { + static ThemeData lightTheme = ThemeData( + useMaterial3: true, + colorScheme: AppColors.lightColorScheme, + extensions: [ + TagChipTheme( + chipColor: AppColors.whiteTransparent, + onChipColor: Colors.white, + ), + ], + ); + + static ThemeData darkTheme = ThemeData( + useMaterial3: true, + colorScheme: AppColors.darkColorScheme, + extensions: [ + TagChipTheme( + chipColor: AppColors.blackTransparent, + onChipColor: Colors.white, + ), + ], + ); +} diff --git a/compass_app/app/lib/ui/core/ui/tag_chip.dart b/compass_app/app/lib/ui/core/ui/tag_chip.dart new file mode 100644 index 000000000..ef084c9af --- /dev/null +++ b/compass_app/app/lib/ui/core/ui/tag_chip.dart @@ -0,0 +1,127 @@ +import 'dart:ui'; + +import '../themes/colors.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +class TagChip extends StatelessWidget { + const TagChip({ + super.key, + required this.tag, + }); + + final String tag; + + @override + Widget build(BuildContext context) { + return ClipRRect( + borderRadius: BorderRadius.circular(10.0), + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 3, sigmaY: 3), + child: DecoratedBox( + decoration: BoxDecoration( + color: Theme.of(context).extension()?.chipColor ?? + AppColors.whiteTransparent, + ), + child: SizedBox( + height: 20.0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 6.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + _iconFrom(tag), + color: Theme.of(context) + .extension() + ?.onChipColor, + size: 10, + ), + const SizedBox(width: 4), + Text( + tag, + textAlign: TextAlign.center, + style: _textStyle(context), + ), + ], + ), + ), + ), + ), + ), + ); + } + + IconData? _iconFrom(String tag) { + return switch (tag) { + 'Adventure sports' => Icons.kayaking_outlined, + 'Beach' => Icons.beach_access_outlined, + 'City' => Icons.location_city_outlined, + 'Cultural experiences' => Icons.museum_outlined, + 'Foodie' || 'Food tours' => Icons.restaurant, + 'Hiking' => Icons.hiking, + 'Historic' => Icons.menu_book_outlined, + 'Island' || 'Coastal' || 'Lake' || 'River' => Icons.water, + 'Luxury' => Icons.attach_money_outlined, + 'Mountain' || 'Wildlife watching' => Icons.landscape_outlined, + 'Nightlife' => Icons.local_bar_outlined, + 'Off-the-beaten-path' => Icons.do_not_step_outlined, + 'Romantic' => Icons.favorite_border_outlined, + 'Rural' => Icons.agriculture_outlined, + 'Secluded' => Icons.church_outlined, + 'Sightseeing' => Icons.attractions_outlined, + 'Skiing' => Icons.downhill_skiing_outlined, + 'Wine tasting' => Icons.wine_bar_outlined, + 'Winter destination' => Icons.ac_unit, + _ => Icons.label_outlined, + }; + } + + // Note: original Figma file uses Google Sans + // which is not available on GoogleFonts + _textStyle(BuildContext context) => GoogleFonts.openSans( + textStyle: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 10, + color: Theme.of(context).extension()?.onChipColor ?? + Colors.white, + textBaseline: TextBaseline.alphabetic, + ), + ); +} + +class TagChipTheme extends ThemeExtension { + final Color chipColor; + final Color onChipColor; + + TagChipTheme({ + required this.chipColor, + required this.onChipColor, + }); + + @override + ThemeExtension copyWith({ + Color? chipColor, + Color? onChipColor, + }) { + return TagChipTheme( + chipColor: chipColor ?? this.chipColor, + onChipColor: onChipColor ?? this.onChipColor, + ); + } + + @override + ThemeExtension lerp( + covariant ThemeExtension other, + double t, + ) { + if (other is! TagChipTheme) { + return this; + } + return TagChipTheme( + chipColor: Color.lerp(chipColor, other.chipColor, t) ?? chipColor, + onChipColor: Color.lerp(onChipColor, other.onChipColor, t) ?? onChipColor, + ); + } +} diff --git a/compass_app/app/lib/ui/results/view_models/results_viewmodel.dart b/compass_app/app/lib/ui/results/view_models/results_viewmodel.dart new file mode 100644 index 000000000..7057afbe8 --- /dev/null +++ b/compass_app/app/lib/ui/results/view_models/results_viewmodel.dart @@ -0,0 +1,65 @@ +import '../../../data/repositories/destination/destination_repository.dart'; +import '../../../utils/result.dart'; +import '../../../data/models/destination.dart'; +import 'package:flutter/cupertino.dart'; + +/// Results screen view model +/// Based on https://docs.flutter.dev/get-started/fwe/state-management#using-mvvm-for-your-applications-architecture +class ResultsViewModel extends ChangeNotifier { + ResultsViewModel({ + required DestinationRepository destinationRepository, + }) : _destinationRepository = destinationRepository { + // Preload a search result + search(continent: 'Europe'); + } + + final DestinationRepository _destinationRepository; + + // Setters are private + List _destinations = []; + bool _loading = false; + String? _continent; + + /// List of destinations, may be empty but never null + List get destinations => _destinations; + + /// Loading state + bool get loading => _loading; + + /// Return a formatted String with all the filter options + String get filters => _continent ?? ''; + + /// Perform search + Future search({String? continent}) async { + // Set loading state and notify the view + _loading = true; + _continent = continent; + notifyListeners(); + + final result = await _destinationRepository.getDestinations(); + // Set loading state to false + _loading = false; + switch (result) { + case Ok(): + { + // If the result is Ok, update the list of destinations + _destinations = result.value + .where((destination) => _filter(destination, continent)) + .toList(); + } + case Error(): + { + // TODO: Handle error + // ignore: avoid_print + print(result.error); + } + } + + // After finish loading results, notify the view + notifyListeners(); + } + + bool _filter(Destination destination, String? continent) { + return (continent == null || destination.continent == continent); + } +} diff --git a/compass_app/app/lib/ui/results/widgets/result_card.dart b/compass_app/app/lib/ui/results/widgets/result_card.dart new file mode 100644 index 000000000..98f7a571a --- /dev/null +++ b/compass_app/app/lib/ui/results/widgets/result_card.dart @@ -0,0 +1,57 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import '../../core/themes/text_styles.dart'; +import '../../core/ui/tag_chip.dart'; +import '../../../data/models/destination.dart'; + +class ResultCard extends StatelessWidget { + const ResultCard({ + super.key, + required this.destination, + }); + + final Destination destination; + + @override + Widget build(BuildContext context) { + return ClipRRect( + borderRadius: BorderRadius.circular(10.0), + // TODO: Improve image loading and caching + child: Stack( + fit: StackFit.expand, + children: [ + CachedNetworkImage( + imageUrl: destination.imageUrl, + fit: BoxFit.fitHeight, + errorWidget: (context, url, error) => const Icon(Icons.error), + ), + Positioned( + bottom: 12.0, + left: 12.0, + right: 12.0, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + destination.name.toUpperCase(), + style: TextStyles.cardTitleStyle, + ), + const SizedBox( + height: 6, + ), + Wrap( + spacing: 4.0, + runSpacing: 4.0, + direction: Axis.horizontal, + children: + destination.tags.map((e) => TagChip(tag: e)).toList(), + ), + ], + ), + ) + ], + ), + ); + } +} diff --git a/compass_app/app/lib/ui/results/widgets/results_screen.dart b/compass_app/app/lib/ui/results/widgets/results_screen.dart new file mode 100644 index 000000000..127f7756a --- /dev/null +++ b/compass_app/app/lib/ui/results/widgets/results_screen.dart @@ -0,0 +1,105 @@ +import '../../core/themes/colors.dart'; +import '../view_models/results_viewmodel.dart'; +import 'result_card.dart'; +import 'package:flutter/material.dart'; + +class ResultsScreen extends StatelessWidget { + const ResultsScreen({ + super.key, + required this.viewModel, + }); + + final ResultsViewModel viewModel; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: ListenableBuilder( + listenable: viewModel, + builder: (context, child) { + if (viewModel.loading) { + return const Center(child: CircularProgressIndicator()); + } + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0), + child: CustomScrollView( + slivers: [ + _Search(viewModel: viewModel), + _Grid(viewModel: viewModel), + ], + ), + ); + }, + ), + ); + } +} + +class _Grid extends StatelessWidget { + const _Grid({ + required this.viewModel, + }); + + final ResultsViewModel viewModel; + + @override + Widget build(BuildContext context) { + return SliverGrid( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 8.0, + mainAxisSpacing: 8.0, + childAspectRatio: 182 / 222, + ), + delegate: SliverChildBuilderDelegate( + (context, index) { + return ResultCard( + key: ValueKey(viewModel.destinations[index].ref), + destination: viewModel.destinations[index], + ); + }, + childCount: viewModel.destinations.length, + ), + ); + } +} + +class _Search extends StatelessWidget { + const _Search({ + required this.viewModel, + }); + + final ResultsViewModel viewModel; + + @override + Widget build(BuildContext context) { + return SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.only(top: 60, bottom: 24), + child: Container( + height: 64, + decoration: BoxDecoration( + border: Border.all(color: AppColors.grey1), + borderRadius: BorderRadius.circular(16.0), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Align( + alignment: AlignmentDirectional.centerStart, + child: Text( + viewModel.filters, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w400, + height: 0, + leadingDistribution: TextLeadingDistribution.even, + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/compass_app/app/lib/utils/result.dart b/compass_app/app/lib/utils/result.dart new file mode 100644 index 000000000..46e273363 --- /dev/null +++ b/compass_app/app/lib/utils/result.dart @@ -0,0 +1,50 @@ +/// Utility class to wrap result data +/// +/// Evaluate the result using a switch statement: +/// ```dart +/// switch (result) { +/// case Ok(): { +/// print(result.value); +/// } +/// case Error(): { +/// print(result.error); +/// } +/// } +/// ``` +sealed class Result { + const Result(); + + /// Creates an instance of Result containing a value + factory Result.ok(T value) => Ok(value); + + /// Create an instance of Result containing an error + factory Result.error(Exception error) => Error(error); + + /// Convenience method to cast to Ok + Ok get asOk => this as Ok; + + /// Convenience method to cast to Error + Error get asError => this as Error; +} + +/// Subclass of Result for values +final class Ok extends Result { + const Ok(this.value); + + /// Returned value in result + final T value; + + @override + String toString() => 'Result<$T>.ok($value)'; +} + +/// Subclass of Result for errors +final class Error extends Result { + const Error(this.error); + + /// Returned error in result + final Exception error; + + @override + String toString() => 'Result<$T>.error($error)'; +} diff --git a/compass_app/linux/.gitignore b/compass_app/app/linux/.gitignore similarity index 100% rename from compass_app/linux/.gitignore rename to compass_app/app/linux/.gitignore diff --git a/compass_app/linux/CMakeLists.txt b/compass_app/app/linux/CMakeLists.txt similarity index 100% rename from compass_app/linux/CMakeLists.txt rename to compass_app/app/linux/CMakeLists.txt diff --git a/compass_app/linux/flutter/CMakeLists.txt b/compass_app/app/linux/flutter/CMakeLists.txt similarity index 100% rename from compass_app/linux/flutter/CMakeLists.txt rename to compass_app/app/linux/flutter/CMakeLists.txt diff --git a/compass_app/linux/flutter/generated_plugin_registrant.cc b/compass_app/app/linux/flutter/generated_plugin_registrant.cc similarity index 100% rename from compass_app/linux/flutter/generated_plugin_registrant.cc rename to compass_app/app/linux/flutter/generated_plugin_registrant.cc diff --git a/compass_app/linux/flutter/generated_plugin_registrant.h b/compass_app/app/linux/flutter/generated_plugin_registrant.h similarity index 100% rename from compass_app/linux/flutter/generated_plugin_registrant.h rename to compass_app/app/linux/flutter/generated_plugin_registrant.h diff --git a/compass_app/linux/flutter/generated_plugins.cmake b/compass_app/app/linux/flutter/generated_plugins.cmake similarity index 100% rename from compass_app/linux/flutter/generated_plugins.cmake rename to compass_app/app/linux/flutter/generated_plugins.cmake diff --git a/compass_app/linux/main.cc b/compass_app/app/linux/main.cc similarity index 100% rename from compass_app/linux/main.cc rename to compass_app/app/linux/main.cc diff --git a/compass_app/linux/my_application.cc b/compass_app/app/linux/my_application.cc similarity index 100% rename from compass_app/linux/my_application.cc rename to compass_app/app/linux/my_application.cc diff --git a/compass_app/linux/my_application.h b/compass_app/app/linux/my_application.h similarity index 100% rename from compass_app/linux/my_application.h rename to compass_app/app/linux/my_application.h diff --git a/compass_app/macos/.gitignore b/compass_app/app/macos/.gitignore similarity index 100% rename from compass_app/macos/.gitignore rename to compass_app/app/macos/.gitignore diff --git a/compass_app/macos/Flutter/Flutter-Debug.xcconfig b/compass_app/app/macos/Flutter/Flutter-Debug.xcconfig similarity index 100% rename from compass_app/macos/Flutter/Flutter-Debug.xcconfig rename to compass_app/app/macos/Flutter/Flutter-Debug.xcconfig diff --git a/compass_app/macos/Flutter/Flutter-Release.xcconfig b/compass_app/app/macos/Flutter/Flutter-Release.xcconfig similarity index 100% rename from compass_app/macos/Flutter/Flutter-Release.xcconfig rename to compass_app/app/macos/Flutter/Flutter-Release.xcconfig diff --git a/compass_app/app/macos/Flutter/GeneratedPluginRegistrant.swift b/compass_app/app/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 000000000..2bfe7e4f1 --- /dev/null +++ b/compass_app/app/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,14 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import path_provider_foundation +import sqflite + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) +} diff --git a/compass_app/macos/Runner.xcodeproj/project.pbxproj b/compass_app/app/macos/Runner.xcodeproj/project.pbxproj similarity index 100% rename from compass_app/macos/Runner.xcodeproj/project.pbxproj rename to compass_app/app/macos/Runner.xcodeproj/project.pbxproj diff --git a/compass_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/compass_app/app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from compass_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to compass_app/app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/compass_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/compass_app/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme similarity index 100% rename from compass_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme rename to compass_app/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme diff --git a/compass_app/macos/Runner.xcworkspace/contents.xcworkspacedata b/compass_app/app/macos/Runner.xcworkspace/contents.xcworkspacedata similarity index 100% rename from compass_app/macos/Runner.xcworkspace/contents.xcworkspacedata rename to compass_app/app/macos/Runner.xcworkspace/contents.xcworkspacedata diff --git a/compass_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/compass_app/app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from compass_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to compass_app/app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/compass_app/macos/Runner/AppDelegate.swift b/compass_app/app/macos/Runner/AppDelegate.swift similarity index 100% rename from compass_app/macos/Runner/AppDelegate.swift rename to compass_app/app/macos/Runner/AppDelegate.swift diff --git a/compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json rename to compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png similarity index 100% rename from compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png rename to compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png diff --git a/compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png similarity index 100% rename from compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png rename to compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png diff --git a/compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png similarity index 100% rename from compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png rename to compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png diff --git a/compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png similarity index 100% rename from compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png rename to compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png diff --git a/compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png similarity index 100% rename from compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png rename to compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png diff --git a/compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png similarity index 100% rename from compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png rename to compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png diff --git a/compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png similarity index 100% rename from compass_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png rename to compass_app/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png diff --git a/compass_app/macos/Runner/Base.lproj/MainMenu.xib b/compass_app/app/macos/Runner/Base.lproj/MainMenu.xib similarity index 100% rename from compass_app/macos/Runner/Base.lproj/MainMenu.xib rename to compass_app/app/macos/Runner/Base.lproj/MainMenu.xib diff --git a/compass_app/macos/Runner/Configs/AppInfo.xcconfig b/compass_app/app/macos/Runner/Configs/AppInfo.xcconfig similarity index 100% rename from compass_app/macos/Runner/Configs/AppInfo.xcconfig rename to compass_app/app/macos/Runner/Configs/AppInfo.xcconfig diff --git a/compass_app/macos/Runner/Configs/Debug.xcconfig b/compass_app/app/macos/Runner/Configs/Debug.xcconfig similarity index 100% rename from compass_app/macos/Runner/Configs/Debug.xcconfig rename to compass_app/app/macos/Runner/Configs/Debug.xcconfig diff --git a/compass_app/macos/Runner/Configs/Release.xcconfig b/compass_app/app/macos/Runner/Configs/Release.xcconfig similarity index 100% rename from compass_app/macos/Runner/Configs/Release.xcconfig rename to compass_app/app/macos/Runner/Configs/Release.xcconfig diff --git a/compass_app/macos/Runner/Configs/Warnings.xcconfig b/compass_app/app/macos/Runner/Configs/Warnings.xcconfig similarity index 100% rename from compass_app/macos/Runner/Configs/Warnings.xcconfig rename to compass_app/app/macos/Runner/Configs/Warnings.xcconfig diff --git a/compass_app/macos/Runner/DebugProfile.entitlements b/compass_app/app/macos/Runner/DebugProfile.entitlements similarity index 85% rename from compass_app/macos/Runner/DebugProfile.entitlements rename to compass_app/app/macos/Runner/DebugProfile.entitlements index dddb8a30c..c946719a1 100644 --- a/compass_app/macos/Runner/DebugProfile.entitlements +++ b/compass_app/app/macos/Runner/DebugProfile.entitlements @@ -8,5 +8,7 @@ com.apple.security.network.server + com.apple.security.network.client + diff --git a/compass_app/macos/Runner/Info.plist b/compass_app/app/macos/Runner/Info.plist similarity index 100% rename from compass_app/macos/Runner/Info.plist rename to compass_app/app/macos/Runner/Info.plist diff --git a/compass_app/macos/Runner/MainFlutterWindow.swift b/compass_app/app/macos/Runner/MainFlutterWindow.swift similarity index 100% rename from compass_app/macos/Runner/MainFlutterWindow.swift rename to compass_app/app/macos/Runner/MainFlutterWindow.swift diff --git a/compass_app/macos/Runner/Release.entitlements b/compass_app/app/macos/Runner/Release.entitlements similarity index 100% rename from compass_app/macos/Runner/Release.entitlements rename to compass_app/app/macos/Runner/Release.entitlements diff --git a/compass_app/macos/RunnerTests/RunnerTests.swift b/compass_app/app/macos/RunnerTests/RunnerTests.swift similarity index 100% rename from compass_app/macos/RunnerTests/RunnerTests.swift rename to compass_app/app/macos/RunnerTests/RunnerTests.swift diff --git a/compass_app/pubspec.yaml b/compass_app/app/pubspec.yaml similarity index 57% rename from compass_app/pubspec.yaml rename to compass_app/app/pubspec.yaml index 0f9ce3ab1..f8ea76fbd 100644 --- a/compass_app/pubspec.yaml +++ b/compass_app/app/pubspec.yaml @@ -7,13 +7,20 @@ environment: sdk: '>=3.4.1 <4.0.0' dependencies: + cached_network_image: ^3.3.1 flutter: sdk: flutter + go_router: ^14.2.0 + google_fonts: ^6.2.1 + provider: ^6.1.2 dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^3.0.0 + flutter_lints: ^4.0.0 + mocktail_image_network: ^1.2.0 flutter: uses-material-design: true + assets: + - assets/destinations.json diff --git a/compass_app/app/test/data/repositories/destination/destination_repository_local_test.dart b/compass_app/app/test/data/repositories/destination/destination_repository_local_test.dart new file mode 100644 index 000000000..90fbf0338 --- /dev/null +++ b/compass_app/app/test/data/repositories/destination/destination_repository_local_test.dart @@ -0,0 +1,26 @@ +import 'package:compass_app/utils/result.dart'; +import 'package:compass_app/data/repositories/destination/destination_repository_local.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('DestinationRepositoryLocal tests', () { + // To load assets + TestWidgetsFlutterBinding.ensureInitialized(); + + final repository = DestinationRepositoryLocal(); + + test('should load and parse', () async { + // Should load the json and parse it + final result = await repository.getDestinations(); + expect(result, isA()); + + // Check that the list is complete + final list = result.asOk.value; + expect(list.length, 137); + + // Check first item + final destination = list.first; + expect(destination.name, 'Alaska'); + }); + }); +} diff --git a/compass_app/app/test/ui/results/fake_destination_repository.dart b/compass_app/app/test/ui/results/fake_destination_repository.dart new file mode 100644 index 000000000..d5c914857 --- /dev/null +++ b/compass_app/app/test/ui/results/fake_destination_repository.dart @@ -0,0 +1,34 @@ +import 'package:compass_app/data/models/destination.dart'; +import 'package:compass_app/data/repositories/destination/destination_repository.dart'; +import 'package:compass_app/utils/result.dart'; + +// TODO: Move to a better place +class FakeDestinationRepository implements DestinationRepository { + @override + Future>> getDestinations() { + return Future.value( + Result.ok( + [ + Destination( + ref: 'ref1', + name: 'name1', + country: 'country1', + continent: 'Europe', + knownFor: 'knownFor1', + tags: ['tags1'], + imageUrl: 'imageUrl1', + ), + Destination( + ref: 'ref2', + name: 'name2', + country: 'country2', + continent: 'Europe', + knownFor: 'knownFor2', + tags: ['tags2'], + imageUrl: 'imageUrl2', + ), + ], + ), + ); + } +} diff --git a/compass_app/app/test/ui/results/results_screen_test.dart b/compass_app/app/test/ui/results/results_screen_test.dart new file mode 100644 index 000000000..391e23524 --- /dev/null +++ b/compass_app/app/test/ui/results/results_screen_test.dart @@ -0,0 +1,46 @@ +import 'package:compass_app/ui/results/view_models/results_viewmodel.dart'; +import 'package:compass_app/ui/results/widgets/results_screen.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter/material.dart'; +import 'package:mocktail_image_network/mocktail_image_network.dart'; + +import 'fake_destination_repository.dart'; + +void main() { + // TODO: Add more cases + group('ResultsScreen widget tests', () { + testWidgets('should load screen', (WidgetTester tester) async { + await mockNetworkImages(() async { + await loadScreen(tester); + expect(find.byType(ResultsScreen), findsOneWidget); + }); + }); + + testWidgets('should display destination', (WidgetTester tester) async { + await mockNetworkImages(() async { + await loadScreen(tester); + + // Wait for list to load + await tester.pumpAndSettle(); + + // Note: Name is converted to uppercase + expect(find.text('NAME1'), findsOneWidget); + expect(find.text('tags1'), findsOneWidget); + }); + }); + }); +} + +// Build and render the ResultsScreen widget +Future loadScreen(WidgetTester tester) async { + final viewModel = ResultsViewModel( + destinationRepository: FakeDestinationRepository(), + ); + await tester.pumpWidget( + MaterialApp( + home: ResultsScreen( + viewModel: viewModel, + ), + ), + ); +} diff --git a/compass_app/app/test/ui/results/results_viewmodel_test.dart b/compass_app/app/test/ui/results/results_viewmodel_test.dart new file mode 100644 index 000000000..53128bfbe --- /dev/null +++ b/compass_app/app/test/ui/results/results_viewmodel_test.dart @@ -0,0 +1,19 @@ +import 'package:compass_app/ui/results/view_models/results_viewmodel.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'fake_destination_repository.dart'; + +void main() { + group('ResultsViewModel tests', () { + final viewModel = ResultsViewModel( + destinationRepository: FakeDestinationRepository(), + ); + + // perform a simple test + // verifies that the list of items is properly loaded + // TODO: Verify loading state and calls to search method + test('should load items', () async { + expect(viewModel.destinations.length, 2); + }); + }); +} diff --git a/compass_app/web/favicon.png b/compass_app/app/web/favicon.png similarity index 100% rename from compass_app/web/favicon.png rename to compass_app/app/web/favicon.png diff --git a/compass_app/web/icons/Icon-192.png b/compass_app/app/web/icons/Icon-192.png similarity index 100% rename from compass_app/web/icons/Icon-192.png rename to compass_app/app/web/icons/Icon-192.png diff --git a/compass_app/web/icons/Icon-512.png b/compass_app/app/web/icons/Icon-512.png similarity index 100% rename from compass_app/web/icons/Icon-512.png rename to compass_app/app/web/icons/Icon-512.png diff --git a/compass_app/web/icons/Icon-maskable-192.png b/compass_app/app/web/icons/Icon-maskable-192.png similarity index 100% rename from compass_app/web/icons/Icon-maskable-192.png rename to compass_app/app/web/icons/Icon-maskable-192.png diff --git a/compass_app/web/icons/Icon-maskable-512.png b/compass_app/app/web/icons/Icon-maskable-512.png similarity index 100% rename from compass_app/web/icons/Icon-maskable-512.png rename to compass_app/app/web/icons/Icon-maskable-512.png diff --git a/compass_app/web/index.html b/compass_app/app/web/index.html similarity index 100% rename from compass_app/web/index.html rename to compass_app/app/web/index.html diff --git a/compass_app/web/manifest.json b/compass_app/app/web/manifest.json similarity index 100% rename from compass_app/web/manifest.json rename to compass_app/app/web/manifest.json diff --git a/compass_app/windows/.gitignore b/compass_app/app/windows/.gitignore similarity index 100% rename from compass_app/windows/.gitignore rename to compass_app/app/windows/.gitignore diff --git a/compass_app/windows/CMakeLists.txt b/compass_app/app/windows/CMakeLists.txt similarity index 100% rename from compass_app/windows/CMakeLists.txt rename to compass_app/app/windows/CMakeLists.txt diff --git a/compass_app/windows/flutter/CMakeLists.txt b/compass_app/app/windows/flutter/CMakeLists.txt similarity index 100% rename from compass_app/windows/flutter/CMakeLists.txt rename to compass_app/app/windows/flutter/CMakeLists.txt diff --git a/compass_app/windows/flutter/generated_plugin_registrant.cc b/compass_app/app/windows/flutter/generated_plugin_registrant.cc similarity index 100% rename from compass_app/windows/flutter/generated_plugin_registrant.cc rename to compass_app/app/windows/flutter/generated_plugin_registrant.cc diff --git a/compass_app/windows/flutter/generated_plugin_registrant.h b/compass_app/app/windows/flutter/generated_plugin_registrant.h similarity index 100% rename from compass_app/windows/flutter/generated_plugin_registrant.h rename to compass_app/app/windows/flutter/generated_plugin_registrant.h diff --git a/compass_app/windows/flutter/generated_plugins.cmake b/compass_app/app/windows/flutter/generated_plugins.cmake similarity index 100% rename from compass_app/windows/flutter/generated_plugins.cmake rename to compass_app/app/windows/flutter/generated_plugins.cmake diff --git a/compass_app/windows/runner/CMakeLists.txt b/compass_app/app/windows/runner/CMakeLists.txt similarity index 100% rename from compass_app/windows/runner/CMakeLists.txt rename to compass_app/app/windows/runner/CMakeLists.txt diff --git a/compass_app/windows/runner/Runner.rc b/compass_app/app/windows/runner/Runner.rc similarity index 100% rename from compass_app/windows/runner/Runner.rc rename to compass_app/app/windows/runner/Runner.rc diff --git a/compass_app/windows/runner/flutter_window.cpp b/compass_app/app/windows/runner/flutter_window.cpp similarity index 100% rename from compass_app/windows/runner/flutter_window.cpp rename to compass_app/app/windows/runner/flutter_window.cpp diff --git a/compass_app/windows/runner/flutter_window.h b/compass_app/app/windows/runner/flutter_window.h similarity index 100% rename from compass_app/windows/runner/flutter_window.h rename to compass_app/app/windows/runner/flutter_window.h diff --git a/compass_app/windows/runner/main.cpp b/compass_app/app/windows/runner/main.cpp similarity index 100% rename from compass_app/windows/runner/main.cpp rename to compass_app/app/windows/runner/main.cpp diff --git a/compass_app/windows/runner/resource.h b/compass_app/app/windows/runner/resource.h similarity index 100% rename from compass_app/windows/runner/resource.h rename to compass_app/app/windows/runner/resource.h diff --git a/compass_app/windows/runner/resources/app_icon.ico b/compass_app/app/windows/runner/resources/app_icon.ico similarity index 100% rename from compass_app/windows/runner/resources/app_icon.ico rename to compass_app/app/windows/runner/resources/app_icon.ico diff --git a/compass_app/windows/runner/runner.exe.manifest b/compass_app/app/windows/runner/runner.exe.manifest similarity index 100% rename from compass_app/windows/runner/runner.exe.manifest rename to compass_app/app/windows/runner/runner.exe.manifest diff --git a/compass_app/windows/runner/utils.cpp b/compass_app/app/windows/runner/utils.cpp similarity index 100% rename from compass_app/windows/runner/utils.cpp rename to compass_app/app/windows/runner/utils.cpp diff --git a/compass_app/windows/runner/utils.h b/compass_app/app/windows/runner/utils.h similarity index 100% rename from compass_app/windows/runner/utils.h rename to compass_app/app/windows/runner/utils.h diff --git a/compass_app/windows/runner/win32_window.cpp b/compass_app/app/windows/runner/win32_window.cpp similarity index 100% rename from compass_app/windows/runner/win32_window.cpp rename to compass_app/app/windows/runner/win32_window.cpp diff --git a/compass_app/windows/runner/win32_window.h b/compass_app/app/windows/runner/win32_window.h similarity index 100% rename from compass_app/windows/runner/win32_window.h rename to compass_app/app/windows/runner/win32_window.h diff --git a/compass_app/lib/main.dart b/compass_app/lib/main.dart deleted file mode 100644 index a7256585a..000000000 --- a/compass_app/lib/main.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:flutter/material.dart'; - -void main() { - runApp(const MainApp()); -} - -class MainApp extends StatelessWidget { - const MainApp({super.key}); - - @override - Widget build(BuildContext context) { - return const MaterialApp( - home: Scaffold( - body: Center( - child: Text('Hello World!'), - ), - ), - ); - } -} diff --git a/compass_app/macos/Flutter/GeneratedPluginRegistrant.swift b/compass_app/macos/Flutter/GeneratedPluginRegistrant.swift deleted file mode 100644 index cccf817a5..000000000 --- a/compass_app/macos/Flutter/GeneratedPluginRegistrant.swift +++ /dev/null @@ -1,10 +0,0 @@ -// -// Generated file. Do not edit. -// - -import FlutterMacOS -import Foundation - - -func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { -}