From 3f848a39910faf73c3939db08e92c411df375d61 Mon Sep 17 00:00:00 2001 From: Nils-Johan Gynther Date: Fri, 24 Apr 2026 22:45:53 +0200 Subject: [PATCH] feat: refactor RecipesScreen to use grid layout and save column preference Co-authored-by: Copilot --- .../recipes/presentation/recipes_screen.dart | 109 ++++++++++++++---- 1 file changed, 87 insertions(+), 22 deletions(-) diff --git a/flutter/lib/features/recipes/presentation/recipes_screen.dart b/flutter/lib/features/recipes/presentation/recipes_screen.dart index 508a0160..bd33f543 100644 --- a/flutter/lib/features/recipes/presentation/recipes_screen.dart +++ b/flutter/lib/features/recipes/presentation/recipes_screen.dart @@ -1,18 +1,77 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import '../../../core/api/api_error_mapper.dart'; import '../../../core/ui/async_state_views.dart'; import '../data/recipe_providers.dart'; -class RecipesScreen extends ConsumerWidget { +class RecipesScreen extends ConsumerStatefulWidget { const RecipesScreen({super.key}); @override - Widget build(BuildContext context, WidgetRef ref) { + ConsumerState createState() => _RecipesScreenState(); +} + +class _RecipesScreenState extends ConsumerState { + int _selectedColumns = 2; + + @override + void initState() { + super.initState(); + _loadSelectedColumns(); + } + + Future _loadSelectedColumns() async { + final prefs = await SharedPreferences.getInstance(); + setState(() { + _selectedColumns = prefs.getInt('selectedColumns') ?? 2; + }); + } + + Future _saveSelectedColumns(int columns) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setInt('selectedColumns', columns); + } + + @override + Widget build(BuildContext context) { final recipesAsync = ref.watch(recipesProvider); + return Scaffold( + appBar: AppBar( + title: const Text('Recept'), + actions: [ + PopupMenuButton( + icon: const Icon(Icons.grid_view), + onSelected: (int columns) { + setState(() { + _selectedColumns = columns; + }); + _saveSelectedColumns(columns); + }, + itemBuilder: (BuildContext context) => >[ + const PopupMenuItem( + value: 2, + child: Text('2 kolumner'), + ), + const PopupMenuItem( + value: 4, + child: Text('4 kolumner'), + ), + const PopupMenuItem( + value: 6, + child: Text('6 kolumner'), + ), + const PopupMenuItem( + value: 8, + child: Text('8 kolumner'), + ), + ], + ), + ], + ), body: recipesAsync.when( loading: () => const LoadingStateView(label: 'Laddar recept...'), error: (error, _) => ErrorStateView( @@ -27,26 +86,32 @@ class RecipesScreen extends ConsumerWidget { ); } - return ListView.builder( - itemCount: recipes.length, - itemBuilder: (context, index) { - final recipe = recipes[index]; - return ListTile( - leading: recipe.imageUrl != null - ? Image.network(recipe.imageUrl!, width: 56, fit: BoxFit.cover) - : const Icon(Icons.restaurant), - title: Text(recipe.title), - subtitle: recipe.description != null - ? Text( - recipe.description!, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ) - : null, - trailing: const Icon(Icons.chevron_right), - onTap: () => context.push('/recipes/${recipe.id}'), - ); - }, + return GridView.count( + crossAxisCount: _selectedColumns, + children: List.generate( + recipes.length, + (index) { + final recipe = recipes[index]; + return GestureDetector( + onTap: () => context.push('/recipes/${recipe.id}'), + child: Container( + margin: const EdgeInsets.all(4.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8.0), + image: recipe.imageUrl != null + ? DecorationImage( + image: NetworkImage(recipe.imageUrl!), + fit: BoxFit.cover, + ) + : null, + ), + child: recipe.imageUrl == null + ? const Center(child: Icon(Icons.restaurant)) + : null, + ), + ); + }, + ), ); }, ),