Create Home Screen and Add other Fiture
This commit is contained in:
parent
7b54413183
commit
8bab6bdb7d
25 changed files with 684 additions and 45 deletions
BIN
assets/Product_1.webp
Normal file
BIN
assets/Product_1.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 176 KiB |
BIN
assets/Product_2.webp
Normal file
BIN
assets/Product_2.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 139 KiB |
BIN
assets/Product_3.webp
Normal file
BIN
assets/Product_3.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 201 KiB |
BIN
assets/fonts/Gordita_Bold.otf
Normal file
BIN
assets/fonts/Gordita_Bold.otf
Normal file
Binary file not shown.
BIN
assets/fonts/Gordita_Light.otf
Normal file
BIN
assets/fonts/Gordita_Light.otf
Normal file
Binary file not shown.
BIN
assets/fonts/Gordita_Medium.otf
Normal file
BIN
assets/fonts/Gordita_Medium.otf
Normal file
Binary file not shown.
BIN
assets/fonts/Gordita_Regular.otf
Normal file
BIN
assets/fonts/Gordita_Regular.otf
Normal file
Binary file not shown.
BIN
assets/fonts/Gordita_Thin.otf
Normal file
BIN
assets/fonts/Gordita_Thin.otf
Normal file
Binary file not shown.
24
lib/components/Category.dart
Normal file
24
lib/components/Category.dart
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
class Category {
|
||||||
|
final String icon, title;
|
||||||
|
|
||||||
|
Category({required this.icon, required this.title});
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Category> demo_categories = [
|
||||||
|
Category(
|
||||||
|
icon: "assets/icons/dress.svg",
|
||||||
|
title: "Dress",
|
||||||
|
),
|
||||||
|
Category(
|
||||||
|
icon: "assets/icons/shirt.svg",
|
||||||
|
title: "Shirt",
|
||||||
|
),
|
||||||
|
Category(
|
||||||
|
icon: "assets/icons/pants.svg",
|
||||||
|
title: "Pants",
|
||||||
|
),
|
||||||
|
Category(
|
||||||
|
icon: "assets/icons/Tshirt.svg",
|
||||||
|
title: "Tshirt",
|
||||||
|
),
|
||||||
|
];
|
67
lib/components/categories.dart
Normal file
67
lib/components/categories.dart
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:nekoya_flutter/components/Category.dart';
|
||||||
|
|
||||||
|
import '../../../constants.dart';
|
||||||
|
|
||||||
|
class Categories extends StatelessWidget {
|
||||||
|
const Categories({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
height: 84,
|
||||||
|
child: ListView.separated(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
itemCount: demo_categories.length,
|
||||||
|
itemBuilder: (context, index) => CategoryCard(
|
||||||
|
icon: demo_categories[index].icon,
|
||||||
|
title: demo_categories[index].title,
|
||||||
|
press: () {},
|
||||||
|
),
|
||||||
|
separatorBuilder: (context, index) =>
|
||||||
|
const SizedBox(width: defaultPadding),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CategoryCard extends StatelessWidget {
|
||||||
|
const CategoryCard({
|
||||||
|
Key? key,
|
||||||
|
required this.icon,
|
||||||
|
required this.title,
|
||||||
|
required this.press,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final String icon, title;
|
||||||
|
final VoidCallback press;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return OutlinedButton(
|
||||||
|
onPressed: press,
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(defaultBorderRadius)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: defaultPadding / 2, horizontal: defaultPadding / 4),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(icon),
|
||||||
|
const SizedBox(height: defaultPadding / 2),
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: Theme.of(context).textTheme.subtitle2,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
29
lib/components/color_dot.dart
Normal file
29
lib/components/color_dot.dart
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../constants.dart';
|
||||||
|
|
||||||
|
class ColorDot extends StatelessWidget {
|
||||||
|
const ColorDot({
|
||||||
|
Key? key,
|
||||||
|
required this.color,
|
||||||
|
required this.isActive,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final Color color;
|
||||||
|
final bool isActive;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(defaultPadding / 4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: isActive ? primaryColor : Colors.transparent),
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
child: CircleAvatar(
|
||||||
|
radius: 10,
|
||||||
|
backgroundColor: color,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
119
lib/components/details_screen.dart
Normal file
119
lib/components/details_screen.dart
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:nekoya_flutter/constants.dart';
|
||||||
|
import 'package:nekoya_flutter/screens/productcoba.dart';
|
||||||
|
import 'package:nekoya_flutter/screens/products.dart';
|
||||||
|
|
||||||
|
import 'package:nekoya_flutter/components/color_dot.dart';
|
||||||
|
|
||||||
|
class DetailsScreen extends StatelessWidget {
|
||||||
|
const DetailsScreen({Key? key, required this.product}) : super(key: key);
|
||||||
|
|
||||||
|
final Product product;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFEFEFF2),
|
||||||
|
appBar: AppBar(
|
||||||
|
leading: const BackButton(color: Colors.black),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: CircleAvatar(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
"assets/icons/Heart.svg",
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
product.image,
|
||||||
|
height: MediaQuery.of(context).size.height * 0.4,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
const SizedBox(height: defaultPadding * 1.5),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.fromLTRB(defaultPadding,
|
||||||
|
defaultPadding * 2, defaultPadding, defaultPadding),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(defaultBorderRadius * 3),
|
||||||
|
topRight: Radius.circular(defaultBorderRadius * 3),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
product.title,
|
||||||
|
style: Theme.of(context).textTheme.headline6,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: defaultPadding),
|
||||||
|
Text(
|
||||||
|
"\$" + product.price.toString(),
|
||||||
|
style: Theme.of(context).textTheme.headline6,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: defaultPadding),
|
||||||
|
child: Text(
|
||||||
|
"A Henley shirt is a collarless pullover shirt, by a round neckline and a placket about 3 to 5 inches (8 to 13 cm) long and usually having 2–5 buttons.",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Colors",
|
||||||
|
style: Theme.of(context).textTheme.subtitle2,
|
||||||
|
),
|
||||||
|
const SizedBox(height: defaultPadding / 2),
|
||||||
|
Row(
|
||||||
|
children: const [
|
||||||
|
ColorDot(
|
||||||
|
color: Color(0xFFBEE8EA),
|
||||||
|
isActive: false,
|
||||||
|
),
|
||||||
|
ColorDot(
|
||||||
|
color: Color(0xFF141B4A),
|
||||||
|
isActive: true,
|
||||||
|
),
|
||||||
|
ColorDot(
|
||||||
|
color: Color(0xFFF4E5C3),
|
||||||
|
isActive: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: defaultPadding * 2),
|
||||||
|
Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 200,
|
||||||
|
height: 48,
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
primary: primaryColor,
|
||||||
|
shape: const StadiumBorder()),
|
||||||
|
child: const Text("Add to Cart"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import 'package:nekoya_flutter/screens/cart.dart';
|
||||||
import 'package:nekoya_flutter/screens/register.dart';
|
import 'package:nekoya_flutter/screens/register.dart';
|
||||||
import 'package:nekoya_flutter/screens/sessions.dart';
|
import 'package:nekoya_flutter/screens/sessions.dart';
|
||||||
import 'package:nekoya_flutter/screens/transactions.dart';
|
import 'package:nekoya_flutter/screens/transactions.dart';
|
||||||
|
import 'package:nekoya_flutter/screens/home_screen.dart';
|
||||||
|
|
||||||
class Menu extends StatefulWidget {
|
class Menu extends StatefulWidget {
|
||||||
const Menu({Key? key, required this.initialScreen}) : super(key: key);
|
const Menu({Key? key, required this.initialScreen}) : super(key: key);
|
||||||
|
@ -65,14 +66,15 @@ class _MenuState extends State<Menu> {
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
checkSessionExist().then((isLoggedIn) {
|
checkSessionExist().then((isLoggedIn) {
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
_selectedWidget = const Sessions();
|
_selectedWidget = const Sessions();
|
||||||
} else {
|
} else {
|
||||||
_selectedIndex = oldSelectedIndex;
|
_selectedIndex = oldSelectedIndex;
|
||||||
Navigator.push(context, MaterialPageRoute(builder: (context) => const Login()));
|
Navigator.push(context,
|
||||||
|
MaterialPageRoute(builder: (context) => const Login()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (index == 1) {
|
} else if (index == 1) {
|
||||||
_selectedWidget = const Payment();
|
_selectedWidget = const HomeScreen();
|
||||||
} else if (index == 2) {
|
} else if (index == 2) {
|
||||||
_selectedWidget = const Products();
|
_selectedWidget = const Products();
|
||||||
} else if (index == 3) {
|
} else if (index == 3) {
|
||||||
|
@ -80,13 +82,14 @@ class _MenuState extends State<Menu> {
|
||||||
} else if (index == 4) {
|
} else if (index == 4) {
|
||||||
checkSessionExist().then((isLoggedIn) {
|
checkSessionExist().then((isLoggedIn) {
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
_selectedWidget = const Transactions();
|
_selectedWidget = const Transactions();
|
||||||
} else {
|
} else {
|
||||||
_selectedIndex = oldSelectedIndex;
|
_selectedIndex = oldSelectedIndex;
|
||||||
Navigator.push(context, MaterialPageRoute(builder: (context) => const Login()));
|
Navigator.push(context,
|
||||||
|
MaterialPageRoute(builder: (context) => const Login()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
55
lib/components/new_arrival_products.dart
Normal file
55
lib/components/new_arrival_products.dart
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:nekoya_flutter/screens/productcoba.dart';
|
||||||
|
import 'package:nekoya_flutter/components/details_screen.dart';
|
||||||
|
|
||||||
|
import '../../../constants.dart';
|
||||||
|
import 'product_card.dart';
|
||||||
|
import 'section_title.dart';
|
||||||
|
|
||||||
|
class NewArrivalProducts extends StatelessWidget {
|
||||||
|
const NewArrivalProducts({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: defaultPadding),
|
||||||
|
child: SectionTitle(
|
||||||
|
title: "New Arrival",
|
||||||
|
pressSeeAll: () {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SingleChildScrollView(
|
||||||
|
physics: const BouncingScrollPhysics(
|
||||||
|
parent: AlwaysScrollableScrollPhysics()),
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
child: Row(
|
||||||
|
children: List.generate(
|
||||||
|
demo_product.length,
|
||||||
|
(index) => Padding(
|
||||||
|
padding: const EdgeInsets.only(right: defaultPadding),
|
||||||
|
child: ProductCard(
|
||||||
|
title: demo_product[index].title,
|
||||||
|
image: demo_product[index].image,
|
||||||
|
price: demo_product[index].price,
|
||||||
|
bgColor: demo_product[index].bgColor,
|
||||||
|
press: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
DetailsScreen(product: demo_product[index]),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
47
lib/components/popular_products.dart
Normal file
47
lib/components/popular_products.dart
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:nekoya_flutter/screens/productcoba.dart';
|
||||||
|
|
||||||
|
import '../../../constants.dart';
|
||||||
|
import 'product_card.dart';
|
||||||
|
import 'section_title.dart';
|
||||||
|
|
||||||
|
class PopularProducts extends StatelessWidget {
|
||||||
|
const PopularProducts({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: defaultPadding),
|
||||||
|
child: SectionTitle(
|
||||||
|
title: "Popular",
|
||||||
|
pressSeeAll: () {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SingleChildScrollView(
|
||||||
|
physics: const BouncingScrollPhysics(
|
||||||
|
parent: AlwaysScrollableScrollPhysics()),
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
child: Row(
|
||||||
|
children: List.generate(
|
||||||
|
demo_product.length,
|
||||||
|
(index) => Padding(
|
||||||
|
padding: const EdgeInsets.only(right: defaultPadding),
|
||||||
|
child: ProductCard(
|
||||||
|
title: demo_product[index].title,
|
||||||
|
image: demo_product[index].image,
|
||||||
|
price: demo_product[index].price,
|
||||||
|
bgColor: demo_product[index].bgColor,
|
||||||
|
press: () {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
65
lib/components/product_card.dart
Normal file
65
lib/components/product_card.dart
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../constants.dart';
|
||||||
|
|
||||||
|
class ProductCard extends StatelessWidget {
|
||||||
|
const ProductCard({
|
||||||
|
Key? key,
|
||||||
|
required this.image,
|
||||||
|
required this.title,
|
||||||
|
required this.price,
|
||||||
|
required this.press,
|
||||||
|
required this.bgColor,
|
||||||
|
}) : super(key: key);
|
||||||
|
final String image, title;
|
||||||
|
final VoidCallback press;
|
||||||
|
final int price;
|
||||||
|
final Color bgColor;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: press,
|
||||||
|
child: Container(
|
||||||
|
width: 154,
|
||||||
|
padding: const EdgeInsets.all(defaultPadding / 2),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(defaultBorderRadius)),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: bgColor,
|
||||||
|
borderRadius: const BorderRadius.all(
|
||||||
|
Radius.circular(defaultBorderRadius)),
|
||||||
|
),
|
||||||
|
child: Image.asset(
|
||||||
|
image,
|
||||||
|
height: 132,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: defaultPadding / 2),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
style: const TextStyle(color: Colors.black),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: defaultPadding / 4),
|
||||||
|
Text(
|
||||||
|
"\$" + price.toString(),
|
||||||
|
style: Theme.of(context).textTheme.subtitle2,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:nekoya_flutter/api/api.dart';
|
import 'package:nekoya_flutter/api/api.dart';
|
||||||
import 'package:nekoya_flutter/data/cart.dart';
|
import 'package:nekoya_flutter/data/cart.dart';
|
||||||
|
import 'package:nekoya_flutter/screens/productcoba.dart';
|
||||||
import 'package:nekoya_flutter/utils/utils.dart';
|
import 'package:nekoya_flutter/utils/utils.dart';
|
||||||
|
|
||||||
Widget makeDismissible({required context, required Widget child}) =>
|
Widget makeDismissible({required context, required Widget child}) =>
|
||||||
|
|
55
lib/components/search_form.dart
Normal file
55
lib/components/search_form.dart
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
|
||||||
|
import '../../../constants.dart';
|
||||||
|
|
||||||
|
const OutlineInputBorder outlineInputBorder = OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||||
|
borderSide: BorderSide.none,
|
||||||
|
);
|
||||||
|
|
||||||
|
class SearchForm extends StatelessWidget {
|
||||||
|
const SearchForm({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Form(
|
||||||
|
child: TextFormField(
|
||||||
|
onSaved: (value) {},
|
||||||
|
decoration: InputDecoration(
|
||||||
|
filled: true,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
hintText: "Search items...",
|
||||||
|
border: outlineInputBorder,
|
||||||
|
enabledBorder: outlineInputBorder,
|
||||||
|
focusedBorder: outlineInputBorder,
|
||||||
|
errorBorder: outlineInputBorder,
|
||||||
|
prefixIcon: Padding(
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
child: SvgPicture.asset("assets/icons/Search.svg"),
|
||||||
|
),
|
||||||
|
suffixIcon: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: defaultPadding, vertical: defaultPadding / 2),
|
||||||
|
child: SizedBox(
|
||||||
|
width: 48,
|
||||||
|
height: 48,
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
primary: primaryColor,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {},
|
||||||
|
child: SvgPicture.asset("assets/icons/Filter.svg"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
34
lib/components/section_title.dart
Normal file
34
lib/components/section_title.dart
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SectionTitle extends StatelessWidget {
|
||||||
|
const SectionTitle({
|
||||||
|
Key? key,
|
||||||
|
required this.title,
|
||||||
|
required this.pressSeeAll,
|
||||||
|
}) : super(key: key);
|
||||||
|
final String title;
|
||||||
|
final VoidCallback pressSeeAll;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: Theme.of(context).textTheme.subtitle1!.copyWith(
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: pressSeeAll,
|
||||||
|
child: const Text(
|
||||||
|
"See All",
|
||||||
|
style: TextStyle(color: Colors.black54),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
7
lib/constants.dart
Normal file
7
lib/constants.dart
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
const Color primaryColor = Color(0xFFF67952);
|
||||||
|
const Color bgColor = Color(0xFFFBFBFD);
|
||||||
|
|
||||||
|
const double defaultPadding = 16.0;
|
||||||
|
const double defaultBorderRadius = 12.0;
|
69
lib/screens/home_screen.dart
Normal file
69
lib/screens/home_screen.dart
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:nekoya_flutter/constants.dart';
|
||||||
|
|
||||||
|
import 'package:nekoya_flutter/components/categories.dart';
|
||||||
|
import 'package:nekoya_flutter/components/new_arrival_products.dart';
|
||||||
|
import 'package:nekoya_flutter/components/popular_products.dart';
|
||||||
|
import 'package:nekoya_flutter/components/search_form.dart';
|
||||||
|
|
||||||
|
class HomeScreen extends StatelessWidget {
|
||||||
|
const HomeScreen({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
leading: IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: SvgPicture.asset("assets/icons/menu.svg"),
|
||||||
|
),
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset("assets/icons/Location.svg"),
|
||||||
|
const SizedBox(width: defaultPadding / 2),
|
||||||
|
Text(
|
||||||
|
"15/2 New Texas",
|
||||||
|
style: Theme.of(context).textTheme.bodyText1,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: SvgPicture.asset("assets/icons/Notification.svg"),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
physics: const BouncingScrollPhysics(
|
||||||
|
parent: AlwaysScrollableScrollPhysics()),
|
||||||
|
padding: const EdgeInsets.all(defaultPadding),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Explore",
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.headline4!
|
||||||
|
.copyWith(fontWeight: FontWeight.w500, color: Colors.black),
|
||||||
|
),
|
||||||
|
const Text(
|
||||||
|
"best Outfits for you",
|
||||||
|
style: TextStyle(fontSize: 18),
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: defaultPadding),
|
||||||
|
child: SearchForm(),
|
||||||
|
),
|
||||||
|
const Categories(),
|
||||||
|
const NewArrivalProducts(),
|
||||||
|
const PopularProducts(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
40
lib/screens/productcoba.dart
Normal file
40
lib/screens/productcoba.dart
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Product {
|
||||||
|
final String image, title;
|
||||||
|
final int price;
|
||||||
|
final Color bgColor;
|
||||||
|
|
||||||
|
Product({
|
||||||
|
required this.image,
|
||||||
|
required this.title,
|
||||||
|
required this.price,
|
||||||
|
this.bgColor = const Color(0xFFEFEFF2),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Product> demo_product = [
|
||||||
|
Product(
|
||||||
|
image: "assets/Product_2.webp",
|
||||||
|
title: "Long Sleeve Shirts",
|
||||||
|
price: 165,
|
||||||
|
bgColor: const Color(0xFFFEFBF9),
|
||||||
|
),
|
||||||
|
Product(
|
||||||
|
image: "assets/Product_1.webp",
|
||||||
|
title: "Casual Henley Shirts",
|
||||||
|
price: 99,
|
||||||
|
),
|
||||||
|
Product(
|
||||||
|
image: "assets/Product_2.webp",
|
||||||
|
title: "Curved Hem Shirts",
|
||||||
|
price: 180,
|
||||||
|
bgColor: const Color(0xFFF8FEFB),
|
||||||
|
),
|
||||||
|
Product(
|
||||||
|
image: "assets/Product_3.webp",
|
||||||
|
title: "Casual Nolin",
|
||||||
|
price: 149,
|
||||||
|
bgColor: const Color(0xFFEEEEED),
|
||||||
|
),
|
||||||
|
];
|
|
@ -1,7 +1,6 @@
|
||||||
import 'package:responsify/responsify.dart';
|
import 'package:responsify/responsify.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
|
||||||
import 'package:nekoya_flutter/api/api.dart';
|
import 'package:nekoya_flutter/api/api.dart';
|
||||||
import 'package:nekoya_flutter/components/product_box.dart';
|
import 'package:nekoya_flutter/components/product_box.dart';
|
||||||
import 'package:nekoya_flutter/components/product_detail.dart';
|
import 'package:nekoya_flutter/components/product_detail.dart';
|
||||||
|
@ -24,41 +23,45 @@ class _ProductsState extends State<Products> {
|
||||||
backgroundColor: const Color(0xff212226),
|
backgroundColor: const Color(0xff212226),
|
||||||
),
|
),
|
||||||
body: ResponsiveUiWidget(
|
body: ResponsiveUiWidget(
|
||||||
targetOlderComputers: true,
|
targetOlderComputers: true,
|
||||||
builder: (context, deviceInformation) {
|
builder: (context, deviceInformation) {
|
||||||
return FutureBuilder<dynamic>(
|
return FutureBuilder<dynamic>(
|
||||||
future: getProducts(),
|
future: getProducts(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
var data = snapshot.data;
|
var data = snapshot.data;
|
||||||
return GridView.count(
|
return GridView.count(
|
||||||
crossAxisCount: deviceInformation.orientation == Orientation.portrait ? 2 : 5,
|
crossAxisCount:
|
||||||
children: List.generate(data!.length, (index) {
|
deviceInformation.orientation == Orientation.portrait
|
||||||
return ProductBox(
|
? 2
|
||||||
imageUrl: "https://nekoya.moe.team/img/${data[index]['IMAGE']}",
|
: 5,
|
||||||
|
children: List.generate(data!.length, (index) {
|
||||||
|
return ProductBox(
|
||||||
|
imageUrl:
|
||||||
|
"https://nekoya.moe.team/img/${data[index]['IMAGE']}",
|
||||||
title: data[index]['TITLE'],
|
title: data[index]['TITLE'],
|
||||||
callback: () {
|
callback: () {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => productDetail(context, data[index]['ID']),
|
builder: (context) =>
|
||||||
|
productDetail(context, data[index]['ID']),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return const Center(
|
return const Center(
|
||||||
child: CircularProgressIndicator(
|
child: CircularProgressIndicator(
|
||||||
color: Color(0xff8B0000),
|
color: Color(0xff8B0000),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
21
pubspec.lock
21
pubspec.lock
|
@ -167,6 +167,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
|
flutter_svg:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_svg
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.3"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -268,6 +275,20 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.8.1"
|
||||||
|
path_drawing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_drawing
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
|
path_parsing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_parsing
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
path_provider:
|
path_provider:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
22
pubspec.yaml
22
pubspec.yaml
|
@ -40,6 +40,7 @@ dependencies:
|
||||||
lottie: ^1.3.0
|
lottie: ^1.3.0
|
||||||
responsify: ^1.0.0+5
|
responsify: ^1.0.0+5
|
||||||
shared_preferences: ^2.0.13
|
shared_preferences: ^2.0.13
|
||||||
|
flutter_svg: ^1.0.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^2.0.1
|
flutter_lints: ^2.0.1
|
||||||
|
@ -75,17 +76,16 @@ flutter:
|
||||||
# "family" key with the font family name, and a "fonts" key with a
|
# "family" key with the font family name, and a "fonts" key with a
|
||||||
# list giving the asset and other descriptors for the font. For
|
# list giving the asset and other descriptors for the font. For
|
||||||
# example:
|
# example:
|
||||||
# fonts:
|
fonts:
|
||||||
# - family: Schyler
|
- family: Gordita
|
||||||
# fonts:
|
fonts:
|
||||||
# - asset: fonts/Schyler-Regular.ttf
|
- asset: assets/fonts/Gordita_Regular.otf
|
||||||
# - asset: fonts/Schyler-Italic.ttf
|
- asset: assets/fonts/Gordita_Medium.otf
|
||||||
# style: italic
|
weight: 500
|
||||||
# - family: Trajan Pro
|
- asset: assets/fonts/Gordita_Bold.otf
|
||||||
# fonts:
|
weight: 700
|
||||||
# - asset: fonts/TrajanPro.ttf
|
- asset: assets/fonts/Gordita_Light.otf
|
||||||
# - asset: fonts/TrajanPro_Bold.ttf
|
weight: 300
|
||||||
# weight: 700
|
|
||||||
#
|
#
|
||||||
# For details regarding fonts from package dependencies,
|
# For details regarding fonts from package dependencies,
|
||||||
# see https://flutter.dev/custom-fonts/#from-packages
|
# see https://flutter.dev/custom-fonts/#from-packages
|
||||||
|
|
Loading…
Reference in a new issue