Backend:
- Add Groq LLM client (llama-3.3-70b) for recipe generation with JSON
retry strategy (retries only on parse errors, not API errors)
- Add Pexels client for parallel photo search per recipe
- Add saved_recipes table (migration 004) with JSONB fields
- Add GET /recommendations endpoint (profile-aware prompt building)
- Add POST/GET/GET{id}/DELETE /saved-recipes CRUD endpoints
- Wire gemini, pexels, recommendation, savedrecipe packages in main.go
Flutter:
- Add Recipe, SavedRecipe models with json_serializable
- Add RecipeService (getRecommendations, getSavedRecipes, save, delete)
- Add RecommendationsNotifier and SavedRecipesNotifier (Riverpod)
- Add RecommendationsScreen with skeleton loading and refresh FAB
- Add RecipeDetailScreen (SliverAppBar, nutrition tooltip, steps with timer)
- Add SavedRecipesScreen with Dismissible swipe-to-delete and empty state
- Update RecipesScreen to TabBar (Recommendations / Saved)
- Add /recipe-detail route outside ShellRoute (no bottom nav)
- Extend ApiClient with getList() and deleteVoid()
Project:
- Add CLAUDE.md with English-only rule for comments and commit messages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
53 lines
1.2 KiB
Dart
53 lines
1.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import 'recommendations_screen.dart';
|
|
import 'saved_recipes_screen.dart';
|
|
|
|
/// Root screen for the Recipes tab — two sub-tabs: Recommendations and Saved.
|
|
class RecipesScreen extends StatefulWidget {
|
|
const RecipesScreen({super.key});
|
|
|
|
@override
|
|
State<RecipesScreen> createState() => _RecipesScreenState();
|
|
}
|
|
|
|
class _RecipesScreenState extends State<RecipesScreen>
|
|
with SingleTickerProviderStateMixin {
|
|
late final TabController _tabController;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_tabController = TabController(length: 2, vsync: this);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_tabController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Рецепты'),
|
|
bottom: TabBar(
|
|
controller: _tabController,
|
|
tabs: const [
|
|
Tab(text: 'Рекомендации'),
|
|
Tab(text: 'Сохранённые'),
|
|
],
|
|
),
|
|
),
|
|
body: TabBarView(
|
|
controller: _tabController,
|
|
children: const [
|
|
RecommendationsScreen(),
|
|
SavedRecipesScreen(),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|