Skip to content

Commit 79b23b8

Browse files
committed
👽️ Create Screen Detail and BarCart
1 parent 30e5f6c commit 79b23b8

File tree

2 files changed

+245
-0
lines changed

2 files changed

+245
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:foods_selection_screen/data/food_data.dart';
3+
import 'package:foods_selection_screen/presentation/detail/widgets/cart_bar.dart';
4+
5+
class DetailScreen extends StatefulWidget {
6+
final Item data;
7+
final String tag;
8+
9+
const DetailScreen({super.key, required this.data, required this.tag});
10+
11+
@override
12+
State<DetailScreen> createState() => _DetailScreenState();
13+
}
14+
15+
class _DetailScreenState extends State<DetailScreen>
16+
with SingleTickerProviderStateMixin {
17+
bool showCart = false;
18+
late final AnimationController _rotationController;
19+
20+
@override
21+
void initState() {
22+
super.initState();
23+
_rotationController = AnimationController(
24+
vsync: this,
25+
duration: const Duration(seconds: 10),
26+
)..repeat();
27+
}
28+
29+
@override
30+
void dispose() {
31+
_rotationController.dispose();
32+
super.dispose();
33+
}
34+
35+
@override
36+
Widget build(BuildContext context) {
37+
return Scaffold(
38+
body: Stack(
39+
children: [
40+
SafeArea(
41+
child: Padding(
42+
padding: const EdgeInsets.symmetric(horizontal: 20),
43+
child: Column(
44+
children: [
45+
_buildHeader(context),
46+
const SizedBox(height: 20),
47+
_buildRotatingFoodImage(),
48+
const Spacer(),
49+
_buildFoodTitle(),
50+
const SizedBox(height: 10),
51+
_buildRating(),
52+
const SizedBox(height: 10),
53+
_buildDescription(),
54+
const Spacer(),
55+
_buildPriceAndCartButton(),
56+
const Spacer(),
57+
],
58+
),
59+
),
60+
),
61+
// _buildCartBar(context),
62+
CartBar(
63+
showCart: showCart,
64+
onClose: () => setState(() => showCart = false),
65+
),
66+
],
67+
),
68+
);
69+
}
70+
71+
Widget _buildHeader(BuildContext context) {
72+
return Row(
73+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
74+
children: [
75+
IconButton(
76+
onPressed: () => Navigator.pop(context),
77+
icon: const Icon(Icons.arrow_back_ios),
78+
),
79+
GestureDetector(
80+
onTap: () => setState(() => showCart = true),
81+
child: CircleAvatar(
82+
radius: 20,
83+
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
84+
child: const Icon(Icons.shopping_cart, color: Colors.black),
85+
),
86+
),
87+
],
88+
);
89+
}
90+
91+
Widget _buildRotatingFoodImage() {
92+
return Center(
93+
child: RotationTransition(
94+
turns: _rotationController,
95+
child: Hero(
96+
tag: widget.tag,
97+
child: CircleAvatar(
98+
radius: 150,
99+
backgroundColor: Colors.transparent,
100+
backgroundImage: AssetImage(widget.data.image),
101+
),
102+
),
103+
),
104+
);
105+
}
106+
107+
Widget _buildFoodTitle() {
108+
return Text(
109+
widget.data.title,
110+
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 32),
111+
textAlign: TextAlign.center,
112+
);
113+
}
114+
115+
Widget _buildRating() {
116+
return Row(
117+
mainAxisAlignment: MainAxisAlignment.center,
118+
children: List.generate(
119+
5,
120+
(index) => const Icon(Icons.star, color: Colors.orange, size: 20),
121+
),
122+
);
123+
}
124+
125+
Widget _buildDescription() {
126+
return Text(
127+
widget.data.description,
128+
style: TextStyle(fontSize: 16, color: Colors.grey.shade600),
129+
maxLines: 4,
130+
overflow: TextOverflow.ellipsis,
131+
textAlign: TextAlign.center,
132+
);
133+
}
134+
135+
Widget _buildPriceAndCartButton() {
136+
return Row(
137+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
138+
children: [
139+
Text(
140+
"Giá món: ${widget.data.price} đ",
141+
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
142+
),
143+
ElevatedButton(
144+
onPressed: () {
145+
setState(() => showCart = true);
146+
},
147+
style: ElevatedButton.styleFrom(
148+
backgroundColor: Colors.black,
149+
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
150+
shape: RoundedRectangleBorder(
151+
borderRadius: BorderRadius.circular(10),
152+
),
153+
),
154+
child: const Text(
155+
"Thêm món",
156+
style: TextStyle(
157+
fontSize: 18,
158+
color: Colors.white,
159+
),
160+
),
161+
),
162+
],
163+
);
164+
}
165+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:foods_selection_screen/data/food_data.dart';
3+
4+
class CartBar extends StatelessWidget {
5+
final bool showCart;
6+
final Function() onClose;
7+
8+
const CartBar({
9+
super.key,
10+
required this.showCart,
11+
required this.onClose,
12+
});
13+
14+
@override
15+
Widget build(BuildContext context) {
16+
return AnimatedPositioned(
17+
duration: const Duration(milliseconds: 300),
18+
curve: Curves.easeInOutBack,
19+
right: showCart ? 10 : -150,
20+
top: MediaQuery.sizeOf(context).height * 0.2,
21+
bottom: MediaQuery.sizeOf(context).height * 0.2,
22+
child: Container(
23+
width: 100,
24+
height: MediaQuery.sizeOf(context).height * 0.6,
25+
decoration: BoxDecoration(
26+
color: Colors.white,
27+
borderRadius: BorderRadius.circular(20),
28+
boxShadow: [
29+
BoxShadow(
30+
color: Colors.black.withOpacity(0.1),
31+
blurRadius: 10,
32+
),
33+
],
34+
),
35+
child: SafeArea(
36+
child: Padding(
37+
padding: const EdgeInsets.symmetric(horizontal: 10),
38+
child: Column(
39+
crossAxisAlignment: CrossAxisAlignment.center,
40+
mainAxisAlignment: MainAxisAlignment.center,
41+
children: [
42+
GestureDetector(
43+
onTap: onClose,
44+
child: CircleAvatar(
45+
radius: 22,
46+
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
47+
child: const Icon(Icons.close, color: Colors.black),
48+
),
49+
),
50+
const SizedBox(height: 20),
51+
const Text("Đơn mua",
52+
textAlign: TextAlign.center,
53+
style: TextStyle(fontSize: 18)),
54+
const SizedBox(height: 20),
55+
Expanded(
56+
child: ListView.builder(
57+
itemCount: items.length,
58+
itemBuilder: (context, index) =>
59+
Image.asset(items[index].image, height: 50),
60+
),
61+
),
62+
const SizedBox(height: 20),
63+
const Text("Tổng:",
64+
style:
65+
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
66+
Text("${items.length} món",
67+
style: const TextStyle(fontSize: 14)),
68+
const SizedBox(height: 5),
69+
const Text("250.000 đ",
70+
style:
71+
TextStyle(fontSize: 16, fontWeight: FontWeight.w800)),
72+
const SizedBox(height: 20),
73+
],
74+
),
75+
),
76+
),
77+
),
78+
);
79+
}
80+
}

0 commit comments

Comments
 (0)