Skip to content

Commit 8bded24

Browse files
committed
Tambahkan konten list category meals di UI Home Screen
1 parent 7cf2c83 commit 8bded24

File tree

3 files changed

+201
-92
lines changed

3 files changed

+201
-92
lines changed

lib/src/blocs/home_bloc.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:food_recipe/src/models/categories/categories.dart';
12
import 'package:food_recipe/src/models/latest/latest_meals.dart';
23
import 'package:food_recipe/src/resources/repository.dart';
34

@@ -8,6 +9,10 @@ class HomeBloc {
89
return await _repository.getLatestMeals();
910
}
1011

12+
Future<Categories> getCategories() async {
13+
return await _repository.getCategories();
14+
}
15+
1116
dispose() {
1217
// TODO: do something in here
1318
}

lib/src/ui/home/home_screen.dart

Lines changed: 194 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import 'dart:io' show Platform;
2+
3+
import 'package:flutter/cupertino.dart';
14
import 'package:flutter/material.dart';
25
import 'package:food_recipe/src/blocs/home_bloc.dart';
6+
import 'package:food_recipe/src/models/categories/categories.dart';
37
import 'package:food_recipe/src/models/latest/latest_meals.dart';
48
import 'package:food_recipe/values/color_assets.dart';
59

@@ -51,7 +55,7 @@ class _HomeScreenState extends State<HomeScreen> {
5155
child: Column(
5256
crossAxisAlignment: CrossAxisAlignment.start,
5357
children: <Widget>[
54-
Padding(padding: EdgeInsets.only(top: 24.0 + mediaQuery.padding.top)),
58+
Padding(padding: EdgeInsets.only(top: 16.0 + mediaQuery.padding.top)),
5559
Text(
5660
"What are you\nCooking today ?",
5761
style: Theme.of(context).textTheme.display1.merge(
@@ -63,113 +67,211 @@ class _HomeScreenState extends State<HomeScreen> {
6367
),
6468
),
6569
Padding(padding: EdgeInsets.only(top: 16.0)),
66-
Container(
67-
decoration: BoxDecoration(
68-
borderRadius: BorderRadius.circular(36.0),
69-
color: Color(0x2FFFFFFF),
70-
),
71-
child: Padding(
72-
padding: const EdgeInsets.symmetric(
73-
horizontal: 12.0,
74-
vertical: 8.0,
75-
),
76-
child: Row(
77-
children: <Widget>[
78-
Icon(
79-
Icons.search,
80-
color: Colors.white,
81-
),
82-
Padding(padding: EdgeInsets.only(right: 8.0)),
83-
Expanded(
84-
child: TextField(
85-
decoration: InputDecoration.collapsed(
86-
hintText: "Search...",
87-
hintStyle: TextStyle(
88-
color: Colors.white70,
89-
),
90-
),
91-
style: TextStyle(color: Colors.white),
92-
maxLines: 1,
93-
),
94-
),
95-
],
96-
),
97-
),
98-
),
70+
_buildTextFieldSearchMeals(),
9971
Padding(padding: EdgeInsets.only(top: 24.0)),
10072
Text("Latest Recipe",
10173
style: Theme.of(context)
10274
.textTheme
10375
.title
10476
.merge(TextStyle(color: Colors.white))),
10577
Padding(padding: EdgeInsets.only(top: 8.0)),
106-
FutureBuilder(
107-
future: homeBloc.getLatestMeals(),
108-
builder:
109-
(BuildContext context, AsyncSnapshot<LatestMeals> snapshot) {
110-
if (snapshot.hasData) {
111-
var latestMeals = snapshot.data;
78+
_buildListViewLatestRecipe(mediaQuery),
79+
Padding(padding: EdgeInsets.only(top: 24.0)),
80+
Text("Category",
81+
style: Theme.of(context)
82+
.textTheme
83+
.title
84+
.merge(TextStyle(color: ColorAssets.primaryTextColor))),
85+
Padding(padding: EdgeInsets.only(top: 8.0)),
86+
_buildListViewCategory(),
87+
],
88+
),
89+
);
90+
}
91+
92+
Widget _buildListViewCategory() {
93+
return FutureBuilder(
94+
future: homeBloc.getCategories(),
95+
builder: (BuildContext context, AsyncSnapshot<Categories> snapshot) {
96+
if (snapshot.hasData) {
97+
int numberItem = 0;
98+
Categories categories = snapshot.data;
99+
return Container(
100+
height: 136.0,
101+
child: ListView.builder(
102+
scrollDirection: Axis.horizontal,
103+
itemCount: categories.categoryItems.length,
104+
itemBuilder: (context, index) {
105+
numberItem += 1;
106+
if (numberItem > 3) {
107+
numberItem = 1;
108+
}
109+
var category = categories.categoryItems[index];
112110
return Container(
113-
height: 256.0,
114-
child: ListView.builder(
115-
scrollDirection: Axis.horizontal,
116-
itemCount: latestMeals.latestMealsItems.length,
117-
itemBuilder: (context, index) {
118-
var latestMealsItem = latestMeals.latestMealsItems[index];
119-
return Padding(
120-
padding: const EdgeInsets.only(right: 8.0),
121-
child: Card(
122-
shape: RoundedRectangleBorder(
123-
borderRadius: BorderRadius.circular(16.0)),
124-
child: ClipRRect(
125-
borderRadius: BorderRadius.only(
126-
topLeft: Radius.circular(16.0),
127-
topRight: Radius.circular(16.0),
111+
width: 136.0,
112+
child: Padding(
113+
padding: const EdgeInsets.only(right: 4.0),
114+
child: Card(
115+
shape: RoundedRectangleBorder(
116+
borderRadius: BorderRadius.circular(16.0)),
117+
color: _setColorItemCategory(numberItem),
118+
child: Padding(
119+
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 12.0),
120+
child: Column(
121+
children: <Widget>[
122+
Text(
123+
category.strCategory,
124+
textAlign: TextAlign.center,
125+
style: TextStyle(
126+
color: Colors.white,
127+
),
128128
),
129-
child: Column(
130-
crossAxisAlignment: CrossAxisAlignment.start,
131-
children: <Widget>[
132-
Container(
133-
child: FadeInImage(
134-
image: NetworkImage(
135-
latestMealsItem.strMealThumb,
136-
),
137-
placeholder: AssetImage(
138-
"assets/images/img_placeholder.jpg",
139-
),
140-
fit: BoxFit.cover,
141-
),
142-
width: mediaQuery.size.width - 96.0,
143-
height: 192.0,
144-
),
145-
Padding(
146-
padding: const EdgeInsets.all(8.0),
147-
child: Text(latestMealsItem.strMeal,
148-
maxLines: 2,
149-
style:
150-
Theme.of(context).textTheme.subhead),
129+
Padding(padding: const EdgeInsets.only(top: 8.0)),
130+
Container(
131+
width: 136.0,
132+
height: 72.0,
133+
child: FadeInImage(
134+
fit: BoxFit.cover,
135+
image: NetworkImage(
136+
category.strCategoryThumb,
151137
),
152-
],
138+
placeholder: AssetImage("assets/images/img_placeholder.jpg"),
139+
),
153140
),
154-
),
141+
],
155142
),
156-
);
157-
},
143+
),
144+
),
158145
),
159146
);
160-
} else if (snapshot.hasError) {
161-
return Text(snapshot.error.toString());
162-
}
163-
return Container(
164-
height: 128.0,
165-
child: Center(
166-
child: CircularProgressIndicator(),
147+
},
148+
),
149+
);
150+
} else if (snapshot.hasError) {
151+
return Text(snapshot.error.toString());
152+
}
153+
return Center(child: _buildCircularProgressIndicator());
154+
},
155+
);
156+
}
157+
158+
Widget _buildListViewLatestRecipe(MediaQueryData mediaQuery) {
159+
return FutureBuilder(
160+
future: homeBloc.getLatestMeals(),
161+
builder: (BuildContext context, AsyncSnapshot<LatestMeals> snapshot) {
162+
if (snapshot.hasData) {
163+
var latestMeals = snapshot.data;
164+
return Container(
165+
height: 256.0,
166+
child: ListView.builder(
167+
scrollDirection: Axis.horizontal,
168+
itemCount: latestMeals.latestMealsItems.length,
169+
itemBuilder: (context, index) {
170+
var latestMealsItem = latestMeals.latestMealsItems[index];
171+
return Padding(
172+
padding: const EdgeInsets.only(right: 8.0),
173+
child: Card(
174+
shape: RoundedRectangleBorder(
175+
borderRadius: BorderRadius.circular(16.0)),
176+
child: ClipRRect(
177+
borderRadius: BorderRadius.only(
178+
topLeft: Radius.circular(16.0),
179+
topRight: Radius.circular(16.0),
180+
),
181+
child: Column(
182+
crossAxisAlignment: CrossAxisAlignment.start,
183+
children: <Widget>[
184+
Container(
185+
child: FadeInImage(
186+
image: NetworkImage(
187+
latestMealsItem.strMealThumb,
188+
),
189+
placeholder: AssetImage(
190+
"assets/images/img_placeholder.jpg",
191+
),
192+
fit: BoxFit.cover,
193+
),
194+
width: mediaQuery.size.width - 96.0,
195+
height: 192.0,
196+
),
197+
Padding(
198+
padding: const EdgeInsets.all(8.0),
199+
child: Text(latestMealsItem.strMeal,
200+
maxLines: 2,
201+
style: Theme.of(context).textTheme.subhead),
202+
),
203+
],
204+
),
205+
),
206+
),
207+
);
208+
},
209+
),
210+
);
211+
} else if (snapshot.hasError) {
212+
return Text(snapshot.error.toString());
213+
}
214+
return Container(
215+
height: 128.0,
216+
child: Center(
217+
child: _buildCircularProgressIndicator(),
218+
),
219+
);
220+
},
221+
);
222+
}
223+
224+
Widget _buildTextFieldSearchMeals() {
225+
return Container(
226+
decoration: BoxDecoration(
227+
borderRadius: BorderRadius.circular(36.0),
228+
color: Color(0x2FFFFFFF),
229+
),
230+
child: Padding(
231+
padding: const EdgeInsets.symmetric(
232+
horizontal: 12.0,
233+
vertical: 8.0,
234+
),
235+
child: Row(
236+
children: <Widget>[
237+
Icon(
238+
Icons.search,
239+
color: Colors.white,
240+
),
241+
Padding(padding: EdgeInsets.only(right: 8.0)),
242+
Expanded(
243+
child: TextField(
244+
decoration: InputDecoration.collapsed(
245+
hintText: "Search...",
246+
hintStyle: TextStyle(
247+
color: Colors.white70,
248+
),
167249
),
168-
);
169-
},
170-
)
171-
],
250+
style: TextStyle(color: Colors.white),
251+
maxLines: 1,
252+
),
253+
),
254+
],
255+
),
172256
),
173257
);
174258
}
259+
260+
Widget _buildCircularProgressIndicator() {
261+
if (Platform.isIOS) {
262+
return CupertinoActivityIndicator();
263+
} else {
264+
return CircularProgressIndicator();
265+
}
266+
}
267+
268+
Color _setColorItemCategory(int number) {
269+
if (number == 1) {
270+
return ColorAssets.accentColor;
271+
} else if (number == 2) {
272+
return ColorAssets.secondColorCategoryItem;
273+
} else {
274+
return ColorAssets.thirdColorCategoryItem;
275+
}
276+
}
175277
}

lib/values/color_assets.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ class ColorAssets {
44
static final Color primarySwatchColor = Color(0xFFE8364B);
55
static final Color accentColor = Color(0xFFEE8F3B);
66
static final Color primaryTextColor = Colors.grey[900];
7+
static final Color secondColorCategoryItem = Color(0xFF3FD231);
8+
static final Color thirdColorCategoryItem = Color(0xFFF03F7D);
79
}

0 commit comments

Comments
 (0)