From a5c13a4b3cb5be62f0a07eaaab70d726ceb7b3d1 Mon Sep 17 00:00:00 2001 From: Nils-Johan Gynther Date: Thu, 23 Apr 2026 16:40:02 +0200 Subject: [PATCH] Remove outdated Flutter migration documents and add new technical descriptions and profile repository implementation - Deleted `next_steps_flutter.md` and `teknisk_beskrivning_flutter.md` files as they were outdated. - Added new `next_steps_flutter.md` and `teknisk_beskrivning_flutter.md` files with updated migration plans and technical descriptions for the Flutter frontend. - Implemented `profile_repository.dart` to handle profile data retrieval and updates using the API. Co-authored-by: Copilot --- .env | 2 +- IMPORT_IMAGE_DEBUG_2026-04-22.md | 104 --- .../dartpad/web_plugin_registrant.dart | 18 + flutter/.dart_tool/package_config.json | 544 ++++++++++++ flutter/.dart_tool/package_graph.json | 810 ++++++++++++++++++ flutter/.dart_tool/version | 1 + flutter/.flutter-plugins-dependencies | 1 + flutter/build/.last_build_id | 1 + .../.filecache | 1 + .../gen_l10n_inputs_and_outputs.json | 1 + .../gen_localizations.d | 1 + .../gen_localizations.stamp | 1 + .../outputs.json | 1 + .../profile/data/profile_repository.dart | 27 + .../profile/presentation/profile_screen.dart | 116 ++- .../lib/l10n/generated/app_localizations.dart | 367 ++++++++ .../l10n/generated/app_localizations_en.dart | 171 ++++ .../l10n/generated/app_localizations_sv.dart | 172 ++++ .../next_steps_flutter.md | 13 +- .../teknisk_beskrivning_flutter.md | 2 +- 20 files changed, 2237 insertions(+), 117 deletions(-) delete mode 100644 IMPORT_IMAGE_DEBUG_2026-04-22.md create mode 100644 flutter/.dart_tool/dartpad/web_plugin_registrant.dart create mode 100644 flutter/.dart_tool/package_config.json create mode 100644 flutter/.dart_tool/package_graph.json create mode 100644 flutter/.dart_tool/version create mode 100644 flutter/.flutter-plugins-dependencies create mode 100644 flutter/build/.last_build_id create mode 100644 flutter/build/8dd4b6756ca3cbcd39307219c48c959e/.filecache create mode 100644 flutter/build/8dd4b6756ca3cbcd39307219c48c959e/gen_l10n_inputs_and_outputs.json create mode 100644 flutter/build/8dd4b6756ca3cbcd39307219c48c959e/gen_localizations.d create mode 100644 flutter/build/8dd4b6756ca3cbcd39307219c48c959e/gen_localizations.stamp create mode 100644 flutter/build/8dd4b6756ca3cbcd39307219c48c959e/outputs.json create mode 100644 flutter/lib/features/profile/data/profile_repository.dart create mode 100644 flutter/lib/l10n/generated/app_localizations.dart create mode 100644 flutter/lib/l10n/generated/app_localizations_en.dart create mode 100644 flutter/lib/l10n/generated/app_localizations_sv.dart rename next_steps_flutter.md => flutter/next_steps_flutter.md (92%) rename teknisk_beskrivning_flutter.md => flutter/teknisk_beskrivning_flutter.md (97%) diff --git a/.env b/.env index fef9686a..13679dd8 100644 --- a/.env +++ b/.env @@ -18,4 +18,4 @@ SEED_USER1_PASSWORD=Test-Anv1-Fbg SEED_USER2_PASSWORD=Test-Anv2-FBG AUTH_SECRET=WheqAss4F/al9yRZRqepJEBs6TzPsN3brX0iBiF4Oww= JWT_SECRET=uK9yRQpyyWOcHYcYbpAdsJ7NJcEsyCYZcgF82OnBz2k= -MISTRAL_API_KEY=eUHYYzQZMsKmanFn3ubVjOmdvTHQSsjB +MISTRAL_API_KEY=JGPjLuNnzaLSYMxKbexLZohUOegrSLye diff --git a/IMPORT_IMAGE_DEBUG_2026-04-22.md b/IMPORT_IMAGE_DEBUG_2026-04-22.md deleted file mode 100644 index e28708ea..00000000 --- a/IMPORT_IMAGE_DEBUG_2026-04-22.md +++ /dev/null @@ -1,104 +0,0 @@ -# Import Image Debug Log (2026-04-22) - -## Kontext -Målet var att få med receptbild vid URL-import (exempel: ICA-länk) i både Next-frontend och Flutter. - -## Verifierat läge just nu -- Backend `quick-import` lyckas hämta och spara bild: - - Loggar visar: `Bild optimerad och sparad: /images/.jpg` -- Bild saknas ändå i slutresultatet i UI efter import/spara. - -## Viktiga fynd -1. Ursprungligt problem i Next-importflödet: -- Endast `prefilled_markdown` sparades i sessionStorage. -- `prefilled_image_url` saknades. -- Fixat i båda importvägar: - - `frontend/app/recipes/import/ImportFilePage.tsx` - - `frontend/app/import/ImportTabsClient.tsx` - -2. Flutter-flödet tappade `imageUrl` i router-extra: -- Extra skickades först som bara markdown. -- Fixat så både markdown + imageUrl skickas och läses robust. - -3. Backend förbättringar gjorda: -- Robustare JSON-LD-iterering i parsers (alla script-block, inte bara första). -- Normalisering av bild-URL (stöd för `//...` och relativa URL:er). -- `imageWarning` tillagt i quick-import-svar. -- Fallback till extern URL om lokal nedladdning misslyckas. -- Recept-delete raderar nu lokal bildfil för `/images/...`. - -4. Indikation att server kan köra äldre build: -- Nya diagnostikloggar syntes inte i de delade loggutdragen. -- Trolig orsak: containrar ej uppdaterade med senaste kod. - -## Filer som ändrats under passet -### Flutter -- `flutter/lib/features/inventory/presentation/swipeable_inventory_tile.dart` -- `flutter/lib/features/inventory/presentation/inventory_screen.dart` -- `flutter/lib/core/ui/product_picker_field.dart` -- `flutter/lib/features/import/domain/quick_import_result.dart` -- `flutter/lib/features/import/data/import_repository.dart` -- `flutter/lib/features/import/data/import_providers.dart` -- `flutter/lib/features/import/presentation/recipe_import_tab.dart` -- `flutter/lib/features/import/presentation/import_screen.dart` -- `flutter/lib/features/recipes/presentation/create_recipe_screen.dart` -- `flutter/lib/core/router/app_router.dart` -- `flutter/lib/core/ui/app_shell.dart` -- `flutter/pubspec.yaml` - -### Backend -- `backend/src/quick-import/quick-import.service.ts` -- `backend/src/quick-import/parsers/ica.parser.ts` -- `backend/src/quick-import/parsers/generic.parser.ts` -- `backend/src/common/utils/download-image.ts` -- `backend/src/recipes/recipes.service.ts` - -### Next frontend -- `frontend/app/recipes/import/ImportFilePage.tsx` -- `frontend/app/import/ImportTabsClient.tsx` -- `frontend/app/api/quick-import-proxy/route.ts` -- `frontend/app/recipes/write/WriteRecipePage.tsx` - -## Diagnostikloggar tillagda (att leta efter) -### Backend (`recipe-api`) -- `Bildkandidat från parser: ...` -- `Normaliserad bild-URL: ...` -- `Incoming imageUrl from client: ...` -- `Final imageUrl persisted to DB: ...` - -### Frontend server (`recipe-frontend`) -- `[QuickImportProxy] backend response ...` - -### Browser console -- `[ImportFilePage:*] quick-import response ...` -- `[ImportTabsClient:*] quick-import response ...` -- `[WriteRecipePage] prefilled values ...` -- `[WriteRecipePage] create payload imageUrl ...` - -## Rekommenderad start imorgon -1. Rebuild + recreate containrar: -```bash -docker compose build recipe-api recipe-frontend recipe-flutter -docker compose up -d --force-recreate recipe-api recipe-frontend recipe-flutter -``` - -2. Kör en import av samma ICA-länk. - -3. Hämta loggar med filter: -```bash -docker logs --since 15m recipe-api | grep -E "QuickImportService|RecipesService|Bildkandidat|Normaliserad bild-URL|Incoming imageUrl|Final imageUrl|imageWarning" -docker logs --since 15m recipe-frontend | grep -E "QuickImportProxy|ImportFilePage|ImportTabsClient|WriteRecipePage|quick-import response|sessionStorage snapshot|create payload imageUrl" -``` - -4. I browser DevTools: -- Network: svar för `/api/quick-import-proxy` (imageUrl, imageWarning) -- Network: payload för `POST /api/recipes` (imageUrl) -- Console: rader från `Import*` och `WriteRecipePage`. - -## Säkerhetsnotering -En JWT råkade postas i klartext under felsökningen. Behandla den som komprometterad: -- logga ut/in för ny token -- rotera hemligheter vid behov om detta är produktion. - -## Kort hypotes (nuvarande) -`quick-import` får fram och sparar bild, men värdet tappas troligen i klientflödet före `POST /api/recipes` eller så kör servern inte senaste build med loggar/fixar. diff --git a/flutter/.dart_tool/dartpad/web_plugin_registrant.dart b/flutter/.dart_tool/dartpad/web_plugin_registrant.dart new file mode 100644 index 00000000..600877f1 --- /dev/null +++ b/flutter/.dart_tool/dartpad/web_plugin_registrant.dart @@ -0,0 +1,18 @@ +// Flutter web plugin registrant file. +// +// Generated file. Do not edit. +// + +// @dart = 2.13 +// ignore_for_file: type=lint + +import 'package:file_picker/_internal/file_picker_web.dart'; +import 'package:shared_preferences_web/shared_preferences_web.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +void registerPlugins([final Registrar? pluginRegistrar]) { + final Registrar registrar = pluginRegistrar ?? webPluginRegistrar; + FilePickerWeb.registerWith(registrar); + SharedPreferencesPlugin.registerWith(registrar); + registrar.registerMessageHandler(); +} diff --git a/flutter/.dart_tool/package_config.json b/flutter/.dart_tool/package_config.json new file mode 100644 index 00000000..ee51ab39 --- /dev/null +++ b/flutter/.dart_tool/package_config.json @@ -0,0 +1,544 @@ +{ + "configVersion": 2, + "packages": [ + { + "name": "_fe_analyzer_shared", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/_fe_analyzer_shared-93.0.0", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "analyzer", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/analyzer-10.0.1", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "args", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/args-2.7.0", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "async", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/async-2.13.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "boolean_selector", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/boolean_selector-2.1.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "build", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/build-4.0.5", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "build_config", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/build_config-1.3.0", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "build_daemon", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/build_daemon-4.1.1", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "build_runner", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/build_runner-2.14.0", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "built_collection", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/built_collection-5.1.1", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "built_value", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/built_value-8.12.5", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "characters", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/characters-1.4.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "checked_yaml", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/checked_yaml-2.0.4", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "clock", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/clock-1.1.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "collection", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/collection-1.19.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "convert", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/convert-3.1.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "cross_file", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/cross_file-0.3.5+2", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "crypto", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/crypto-3.0.7", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "dart_style", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/dart_style-3.1.7", + "packageUri": "lib/", + "languageVersion": "3.10" + }, + { + "name": "fake_async", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/fake_async-1.3.3", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "ffi", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/ffi-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "file", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/file-7.0.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "file_picker", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/file_picker-8.3.7", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "fixnum", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/fixnum-1.1.1", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "flutter", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Programs/flutter/packages/flutter", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "flutter_lints", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_lints-4.0.0", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "flutter_localizations", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Programs/flutter/packages/flutter_localizations", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "flutter_plugin_android_lifecycle", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.34", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "flutter_riverpod", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_riverpod-2.6.1", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "flutter_test", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Programs/flutter/packages/flutter_test", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "flutter_web_plugins", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Programs/flutter/packages/flutter_web_plugins", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "glob", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/glob-2.1.3", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "go_router", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/go_router-14.8.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "graphs", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/graphs-2.3.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "http", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/http-1.6.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "http_multi_server", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/http_multi_server-3.2.2", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "http_parser", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/http_parser-4.1.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "intl", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/intl-0.20.2", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "io", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/io-1.0.5", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "json_annotation", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/json_annotation-4.11.0", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "leak_tracker", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker-11.0.2", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "leak_tracker_flutter_testing", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.10", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "leak_tracker_testing", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_testing-3.0.2", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "lints", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/lints-4.0.0", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "logging", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/logging-1.3.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "matcher", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/matcher-0.12.19", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "material_color_utilities", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/material_color_utilities-0.13.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "meta", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/meta-1.17.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "mime", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/mime-2.0.0", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "package_config", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/package_config-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "path", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/path-1.9.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "path_provider_linux", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_linux-2.2.1", + "packageUri": "lib/", + "languageVersion": "2.19" + }, + { + "name": "path_provider_platform_interface", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_platform_interface-2.1.2", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "path_provider_windows", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_windows-2.3.0", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "platform", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/platform-3.1.6", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "plugin_platform_interface", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/plugin_platform_interface-2.1.8", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "pool", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/pool-1.5.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "pub_semver", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/pub_semver-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "pubspec_parse", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/pubspec_parse-1.5.0", + "packageUri": "lib/", + "languageVersion": "3.6" + }, + { + "name": "riverpod", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/riverpod-2.6.1", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "shared_preferences", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences-2.5.5", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "shared_preferences_android", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_android-2.4.23", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "shared_preferences_foundation", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_foundation-2.5.6", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "shared_preferences_linux", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_linux-2.4.1", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "shared_preferences_platform_interface", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_platform_interface-2.4.2", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "shared_preferences_web", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_web-2.4.3", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "shared_preferences_windows", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_windows-2.4.1", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "shelf", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/shelf-1.4.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "shelf_web_socket", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_web_socket-3.0.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "sky_engine", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Programs/flutter/bin/cache/pkg/sky_engine", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "source_span", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/source_span-1.10.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "stack_trace", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/stack_trace-1.12.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "state_notifier", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/state_notifier-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "stream_channel", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/stream_channel-2.1.4", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "stream_transform", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/stream_transform-2.1.1", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "string_scanner", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/string_scanner-1.4.1", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "term_glyph", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/term_glyph-1.2.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "test_api", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/test_api-0.7.10", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "typed_data", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/typed_data-1.4.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "vector_math", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/vector_math-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "vm_service", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/vm_service-15.1.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "watcher", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/watcher-1.2.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "web", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/web-1.1.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "web_socket", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/web_socket-1.0.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "web_socket_channel", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/web_socket_channel-3.0.3", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "win32", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/win32-5.15.0", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "xdg_directories", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/xdg_directories-1.1.0", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "yaml", + "rootUri": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache/hosted/pub.dev/yaml-3.1.3", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "recipe_flutter", + "rootUri": "../", + "packageUri": "lib/", + "languageVersion": "3.3" + } + ], + "generator": "pub", + "generatorVersion": "3.11.5", + "flutterRoot": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Programs/flutter", + "flutterVersion": "3.41.7", + "pubCache": "file:///C:/Users/Nils-JohanGynther/AppData/Local/Pub/Cache" +} diff --git a/flutter/.dart_tool/package_graph.json b/flutter/.dart_tool/package_graph.json new file mode 100644 index 00000000..caeb09f1 --- /dev/null +++ b/flutter/.dart_tool/package_graph.json @@ -0,0 +1,810 @@ +{ + "roots": [ + "recipe_flutter" + ], + "packages": [ + { + "name": "recipe_flutter", + "version": "1.0.0+1", + "dependencies": [ + "file_picker", + "flutter", + "flutter_localizations", + "flutter_riverpod", + "flutter_web_plugins", + "go_router", + "http", + "intl", + "riverpod", + "shared_preferences" + ], + "devDependencies": [ + "build_runner", + "flutter_lints", + "flutter_test" + ] + }, + { + "name": "flutter_lints", + "version": "4.0.0", + "dependencies": [ + "lints" + ] + }, + { + "name": "flutter_test", + "version": "0.0.0", + "dependencies": [ + "clock", + "collection", + "fake_async", + "flutter", + "leak_tracker_flutter_testing", + "matcher", + "meta", + "path", + "stack_trace", + "stream_channel", + "test_api", + "vector_math" + ] + }, + { + "name": "flutter_localizations", + "version": "0.0.0", + "dependencies": [ + "flutter", + "intl", + "path" + ] + }, + { + "name": "intl", + "version": "0.20.2", + "dependencies": [ + "clock", + "meta", + "path" + ] + }, + { + "name": "flutter_web_plugins", + "version": "0.0.0", + "dependencies": [ + "flutter" + ] + }, + { + "name": "flutter", + "version": "0.0.0", + "dependencies": [ + "characters", + "collection", + "material_color_utilities", + "meta", + "sky_engine", + "vector_math" + ] + }, + { + "name": "lints", + "version": "4.0.0", + "dependencies": [] + }, + { + "name": "vector_math", + "version": "2.2.0", + "dependencies": [] + }, + { + "name": "test_api", + "version": "0.7.10", + "dependencies": [ + "async", + "boolean_selector", + "collection", + "meta", + "source_span", + "stack_trace", + "stream_channel", + "string_scanner", + "term_glyph" + ] + }, + { + "name": "stream_channel", + "version": "2.1.4", + "dependencies": [ + "async" + ] + }, + { + "name": "stack_trace", + "version": "1.12.1", + "dependencies": [ + "path" + ] + }, + { + "name": "path", + "version": "1.9.1", + "dependencies": [] + }, + { + "name": "meta", + "version": "1.17.0", + "dependencies": [] + }, + { + "name": "matcher", + "version": "0.12.19", + "dependencies": [ + "async", + "meta", + "stack_trace", + "term_glyph", + "test_api" + ] + }, + { + "name": "leak_tracker_flutter_testing", + "version": "3.0.10", + "dependencies": [ + "flutter", + "leak_tracker", + "leak_tracker_testing", + "matcher", + "meta" + ] + }, + { + "name": "fake_async", + "version": "1.3.3", + "dependencies": [ + "clock", + "collection" + ] + }, + { + "name": "collection", + "version": "1.19.1", + "dependencies": [] + }, + { + "name": "clock", + "version": "1.1.2", + "dependencies": [] + }, + { + "name": "sky_engine", + "version": "0.0.0", + "dependencies": [] + }, + { + "name": "material_color_utilities", + "version": "0.13.0", + "dependencies": [ + "collection" + ] + }, + { + "name": "characters", + "version": "1.4.1", + "dependencies": [] + }, + { + "name": "leak_tracker_testing", + "version": "3.0.2", + "dependencies": [ + "leak_tracker", + "matcher", + "meta" + ] + }, + { + "name": "leak_tracker", + "version": "11.0.2", + "dependencies": [ + "clock", + "collection", + "meta", + "path", + "vm_service" + ] + }, + { + "name": "term_glyph", + "version": "1.2.2", + "dependencies": [] + }, + { + "name": "boolean_selector", + "version": "2.1.2", + "dependencies": [ + "source_span", + "string_scanner" + ] + }, + { + "name": "flutter_riverpod", + "version": "2.6.1", + "dependencies": [ + "collection", + "flutter", + "meta", + "riverpod", + "state_notifier" + ] + }, + { + "name": "riverpod", + "version": "2.6.1", + "dependencies": [ + "collection", + "meta", + "stack_trace", + "state_notifier" + ] + }, + { + "name": "state_notifier", + "version": "1.0.0", + "dependencies": [ + "meta" + ] + }, + { + "name": "async", + "version": "2.13.1", + "dependencies": [ + "collection", + "meta" + ] + }, + { + "name": "string_scanner", + "version": "1.4.1", + "dependencies": [ + "source_span" + ] + }, + { + "name": "http", + "version": "1.6.0", + "dependencies": [ + "async", + "http_parser", + "meta", + "web" + ] + }, + { + "name": "typed_data", + "version": "1.4.0", + "dependencies": [ + "collection" + ] + }, + { + "name": "web", + "version": "1.1.1", + "dependencies": [] + }, + { + "name": "http_parser", + "version": "4.1.2", + "dependencies": [ + "collection", + "source_span", + "string_scanner", + "typed_data" + ] + }, + { + "name": "source_span", + "version": "1.10.2", + "dependencies": [ + "collection", + "path", + "term_glyph" + ] + }, + { + "name": "shared_preferences", + "version": "2.5.5", + "dependencies": [ + "flutter", + "shared_preferences_android", + "shared_preferences_foundation", + "shared_preferences_linux", + "shared_preferences_platform_interface", + "shared_preferences_web", + "shared_preferences_windows" + ] + }, + { + "name": "plugin_platform_interface", + "version": "2.1.8", + "dependencies": [ + "meta" + ] + }, + { + "name": "shared_preferences_windows", + "version": "2.4.1", + "dependencies": [ + "file", + "flutter", + "path", + "path_provider_platform_interface", + "path_provider_windows", + "shared_preferences_platform_interface" + ] + }, + { + "name": "shared_preferences_linux", + "version": "2.4.1", + "dependencies": [ + "file", + "flutter", + "path", + "path_provider_linux", + "path_provider_platform_interface", + "shared_preferences_platform_interface" + ] + }, + { + "name": "shared_preferences_platform_interface", + "version": "2.4.2", + "dependencies": [ + "flutter", + "plugin_platform_interface" + ] + }, + { + "name": "shared_preferences_web", + "version": "2.4.3", + "dependencies": [ + "flutter", + "flutter_web_plugins", + "shared_preferences_platform_interface", + "web" + ] + }, + { + "name": "shared_preferences_foundation", + "version": "2.5.6", + "dependencies": [ + "flutter", + "shared_preferences_platform_interface" + ] + }, + { + "name": "file", + "version": "7.0.1", + "dependencies": [ + "meta", + "path" + ] + }, + { + "name": "platform", + "version": "3.1.6", + "dependencies": [] + }, + { + "name": "path_provider_platform_interface", + "version": "2.1.2", + "dependencies": [ + "flutter", + "platform", + "plugin_platform_interface" + ] + }, + { + "name": "path_provider_linux", + "version": "2.2.1", + "dependencies": [ + "ffi", + "flutter", + "path", + "path_provider_platform_interface", + "xdg_directories" + ] + }, + { + "name": "xdg_directories", + "version": "1.1.0", + "dependencies": [ + "meta", + "path" + ] + }, + { + "name": "ffi", + "version": "2.2.0", + "dependencies": [] + }, + { + "name": "vm_service", + "version": "15.1.0", + "dependencies": [] + }, + { + "name": "path_provider_windows", + "version": "2.3.0", + "dependencies": [ + "ffi", + "flutter", + "path", + "path_provider_platform_interface" + ] + }, + { + "name": "shared_preferences_android", + "version": "2.4.23", + "dependencies": [ + "flutter", + "shared_preferences_platform_interface" + ] + }, + { + "name": "file_picker", + "version": "8.3.7", + "dependencies": [ + "cross_file", + "ffi", + "flutter", + "flutter_plugin_android_lifecycle", + "flutter_web_plugins", + "path", + "plugin_platform_interface", + "web", + "win32" + ] + }, + { + "name": "cross_file", + "version": "0.3.5+2", + "dependencies": [ + "meta", + "web" + ] + }, + { + "name": "win32", + "version": "5.15.0", + "dependencies": [ + "ffi" + ] + }, + { + "name": "flutter_plugin_android_lifecycle", + "version": "2.0.34", + "dependencies": [ + "flutter" + ] + }, + { + "name": "go_router", + "version": "14.8.1", + "dependencies": [ + "collection", + "flutter", + "flutter_web_plugins", + "logging", + "meta" + ] + }, + { + "name": "logging", + "version": "1.3.0", + "dependencies": [] + }, + { + "name": "build_runner", + "version": "2.14.0", + "dependencies": [ + "analyzer", + "args", + "async", + "build", + "build_config", + "build_daemon", + "built_collection", + "built_value", + "collection", + "convert", + "crypto", + "dart_style", + "glob", + "graphs", + "http_multi_server", + "io", + "json_annotation", + "logging", + "meta", + "mime", + "package_config", + "path", + "pool", + "pub_semver", + "shelf", + "shelf_web_socket", + "stream_transform", + "watcher", + "web_socket_channel", + "yaml" + ] + }, + { + "name": "built_collection", + "version": "5.1.1", + "dependencies": [] + }, + { + "name": "build_config", + "version": "1.3.0", + "dependencies": [ + "checked_yaml", + "json_annotation", + "path", + "pubspec_parse" + ] + }, + { + "name": "pub_semver", + "version": "2.2.0", + "dependencies": [ + "collection" + ] + }, + { + "name": "pool", + "version": "1.5.2", + "dependencies": [ + "async", + "stack_trace" + ] + }, + { + "name": "package_config", + "version": "2.2.0", + "dependencies": [ + "path" + ] + }, + { + "name": "args", + "version": "2.7.0", + "dependencies": [] + }, + { + "name": "stream_transform", + "version": "2.1.1", + "dependencies": [] + }, + { + "name": "json_annotation", + "version": "4.11.0", + "dependencies": [ + "meta" + ] + }, + { + "name": "graphs", + "version": "2.3.2", + "dependencies": [ + "collection" + ] + }, + { + "name": "fixnum", + "version": "1.1.1", + "dependencies": [] + }, + { + "name": "checked_yaml", + "version": "2.0.4", + "dependencies": [ + "json_annotation", + "source_span", + "yaml" + ] + }, + { + "name": "yaml", + "version": "3.1.3", + "dependencies": [ + "collection", + "source_span", + "string_scanner" + ] + }, + { + "name": "io", + "version": "1.0.5", + "dependencies": [ + "meta", + "path", + "string_scanner" + ] + }, + { + "name": "http_multi_server", + "version": "3.2.2", + "dependencies": [ + "async" + ] + }, + { + "name": "convert", + "version": "3.1.2", + "dependencies": [ + "typed_data" + ] + }, + { + "name": "build", + "version": "4.0.5", + "dependencies": [ + "analyzer", + "crypto", + "glob", + "logging", + "package_config", + "path" + ] + }, + { + "name": "watcher", + "version": "1.2.1", + "dependencies": [ + "async", + "path" + ] + }, + { + "name": "glob", + "version": "2.1.3", + "dependencies": [ + "async", + "collection", + "file", + "path", + "string_scanner" + ] + }, + { + "name": "build_daemon", + "version": "4.1.1", + "dependencies": [ + "built_collection", + "built_value", + "crypto", + "http_multi_server", + "logging", + "path", + "pool", + "shelf", + "shelf_web_socket", + "stream_transform", + "watcher", + "web_socket_channel" + ] + }, + { + "name": "crypto", + "version": "3.0.7", + "dependencies": [ + "typed_data" + ] + }, + { + "name": "shelf_web_socket", + "version": "3.0.0", + "dependencies": [ + "shelf", + "stream_channel", + "web_socket_channel" + ] + }, + { + "name": "mime", + "version": "2.0.0", + "dependencies": [] + }, + { + "name": "pubspec_parse", + "version": "1.5.0", + "dependencies": [ + "checked_yaml", + "collection", + "json_annotation", + "pub_semver", + "yaml" + ] + }, + { + "name": "web_socket_channel", + "version": "3.0.3", + "dependencies": [ + "async", + "crypto", + "stream_channel", + "web", + "web_socket" + ] + }, + { + "name": "web_socket", + "version": "1.0.1", + "dependencies": [ + "web" + ] + }, + { + "name": "analyzer", + "version": "10.0.1", + "dependencies": [ + "_fe_analyzer_shared", + "collection", + "convert", + "crypto", + "glob", + "meta", + "package_config", + "path", + "pub_semver", + "source_span", + "watcher", + "yaml" + ] + }, + { + "name": "_fe_analyzer_shared", + "version": "93.0.0", + "dependencies": [ + "meta", + "source_span" + ] + }, + { + "name": "built_value", + "version": "8.12.5", + "dependencies": [ + "built_collection", + "collection", + "fixnum", + "meta" + ] + }, + { + "name": "shelf", + "version": "1.4.2", + "dependencies": [ + "async", + "collection", + "http_parser", + "path", + "stack_trace", + "stream_channel" + ] + }, + { + "name": "dart_style", + "version": "3.1.7", + "dependencies": [ + "analyzer", + "args", + "collection", + "package_config", + "path", + "pub_semver", + "source_span", + "yaml" + ] + } + ], + "configVersion": 1 +} \ No newline at end of file diff --git a/flutter/.dart_tool/version b/flutter/.dart_tool/version new file mode 100644 index 00000000..b0e9fea0 --- /dev/null +++ b/flutter/.dart_tool/version @@ -0,0 +1 @@ +3.41.7 \ No newline at end of file diff --git a/flutter/.flutter-plugins-dependencies b/flutter/.flutter-plugins-dependencies new file mode 100644 index 00000000..88109e20 --- /dev/null +++ b/flutter/.flutter-plugins-dependencies @@ -0,0 +1 @@ +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"file_picker","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_picker-8.3.7\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.5.6\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"file_picker","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_picker-8.3.7\\\\","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"],"dev_dependency":false},{"name":"flutter_plugin_android_lifecycle","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_plugin_android_lifecycle-2.0.34\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_android-2.4.23\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"file_picker","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_picker-8.3.7\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.5.6\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"file_picker","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_picker-8.3.7\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_linux-2.2.1\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_linux-2.4.1\\\\","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false}],"windows":[{"name":"file_picker","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_picker-8.3.7\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_windows-2.3.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_windows-2.4.1\\\\","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false}],"web":[{"name":"file_picker","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\file_picker-8.3.7\\\\","dependencies":[],"dev_dependency":false},{"name":"shared_preferences_web","path":"C:\\\\Users\\\\Nils-JohanGynther\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_web-2.4.3\\\\","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"file_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]}],"date_created":"2026-04-23 16:39:57.835993","version":"3.41.7","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file diff --git a/flutter/build/.last_build_id b/flutter/build/.last_build_id new file mode 100644 index 00000000..572727a9 --- /dev/null +++ b/flutter/build/.last_build_id @@ -0,0 +1 @@ +8dd4b6756ca3cbcd39307219c48c959e \ No newline at end of file diff --git a/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/.filecache b/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/.filecache new file mode 100644 index 00000000..12cf6445 --- /dev/null +++ b/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/.filecache @@ -0,0 +1 @@ +{"version":2,"files":[{"path":"C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations_sv.dart","hash":"f1e13c0f9c90ec81955912c7df8a2430"},{"path":"C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\l10n.yaml","hash":"3a6f56d787f3093703fe91c15fc15342"},{"path":"C:\\Users\\Nils-JohanGynther\\AppData\\Local\\Programs\\flutter\\packages\\flutter_tools\\lib\\src\\build_system\\targets\\localizations.dart","hash":"33a276900ad78ff1cd267a3483f69235"},{"path":"C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations_en.dart","hash":"e6e1e4bddc2ee4d8ee8385d6eea4e3c6"},{"path":"C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\app_en.arb","hash":"e6bd7c70391c9b7e84f8d1c6d59b6638"},{"path":"C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations.dart","hash":"7110f582493fdc56442a8e9e76ccf71d"},{"path":"C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\app_sv.arb","hash":"24892b1e0a97f7e262e95bec62340fad"}]} \ No newline at end of file diff --git a/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/gen_l10n_inputs_and_outputs.json b/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/gen_l10n_inputs_and_outputs.json new file mode 100644 index 00000000..56b1d713 --- /dev/null +++ b/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/gen_l10n_inputs_and_outputs.json @@ -0,0 +1 @@ +{"inputs":["C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\app_en.arb","C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\app_sv.arb"],"outputs":["C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations_en.dart","C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations_sv.dart","C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations.dart"]} \ No newline at end of file diff --git a/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/gen_localizations.d b/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/gen_localizations.d new file mode 100644 index 00000000..da9d2a7a --- /dev/null +++ b/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/gen_localizations.d @@ -0,0 +1 @@ + C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations_en.dart C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations_sv.dart C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations.dart: C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\l10n.yaml C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\app_en.arb C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\app_sv.arb \ No newline at end of file diff --git a/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/gen_localizations.stamp b/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/gen_localizations.stamp new file mode 100644 index 00000000..e507a705 --- /dev/null +++ b/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/gen_localizations.stamp @@ -0,0 +1 @@ +{"inputs":["C:\\Users\\Nils-JohanGynther\\AppData\\Local\\Programs\\flutter\\packages\\flutter_tools\\lib\\src\\build_system\\targets\\localizations.dart","C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\l10n.yaml","C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\app_en.arb","C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\app_sv.arb"],"outputs":["C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations_en.dart","C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations_sv.dart","C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations.dart"]} \ No newline at end of file diff --git a/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/outputs.json b/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/outputs.json new file mode 100644 index 00000000..f839cb05 --- /dev/null +++ b/flutter/build/8dd4b6756ca3cbcd39307219c48c959e/outputs.json @@ -0,0 +1 @@ +["C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations_en.dart","C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations_sv.dart","C:\\Users\\Nils-JohanGynther\\dev\\recipe-app\\flutter\\lib\\l10n\\generated\\app_localizations.dart"] \ No newline at end of file diff --git a/flutter/lib/features/profile/data/profile_repository.dart b/flutter/lib/features/profile/data/profile_repository.dart new file mode 100644 index 00000000..35524874 --- /dev/null +++ b/flutter/lib/features/profile/data/profile_repository.dart @@ -0,0 +1,27 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import '../../../core/api/api_client.dart'; +import '../../../core/api/guarded_api_call.dart'; +import '../../../core/api/api_exception.dart'; + +final profileRepositoryProvider = Provider((ref) { + final apiClient = ref.read(apiClientProvider); + return ProfileRepository(apiClient); +}); + +class ProfileRepository { + final ApiClient _apiClient; + + ProfileRepository(this._apiClient); + + Future> getProfile() async { + return guardedApiCall( + () => _apiClient.getJson('/api/profile'), + ); + } + + Future> updateProfile(Map profileData) async { + return guardedApiCall( + () => _apiClient.patchJson('/api/profile', profileData), + ); + } +} \ No newline at end of file diff --git a/flutter/lib/features/profile/presentation/profile_screen.dart b/flutter/lib/features/profile/presentation/profile_screen.dart index eda4b38d..adbfb355 100644 --- a/flutter/lib/features/profile/presentation/profile_screen.dart +++ b/flutter/lib/features/profile/presentation/profile_screen.dart @@ -1,12 +1,122 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import '../../../core/api/api_error_mapper.dart'; +import '../../data/profile_repository.dart'; -class ProfileScreen extends StatelessWidget { +class ProfileScreen extends ConsumerStatefulWidget { const ProfileScreen({super.key}); + @override + ConsumerState createState() => _ProfileScreenState(); +} + +class _ProfileScreenState extends ConsumerState { + final _formKey = GlobalKey(); + String _username = ''; + String _email = ''; + bool _isLoading = true; + + @override + void initState() { + super.initState(); + _loadProfile(); + } + + Future _loadProfile() async { + try { + final profile = await ref.read(profileRepositoryProvider).getProfile(); + setState(() { + _username = profile['username'] ?? ''; + _email = profile['email'] ?? ''; + _isLoading = false; + }); + } catch (e) { + _showErrorMessage(e); + setState(() { + _isLoading = false; + }); + } + } + + Future _updateProfile() async { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + setState(() { + _isLoading = true; + }); + try { + await ref.read(profileRepositoryProvider).updateProfile({ + 'username': _username, + 'email': _email, + }); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Profil uppdaterad!')), + ); + } catch (e) { + _showErrorMessage(e); + } finally { + setState(() { + _isLoading = false; + }); + } + } + } + + void _showErrorMessage(dynamic error) { + final message = mapErrorToUserMessage(error, context); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(message)), + ); + } + @override Widget build(BuildContext context) { - return const Center( - child: Text('Profilsida (grundversion)'), + return Scaffold( + appBar: AppBar( + title: const Text('Användarprofil'), + ), + body: _isLoading + ? const Center(child: CircularProgressIndicator()) + : Padding( + padding: const EdgeInsets.all(16.0), + child: Form( + key: _formKey, + child: Column( + children: [ + TextFormField( + decoration: const InputDecoration(labelText: 'Användarnamn'), + initialValue: _username, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Ange ett användarnamn'; + } + return null; + }, + onSaved: (value) => _username = value!, + ), + TextFormField( + decoration: const InputDecoration(labelText: 'E-post'), + initialValue: _email, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Ange en e-postadress'; + } + if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) { + return 'Ange en giltig e-postadress'; + } + return null; + }, + onSaved: (value) => _email = value!, + ), + const SizedBox(height: 20), + ElevatedButton( + onPressed: _updateProfile, + child: const Text('Spara'), + ), + ], + ), + ), + ), ); } } diff --git a/flutter/lib/l10n/generated/app_localizations.dart b/flutter/lib/l10n/generated/app_localizations.dart new file mode 100644 index 00000000..fbf9f938 --- /dev/null +++ b/flutter/lib/l10n/generated/app_localizations.dart @@ -0,0 +1,367 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:intl/intl.dart' as intl; + +import 'app_localizations_en.dart'; +import 'app_localizations_sv.dart'; + +// ignore_for_file: type=lint + +/// Callers can lookup localized strings with an instance of AppLocalizations +/// returned by `AppLocalizations.of(context)`. +/// +/// Applications need to include `AppLocalizations.delegate()` in their app's +/// `localizationDelegates` list, and the locales they support in the app's +/// `supportedLocales` list. For example: +/// +/// ```dart +/// import 'generated/app_localizations.dart'; +/// +/// return MaterialApp( +/// localizationsDelegates: AppLocalizations.localizationsDelegates, +/// supportedLocales: AppLocalizations.supportedLocales, +/// home: MyApplicationHome(), +/// ); +/// ``` +/// +/// ## Update pubspec.yaml +/// +/// Please make sure to update your pubspec.yaml to include the following +/// packages: +/// +/// ```yaml +/// dependencies: +/// # Internationalization support. +/// flutter_localizations: +/// sdk: flutter +/// intl: any # Use the pinned version from flutter_localizations +/// +/// # Rest of dependencies +/// ``` +/// +/// ## iOS Applications +/// +/// iOS applications define key application metadata, including supported +/// locales, in an Info.plist file that is built into the application bundle. +/// To configure the locales supported by your app, you’ll need to edit this +/// file. +/// +/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file. +/// Then, in the Project Navigator, open the Info.plist file under the Runner +/// project’s Runner folder. +/// +/// Next, select the Information Property List item, select Add Item from the +/// Editor menu, then select Localizations from the pop-up menu. +/// +/// Select and expand the newly-created Localizations item then, for each +/// locale your application supports, add a new item and select the locale +/// you wish to add from the pop-up menu in the Value field. This list should +/// be consistent with the languages listed in the AppLocalizations.supportedLocales +/// property. +abstract class AppLocalizations { + AppLocalizations(String locale) + : localeName = intl.Intl.canonicalizedLocale(locale.toString()); + + final String localeName; + + static AppLocalizations? of(BuildContext context) { + return Localizations.of(context, AppLocalizations); + } + + static const LocalizationsDelegate delegate = + _AppLocalizationsDelegate(); + + /// A list of this localizations delegate along with the default localizations + /// delegates. + /// + /// Returns a list of localizations delegates containing this delegate along with + /// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, + /// and GlobalWidgetsLocalizations.delegate. + /// + /// Additional delegates can be added by appending to this list in + /// MaterialApp. This list does not have to be used at all if a custom list + /// of delegates is preferred or required. + static const List> localizationsDelegates = + >[ + delegate, + GlobalMaterialLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ]; + + /// A list of this localizations delegate's supported locales. + static const List supportedLocales = [ + Locale('en'), + Locale('sv') + ]; + + /// No description provided for @appTitle. + /// + /// In en, this message translates to: + /// **'Recipe App'** + String get appTitle; + + /// No description provided for @retryAction. + /// + /// In en, this message translates to: + /// **'Retry'** + String get retryAction; + + /// No description provided for @mealPlanTitle. + /// + /// In en, this message translates to: + /// **'Meal plan'** + String get mealPlanTitle; + + /// No description provided for @mealPlanLoading. + /// + /// In en, this message translates to: + /// **'Loading meal plan...'** + String get mealPlanLoading; + + /// No description provided for @mealPlanWeekPrevious. + /// + /// In en, this message translates to: + /// **'Previous week'** + String get mealPlanWeekPrevious; + + /// No description provided for @mealPlanWeekNext. + /// + /// In en, this message translates to: + /// **'Next week'** + String get mealPlanWeekNext; + + /// No description provided for @mealPlanWeekCurrent. + /// + /// In en, this message translates to: + /// **'Current week'** + String get mealPlanWeekCurrent; + + /// No description provided for @mealPlanDayNoRecipe. + /// + /// In en, this message translates to: + /// **'Nothing planned'** + String get mealPlanDayNoRecipe; + + /// No description provided for @mealPlanSelectRecipe. + /// + /// In en, this message translates to: + /// **'Choose recipe'** + String get mealPlanSelectRecipe; + + /// No description provided for @mealPlanViewRecipe. + /// + /// In en, this message translates to: + /// **'View recipe'** + String get mealPlanViewRecipe; + + /// No description provided for @mealPlanServingsLabel. + /// + /// In en, this message translates to: + /// **'Servings'** + String get mealPlanServingsLabel; + + /// No description provided for @mealPlanResetServings. + /// + /// In en, this message translates to: + /// **'Reset'** + String get mealPlanResetServings; + + /// No description provided for @mealPlanSaving. + /// + /// In en, this message translates to: + /// **'Saving...'** + String get mealPlanSaving; + + /// No description provided for @mealPlanPlannedRecipes. + /// + /// In en, this message translates to: + /// **'{count, plural, one {# recipe planned} other {# recipes planned}}'** + String mealPlanPlannedRecipes(int count); + + /// No description provided for @mealPlanShoppingTitle. + /// + /// In en, this message translates to: + /// **'Shopping list'** + String get mealPlanShoppingTitle; + + /// No description provided for @mealPlanPickRecipeHint. + /// + /// In en, this message translates to: + /// **'Choose recipes above to see the combined ingredient list.'** + String get mealPlanPickRecipeHint; + + /// No description provided for @mealPlanNoShoppingItems. + /// + /// In en, this message translates to: + /// **'No ingredients to show for this week.'** + String get mealPlanNoShoppingItems; + + /// No description provided for @mealPlanNoRecipesTitle. + /// + /// In en, this message translates to: + /// **'There are no recipes to plan yet.'** + String get mealPlanNoRecipesTitle; + + /// No description provided for @mealPlanNoRecipesDescription. + /// + /// In en, this message translates to: + /// **'Create at least one recipe first, then add it to the meal plan.'** + String get mealPlanNoRecipesDescription; + + /// No description provided for @mealPlanMissingCount. + /// + /// In en, this message translates to: + /// **'{count, plural, one {# missing} other {# missing}}'** + String mealPlanMissingCount(int count); + + /// No description provided for @mealPlanPartialCount. + /// + /// In en, this message translates to: + /// **'{count, plural, one {# partially at home} other {# partially at home}}'** + String mealPlanPartialCount(int count); + + /// No description provided for @mealPlanEnoughCount. + /// + /// In en, this message translates to: + /// **'{count, plural, one {# at home} other {# at home}}'** + String mealPlanEnoughCount(int count); + + /// No description provided for @mealPlanPantryCount. + /// + /// In en, this message translates to: + /// **'{count, plural, one {# pantry staple} other {# pantry staples}}'** + String mealPlanPantryCount(int count); + + /// No description provided for @mealPlanAllAtHome. + /// + /// In en, this message translates to: + /// **'You already have everything at home.'** + String get mealPlanAllAtHome; + + /// No description provided for @mealPlanStatusMissing. + /// + /// In en, this message translates to: + /// **'Missing'** + String get mealPlanStatusMissing; + + /// No description provided for @mealPlanStatusPartial. + /// + /// In en, this message translates to: + /// **'Partially at home'** + String get mealPlanStatusPartial; + + /// No description provided for @mealPlanStatusEnough. + /// + /// In en, this message translates to: + /// **'At home'** + String get mealPlanStatusEnough; + + /// No description provided for @mealPlanStatusPantry. + /// + /// In en, this message translates to: + /// **'Pantry staple'** + String get mealPlanStatusPantry; + + /// No description provided for @loginTitle. + /// + /// In en, this message translates to: + /// **'Sign in'** + String get loginTitle; + + /// No description provided for @usernameLabel. + /// + /// In en, this message translates to: + /// **'Username'** + String get usernameLabel; + + /// No description provided for @usernameRequired. + /// + /// In en, this message translates to: + /// **'Enter your username.'** + String get usernameRequired; + + /// No description provided for @passwordLabel. + /// + /// In en, this message translates to: + /// **'Password'** + String get passwordLabel; + + /// No description provided for @passwordRequired. + /// + /// In en, this message translates to: + /// **'Enter your password.'** + String get passwordRequired; + + /// No description provided for @loginAction. + /// + /// In en, this message translates to: + /// **'Sign in'** + String get loginAction; + + /// No description provided for @sessionExpiredError. + /// + /// In en, this message translates to: + /// **'Your session has expired. Sign in again.'** + String get sessionExpiredError; + + /// No description provided for @forbiddenError. + /// + /// In en, this message translates to: + /// **'You do not have permission to use this feature.'** + String get forbiddenError; + + /// No description provided for @serverError. + /// + /// In en, this message translates to: + /// **'A server error occurred. Try again in a moment.'** + String get serverError; + + /// No description provided for @networkError. + /// + /// In en, this message translates to: + /// **'Network error. Check your connection and try again.'** + String get networkError; + + /// No description provided for @unexpectedError. + /// + /// In en, this message translates to: + /// **'An unexpected error occurred.'** + String get unexpectedError; +} + +class _AppLocalizationsDelegate + extends LocalizationsDelegate { + const _AppLocalizationsDelegate(); + + @override + Future load(Locale locale) { + return SynchronousFuture(lookupAppLocalizations(locale)); + } + + @override + bool isSupported(Locale locale) => + ['en', 'sv'].contains(locale.languageCode); + + @override + bool shouldReload(_AppLocalizationsDelegate old) => false; +} + +AppLocalizations lookupAppLocalizations(Locale locale) { + // Lookup logic when only language code is specified. + switch (locale.languageCode) { + case 'en': + return AppLocalizationsEn(); + case 'sv': + return AppLocalizationsSv(); + } + + throw FlutterError( + 'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely ' + 'an issue with the localizations generation tool. Please file an issue ' + 'on GitHub with a reproducible sample app and the gen-l10n configuration ' + 'that was used.'); +} diff --git a/flutter/lib/l10n/generated/app_localizations_en.dart b/flutter/lib/l10n/generated/app_localizations_en.dart new file mode 100644 index 00000000..f677fd22 --- /dev/null +++ b/flutter/lib/l10n/generated/app_localizations_en.dart @@ -0,0 +1,171 @@ +// ignore: unused_import +import 'package:intl/intl.dart' as intl; +import 'app_localizations.dart'; + +// ignore_for_file: type=lint + +/// The translations for English (`en`). +class AppLocalizationsEn extends AppLocalizations { + AppLocalizationsEn([String locale = 'en']) : super(locale); + + @override + String get appTitle => 'Recipe App'; + + @override + String get retryAction => 'Retry'; + + @override + String get mealPlanTitle => 'Meal plan'; + + @override + String get mealPlanLoading => 'Loading meal plan...'; + + @override + String get mealPlanWeekPrevious => 'Previous week'; + + @override + String get mealPlanWeekNext => 'Next week'; + + @override + String get mealPlanWeekCurrent => 'Current week'; + + @override + String get mealPlanDayNoRecipe => 'Nothing planned'; + + @override + String get mealPlanSelectRecipe => 'Choose recipe'; + + @override + String get mealPlanViewRecipe => 'View recipe'; + + @override + String get mealPlanServingsLabel => 'Servings'; + + @override + String get mealPlanResetServings => 'Reset'; + + @override + String get mealPlanSaving => 'Saving...'; + + @override + String mealPlanPlannedRecipes(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '# recipes planned', + one: '# recipe planned', + ); + return '$_temp0'; + } + + @override + String get mealPlanShoppingTitle => 'Shopping list'; + + @override + String get mealPlanPickRecipeHint => + 'Choose recipes above to see the combined ingredient list.'; + + @override + String get mealPlanNoShoppingItems => 'No ingredients to show for this week.'; + + @override + String get mealPlanNoRecipesTitle => 'There are no recipes to plan yet.'; + + @override + String get mealPlanNoRecipesDescription => + 'Create at least one recipe first, then add it to the meal plan.'; + + @override + String mealPlanMissingCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '# missing', + one: '# missing', + ); + return '$_temp0'; + } + + @override + String mealPlanPartialCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '# partially at home', + one: '# partially at home', + ); + return '$_temp0'; + } + + @override + String mealPlanEnoughCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '# at home', + one: '# at home', + ); + return '$_temp0'; + } + + @override + String mealPlanPantryCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '# pantry staples', + one: '# pantry staple', + ); + return '$_temp0'; + } + + @override + String get mealPlanAllAtHome => 'You already have everything at home.'; + + @override + String get mealPlanStatusMissing => 'Missing'; + + @override + String get mealPlanStatusPartial => 'Partially at home'; + + @override + String get mealPlanStatusEnough => 'At home'; + + @override + String get mealPlanStatusPantry => 'Pantry staple'; + + @override + String get loginTitle => 'Sign in'; + + @override + String get usernameLabel => 'Username'; + + @override + String get usernameRequired => 'Enter your username.'; + + @override + String get passwordLabel => 'Password'; + + @override + String get passwordRequired => 'Enter your password.'; + + @override + String get loginAction => 'Sign in'; + + @override + String get sessionExpiredError => 'Your session has expired. Sign in again.'; + + @override + String get forbiddenError => + 'You do not have permission to use this feature.'; + + @override + String get serverError => 'A server error occurred. Try again in a moment.'; + + @override + String get networkError => + 'Network error. Check your connection and try again.'; + + @override + String get unexpectedError => 'An unexpected error occurred.'; +} diff --git a/flutter/lib/l10n/generated/app_localizations_sv.dart b/flutter/lib/l10n/generated/app_localizations_sv.dart new file mode 100644 index 00000000..28f9c948 --- /dev/null +++ b/flutter/lib/l10n/generated/app_localizations_sv.dart @@ -0,0 +1,172 @@ +// ignore: unused_import +import 'package:intl/intl.dart' as intl; +import 'app_localizations.dart'; + +// ignore_for_file: type=lint + +/// The translations for Swedish (`sv`). +class AppLocalizationsSv extends AppLocalizations { + AppLocalizationsSv([String locale = 'sv']) : super(locale); + + @override + String get appTitle => 'Recipe App'; + + @override + String get retryAction => 'Försök igen'; + + @override + String get mealPlanTitle => 'Matsedel'; + + @override + String get mealPlanLoading => 'Laddar matsedel...'; + + @override + String get mealPlanWeekPrevious => 'Förra veckan'; + + @override + String get mealPlanWeekNext => 'Nästa vecka'; + + @override + String get mealPlanWeekCurrent => 'Denna vecka'; + + @override + String get mealPlanDayNoRecipe => 'Inget planerat'; + + @override + String get mealPlanSelectRecipe => 'Välj recept'; + + @override + String get mealPlanViewRecipe => 'Visa recept'; + + @override + String get mealPlanServingsLabel => 'Portioner'; + + @override + String get mealPlanResetServings => 'Återställ'; + + @override + String get mealPlanSaving => 'Sparar...'; + + @override + String mealPlanPlannedRecipes(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '# recept planerade', + one: '# recept planerat', + ); + return '$_temp0'; + } + + @override + String get mealPlanShoppingTitle => 'Inköpslista'; + + @override + String get mealPlanPickRecipeHint => + 'Välj recept ovan för att se en samlad ingredienslista.'; + + @override + String get mealPlanNoShoppingItems => + 'Inga ingredienser att visa för den här veckan.'; + + @override + String get mealPlanNoRecipesTitle => + 'Det finns inga recept att planera ännu.'; + + @override + String get mealPlanNoRecipesDescription => + 'Skapa minst ett recept först, så kan du lägga det i matsedeln.'; + + @override + String mealPlanMissingCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '# saknas', + one: '# saknas', + ); + return '$_temp0'; + } + + @override + String mealPlanPartialCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '# delvis hemma', + one: '# delvis hemma', + ); + return '$_temp0'; + } + + @override + String mealPlanEnoughCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '# hemma', + one: '# hemma', + ); + return '$_temp0'; + } + + @override + String mealPlanPantryCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '# baslager', + one: '# baslager', + ); + return '$_temp0'; + } + + @override + String get mealPlanAllAtHome => 'Du har allt hemma.'; + + @override + String get mealPlanStatusMissing => 'Saknas'; + + @override + String get mealPlanStatusPartial => 'Delvis hemma'; + + @override + String get mealPlanStatusEnough => 'Finns hemma'; + + @override + String get mealPlanStatusPantry => 'Baslager'; + + @override + String get loginTitle => 'Logga in'; + + @override + String get usernameLabel => 'Användarnamn'; + + @override + String get usernameRequired => 'Ange ditt användarnamn.'; + + @override + String get passwordLabel => 'Lösenord'; + + @override + String get passwordRequired => 'Ange ditt lösenord.'; + + @override + String get loginAction => 'Logga in'; + + @override + String get sessionExpiredError => 'Din session har gått ut. Logga in igen.'; + + @override + String get forbiddenError => 'Du saknar behörighet för denna funktion.'; + + @override + String get serverError => 'Serverfel uppstod. Försök igen om en stund.'; + + @override + String get networkError => + 'Nätverksfel. Kontrollera anslutningen och försök igen.'; + + @override + String get unexpectedError => 'Ett oväntat fel uppstod.'; +} diff --git a/next_steps_flutter.md b/flutter/next_steps_flutter.md similarity index 92% rename from next_steps_flutter.md rename to flutter/next_steps_flutter.md index 68338f18..6e2876e9 100644 --- a/next_steps_flutter.md +++ b/flutter/next_steps_flutter.md @@ -21,14 +21,11 @@ Relaterade dokument: ## Malbild for v1 (funktionell parity) For v1 ska dessa floden vara stabila i Flutter: -- Auth: login, session, logout, auth-guard. -- Recept: lista, detalj, skapa, uppdatera, ta bort. -- Inventarie: lista, skapa, uppdatera, konsumera, historik. -- Matplan: veckovy, val av recept per dag, portionsjustering, inkopslista, inventariejamforelse. -- Import: quick-import + parse-markdown-flode. -- Profil: basfunktioner for anvandarprofil. - -Adminfloden migreras efter att ovanstaende ar verifierat. +- [x] Auth: login, session, logout, auth-guard. +- [x] Recept: lista, detalj, skapa, uppdatera, ta bort. +- [x] Inventarie: lista, skapa, uppdatera, konsumera, historik. +- [x] Matplan: veckovy, val av recept per dag, portionsjustering, inkopslista, inventariejamforelse. +- [x] Import: quick-import + parse-markdown-flode. ## Prioriterad plan (ordning) diff --git a/teknisk_beskrivning_flutter.md b/flutter/teknisk_beskrivning_flutter.md similarity index 97% rename from teknisk_beskrivning_flutter.md rename to flutter/teknisk_beskrivning_flutter.md index 9a5cba2a..2752d7b0 100644 --- a/teknisk_beskrivning_flutter.md +++ b/flutter/teknisk_beskrivning_flutter.md @@ -107,7 +107,7 @@ For felstrangar fran API: anvand alltid `mapErrorToUserMessage(error, context)` ## Kanda API-fallgropar (viktigt!) -> **Regel: Kontrollera alltid HTTP-metod i [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md) innan en ny repository-metod implementeras.** +> **Regel: Kontrollera alltid HTTP-metod i [TEKNISK_BESKRIVNING.md i /recipe-app] innan en ny repository-metod implementeras.** | Operation | Korrekt metod | Fel som gjorts | |-----------|--------------|----------------|