Files
food_hub_app/lib/widgets/recipe/detail.dart

228 lines
6.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:food_hub_app/models/recipe.dart' as recipeModel;
class RecipeDetail extends StatefulWidget {
const RecipeDetail({super.key});
@override
State<RecipeDetail> createState() => _RecipeDetailState();
}
class _RecipeDetailState extends State<RecipeDetail> {
@override
void initState() {
super.initState();
}
recipeModel.Recipe recipe = recipeModel.Recipe(
name: '雪糕',
category: '冷饮',
recommendRate: 4,
isShare: true,
recordList: [],
stepList: [
recipeModel.Step(
sort: 1,
content: '将牛奶倒入锅中,小火加热至微沸',
imageUrl: 'https://picsum.photos/400/300?step=1', // 步骤图片URL
),
recipeModel.Step(sort: 2, content: '你好', imageUrl: ''),
],
materialList: [],
);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('菜谱信息', style: TextStyle(color: Colors.white)),
backgroundColor: Theme.of(context).primaryColor,
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: () => Navigator.pop(context),
),
),
backgroundColor: Color(0xFFF5F5F5),
body: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
recipe.name,
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
// 基础信息卡片
_buildInfoCard(
context,
icon: Icons.info,
title: "基础信息",
content: Column(
children: [_buildInfoRow("类别", recipe.category)],
),
),
// 食材信息卡片
_buildInfoCard(
context,
icon: Icons.shopping_cart,
title: "食材信息",
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildMaterialSection("主料", 1),
_buildMaterialSection("配料", 2),
_buildMaterialSection("辅料", 3),
],
),
),
// 步骤信息卡片
_buildInfoCard(
context,
icon: Icons.list,
title: "步骤信息",
content: Column(
children:
recipe.stepList?.map((step) {
return _buildStepSection(step);
}).toList() ??
[],
),
),
// 其他信息卡片
if (recipe.remark != null && recipe.remark!.isNotEmpty)
_buildInfoCard(
context,
icon: Icons.note,
title: "其他信息",
content: Text(
recipe.remark!,
style: const TextStyle(height: 1.5),
),
),
const SizedBox(height: 20),
],
),
),
),
);
}
// 构建食材分类部分
Widget _buildMaterialSection(String title, int type) {
final materials =
recipe.materialList
?.where((material) => material.type == type)
?.toList() ??
[];
if (materials.isEmpty) return const SizedBox.shrink();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(
title,
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
),
),
...materials.map((material) {
return Padding(
padding: const EdgeInsets.only(bottom: 4.0),
child: Row(
children: [
const Icon(Icons.circle, size: 6, color: Colors.grey),
const SizedBox(width: 8),
Text("${material.name} ${material.amount ?? ''}"),
],
),
);
}).toList(),
],
);
}
Widget _buildStepSection(recipeModel.Step step) {
return Padding(
padding: const EdgeInsets.only(bottom: 16.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("${step.sort}"),
SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(step.content, style: const TextStyle(height: 1.4, fontWeight: FontWeight.bold)),
const SizedBox(height: 8),
if (step.imageUrl.isNotEmpty)
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(
step.imageUrl,
width: double.infinity,
height: 180,
fit: BoxFit.contain,
),
),
],
),
),
],
),
);
}
// 构建信息行
Widget _buildInfoRow(String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [Text(label), Text(value)],
),
);
}
// 通用卡片组件
Widget _buildInfoCard(
BuildContext context, {
required IconData icon,
required String title,
required Widget content,
}) {
return Card(
elevation: 0,
color: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
child: Padding(
padding: const EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(icon, color: Theme.of(context).primaryColor),
const SizedBox(width: 8),
Text(
title,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
],
),
SizedBox(height: 5),
content,
],
),
),
);
}
}