Product card on main screen
This commit is contained in:
BIN
assets/product.png
Normal file
BIN
assets/product.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 455 KiB |
54
lib/components/card.dart
Normal file
54
lib/components/card.dart
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ProductCard extends StatelessWidget {
|
||||||
|
final Image imagePath;
|
||||||
|
final String name;
|
||||||
|
final int price;
|
||||||
|
final VoidCallback onTap;
|
||||||
|
|
||||||
|
const ProductCard({
|
||||||
|
super.key,
|
||||||
|
required this.imagePath,
|
||||||
|
required this.name,
|
||||||
|
required this.price,
|
||||||
|
required this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(minHeight: 200),
|
||||||
|
child: Card(
|
||||||
|
elevation: 3,
|
||||||
|
color: const Color(0xFFF2F3F9),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
imagePath,
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(name, style: Theme.of(context).textTheme.titleLarge),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text('\$$price', style: Theme.of(context).textTheme.titleSmall),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
// child: Column(
|
||||||
|
// mainAxisSize: MainAxisSize.min,
|
||||||
|
// children: [
|
||||||
|
// imagePath,
|
||||||
|
// const SizedBox(height: 16),
|
||||||
|
// Text(name, style: Theme.of(context).textTheme.titleLarge),
|
||||||
|
// const SizedBox(height: 8),
|
||||||
|
// Text('\$$price', style: Theme.of(context).textTheme.titleSmall),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
233
lib/main.dart
233
lib/main.dart
@@ -3,6 +3,8 @@ import 'dart:js_interop' as js;
|
|||||||
import 'dart:js_interop_unsafe' as js_util;
|
import 'dart:js_interop_unsafe' as js_util;
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_application_1/components/card.dart';
|
||||||
|
import 'package:flutter_application_1/theme.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
@@ -42,9 +44,7 @@ class _MyAppState extends State<MyApp> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: 'GymLink Module',
|
title: 'GymLink Module',
|
||||||
theme: ThemeData(
|
theme: myTheme,
|
||||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
|
|
||||||
),
|
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
home: gymLinkScreenRouter(_currentGymLinkScreen),
|
home: gymLinkScreenRouter(_currentGymLinkScreen),
|
||||||
);
|
);
|
||||||
@@ -110,120 +110,145 @@ class _MainPageState extends State<MainPage> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: widget.isLoading
|
appBar: widget.isLoading
|
||||||
? null
|
? null
|
||||||
: AppBar(
|
: AppBar(
|
||||||
title: Row(
|
backgroundColor: Colors.white,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
elevation: 0,
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8),
|
||||||
|
child: Image.asset('logo.png', width: 24, height: 24),
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: Text(
|
||||||
|
'Powered by GymLink',
|
||||||
|
style: Theme.of(context).textTheme.titleSmall,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
toolbarHeight: 30,
|
||||||
|
),
|
||||||
|
body: widget.isLoading
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 5),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Expanded(
|
||||||
padding: const EdgeInsets.only(right: 8),
|
child: TextField(
|
||||||
child: Image.asset('logo.png', width: 24, height: 24),
|
decoration: InputDecoration(
|
||||||
),
|
hintText: 'Search',
|
||||||
Align(
|
border: OutlineInputBorder(
|
||||||
alignment: Alignment.centerRight,
|
borderRadius: BorderRadius.circular(10),
|
||||||
child: Text('Powered by GymLink',
|
),
|
||||||
style: Theme.of(context).textTheme.titleSmall),
|
suffixIcon: Padding(
|
||||||
),
|
padding: const EdgeInsets.only(right: 8),
|
||||||
])),
|
child: ElevatedButton(
|
||||||
body: widget.isLoading
|
onPressed: () {
|
||||||
? const Center(child: CircularProgressIndicator())
|
debugPrint('search button pressed');
|
||||||
: Column(
|
},
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
style: ElevatedButton.styleFrom(
|
||||||
children: <Widget>[
|
padding: const EdgeInsets.symmetric(
|
||||||
Row(
|
vertical: 8, horizontal: 0),
|
||||||
children: [
|
minimumSize:
|
||||||
Expanded(
|
const Size(50, kMinInteractiveDimension),
|
||||||
child: TextField(
|
backgroundColor:
|
||||||
decoration: InputDecoration(
|
Theme.of(context).primaryColor,
|
||||||
hintText: 'Search',
|
shape: const CircleBorder(),
|
||||||
border: OutlineInputBorder(
|
),
|
||||||
borderRadius: BorderRadius.circular(10),
|
child: const Icon(
|
||||||
),
|
Icons.search,
|
||||||
suffixIcon: Padding(
|
color: Colors.white,
|
||||||
padding: const EdgeInsets.only(right: 8),
|
size: 24,
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: () {
|
|
||||||
debugPrint('search button pressed');
|
|
||||||
},
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 8, horizontal: 0),
|
|
||||||
minimumSize: const Size(
|
|
||||||
50, kMinInteractiveDimension),
|
|
||||||
backgroundColor: Colors.blue,
|
|
||||||
shape: const CircleBorder(),
|
|
||||||
),
|
|
||||||
child: const Icon(
|
|
||||||
Icons.search,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 24,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
),
|
||||||
ElevatedButton(
|
const SizedBox(width: 8),
|
||||||
onPressed: () {
|
ElevatedButton(
|
||||||
setState(() {
|
onPressed: () {
|
||||||
widget.changeGymLinkScreenTo('basket');
|
setState(() {
|
||||||
});
|
widget.changeGymLinkScreenTo('basket');
|
||||||
},
|
});
|
||||||
style: ElevatedButton.styleFrom(
|
},
|
||||||
padding: const EdgeInsets.all(0),
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.blue,
|
padding: const EdgeInsets.all(0),
|
||||||
shape: const CircleBorder(
|
minimumSize: const Size(40, kMinInteractiveDimension),
|
||||||
side: BorderSide(
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
color: Colors.black,
|
shape: const CircleBorder(
|
||||||
width: 1,
|
side: BorderSide(
|
||||||
),
|
color: Colors.black,
|
||||||
|
width: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: const Icon(
|
|
||||||
Icons.shopping_basket,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 24,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
child: const Icon(
|
||||||
ElevatedButton(
|
Icons.shopping_basket,
|
||||||
onPressed: () {
|
color: Colors.white,
|
||||||
setState(() {
|
size: 24,
|
||||||
widget.changeGymLinkScreenTo('history');
|
),
|
||||||
});
|
),
|
||||||
},
|
const SizedBox(width: 8),
|
||||||
style: ElevatedButton.styleFrom(
|
ElevatedButton(
|
||||||
padding: const EdgeInsets.all(0),
|
onPressed: () {
|
||||||
backgroundColor: Colors.blue,
|
setState(() {
|
||||||
shape: const CircleBorder(
|
widget.changeGymLinkScreenTo('history');
|
||||||
side: BorderSide(
|
});
|
||||||
color: Colors.black,
|
},
|
||||||
width: 1,
|
style: ElevatedButton.styleFrom(
|
||||||
),
|
padding: const EdgeInsets.all(0),
|
||||||
|
minimumSize: const Size(40, kMinInteractiveDimension),
|
||||||
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
|
shape: const CircleBorder(
|
||||||
|
side: BorderSide(
|
||||||
|
color: Colors.black,
|
||||||
|
width: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: const Icon(
|
|
||||||
Icons.history,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 24,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
child: const Icon(
|
||||||
|
Icons.history,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 24,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: GridView.builder(
|
||||||
|
gridDelegate:
|
||||||
|
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: 2,
|
||||||
),
|
),
|
||||||
])
|
itemCount: 10,
|
||||||
// : const Center(
|
itemBuilder: (context, index) {
|
||||||
// child: Column(
|
return ProductCard(
|
||||||
// mainAxisAlignment: MainAxisAlignment.center,
|
imagePath: Image.asset(
|
||||||
// children: <Widget>[
|
'product.png',
|
||||||
// Text(
|
width: 100,
|
||||||
// 'Здесь будут товары',
|
),
|
||||||
// ),
|
name: 'Product $index',
|
||||||
// ],
|
price: 100,
|
||||||
// ),
|
onTap: () => debugPrint('product $index pressed'),
|
||||||
// ),
|
);
|
||||||
);
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
26
lib/theme.dart
Normal file
26
lib/theme.dart
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
final ThemeData myTheme = ThemeData(
|
||||||
|
colorScheme: ColorScheme.fromSeed(
|
||||||
|
seedColor: getMaterialColor(const Color(0x007d85ff))));
|
||||||
|
|
||||||
|
MaterialColor getMaterialColor(Color color) {
|
||||||
|
final int red = color.red;
|
||||||
|
final int green = color.green;
|
||||||
|
final int blue = color.blue;
|
||||||
|
|
||||||
|
final Map<int, Color> shades = {
|
||||||
|
50: Color.fromRGBO(red, green, blue, .1),
|
||||||
|
100: Color.fromRGBO(red, green, blue, .2),
|
||||||
|
200: Color.fromRGBO(red, green, blue, .3),
|
||||||
|
300: Color.fromRGBO(red, green, blue, .4),
|
||||||
|
400: Color.fromRGBO(red, green, blue, .5),
|
||||||
|
500: Color.fromRGBO(red, green, blue, .6),
|
||||||
|
600: Color.fromRGBO(red, green, blue, .7),
|
||||||
|
700: Color.fromRGBO(red, green, blue, .8),
|
||||||
|
800: Color.fromRGBO(red, green, blue, .9),
|
||||||
|
900: Color.fromRGBO(red, green, blue, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
return MaterialColor(color.value, shades);
|
||||||
|
}
|
||||||
@@ -59,6 +59,7 @@ flutter:
|
|||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
assets:
|
assets:
|
||||||
- assets/logo.png
|
- assets/logo.png
|
||||||
|
- assets/product.png
|
||||||
|
|
||||||
# To add assets to your application, add an assets section, like this:
|
# To add assets to your application, add an assets section, like this:
|
||||||
# assets:
|
# assets:
|
||||||
|
|||||||
Reference in New Issue
Block a user