diff --git a/flutter/lib/core/ui/app_shell.dart b/flutter/lib/core/ui/app_shell.dart index 264f4cc5..7c092f4f 100644 --- a/flutter/lib/core/ui/app_shell.dart +++ b/flutter/lib/core/ui/app_shell.dart @@ -4,9 +4,6 @@ import 'package:go_router/go_router.dart'; import '../../features/auth/data/auth_providers.dart'; import '../../features/recipes/data/recipes_grid_provider.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; const _adminDestination = _AppDestination( path: '/admin', diff --git a/flutter/lib/core/ui/product_picker_field.dart b/flutter/lib/core/ui/product_picker_field.dart index 41cc50f6..a0b7396e 100644 --- a/flutter/lib/core/ui/product_picker_field.dart +++ b/flutter/lib/core/ui/product_picker_field.dart @@ -81,6 +81,98 @@ class ProductPickerField extends StatelessWidget { } Future _openPicker(BuildContext context) async { - // Implementera logik för att öppna en bottom sheet för produktval + final selectedId = await showModalBottomSheet( + context: context, + isScrollControlled: true, + useSafeArea: true, + builder: (sheetContext) { + var query = ''; + + return StatefulBuilder( + builder: (context, setModalState) { + final normalizedQuery = query.trim().toLowerCase(); + final filtered = normalizedQuery.isEmpty + ? products + : products + .where( + (p) => p.name.toLowerCase().contains(normalizedQuery), + ) + .toList(); + + return SizedBox( + height: MediaQuery.of(context).size.height * 0.85, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(16, 12, 16, 8), + child: Row( + children: [ + Expanded( + child: Text( + label, + style: Theme.of(context).textTheme.titleMedium, + ), + ), + TextButton.icon( + onPressed: () => Navigator.pop(context, null), + icon: const Icon(Icons.clear), + label: const Text('Rensa'), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), + child: TextField( + autofocus: true, + decoration: const InputDecoration( + hintText: 'Sök produkt...', + prefixIcon: Icon(Icons.search), + border: OutlineInputBorder(), + ), + onChanged: (text) { + setModalState(() { + query = text; + }); + }, + ), + ), + const Divider(height: 1), + Expanded( + child: filtered.isEmpty + ? const Center( + child: Text('Inga produkter matchar sökningen.'), + ) + : ListView.separated( + itemCount: filtered.length, + separatorBuilder: (_, __) => const Divider(height: 1), + itemBuilder: (context, index) { + final product = filtered[index]; + final isSelected = product.id == value; + return ListTile( + selected: isSelected, + title: Text(product.name), + trailing: isSelected + ? const Icon(Icons.check) + : null, + onTap: () => Navigator.pop(context, product.id), + ); + }, + ), + ), + ], + ), + ); + }, + ); + }, + ); + + if (!context.mounted) return; + if (selectedId == null) { + onChanged?.call(null); + return; + } + onChanged?.call(selectedId); } } diff --git a/flutter/lib/features/recipes/presentation/recipes_screen.dart b/flutter/lib/features/recipes/presentation/recipes_screen.dart index 779d8335..95a2d3fb 100644 --- a/flutter/lib/features/recipes/presentation/recipes_screen.dart +++ b/flutter/lib/features/recipes/presentation/recipes_screen.dart @@ -71,15 +71,42 @@ class RecipesScreen extends ConsumerWidget { itemCount: recipes.length, itemBuilder: (context, index) { final recipe = recipes[index]; - return ListTile( - leading: recipe.imageUrl != null - ? CircleAvatar( - backgroundImage: NetworkImage(recipe.imageUrl!), - ) - : const CircleAvatar(child: Icon(Icons.restaurant)), - title: Text(recipe.title), - subtitle: Text(recipe.description ?? ''), + return InkWell( onTap: () => context.push('/recipes/${recipe.id}'), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 6), + child: Row( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(6), + child: recipe.imageUrl != null + ? Image.network( + recipe.imageUrl!, + width: 72, + height: 72, + fit: BoxFit.cover, + ) + : Container( + width: 72, + height: 72, + color: Colors.grey[200], + child: const Icon(Icons.restaurant, + size: 32), + ), + ), + const SizedBox(width: 12), + Expanded( + child: Text( + recipe.title, + style: Theme.of(context).textTheme.titleMedium, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), ); }, );