Goods details page
This commit is contained in:
@@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||
class ProductCard extends StatelessWidget {
|
||||
final Image imagePath;
|
||||
final String name;
|
||||
final int price;
|
||||
final String price;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const ProductCard({
|
||||
|
||||
178
lib/main.dart
178
lib/main.dart
@@ -4,14 +4,16 @@ import 'dart:js_interop_unsafe' as js_util;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_application_1/components/card.dart';
|
||||
import 'package:flutter_application_1/pages/basket.dart';
|
||||
import 'package:flutter_application_1/pages/detail.dart';
|
||||
import 'package:flutter_application_1/pages/order_history.dart';
|
||||
import 'package:flutter_application_1/theme.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
enum GymLinkScreen { mainPage, basketPage, historyPage }
|
||||
|
||||
class MyApp extends StatefulWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@@ -20,10 +22,47 @@ class MyApp extends StatefulWidget {
|
||||
State<MyApp> createState() => _MyAppState();
|
||||
}
|
||||
|
||||
const List<Map<String, String>> testData = [
|
||||
{
|
||||
"name": "Протеин",
|
||||
"image": "product.png",
|
||||
"price": "120",
|
||||
"details": "Test details",
|
||||
"id": "34fa3126-bfaf-5dec-8f4a-b246c097ef73"
|
||||
},
|
||||
{
|
||||
"name": "Протеин",
|
||||
"image": "product.png",
|
||||
"price": "150",
|
||||
"details": "Test details",
|
||||
"id": "34a26e82-7656-5e98-a44a-c2d01d0b1ad1123"
|
||||
},
|
||||
{
|
||||
"name": "Протеин",
|
||||
"image": "product.png",
|
||||
"price": "250",
|
||||
"details": "Test details",
|
||||
"id": "4fb204b7-3f9e-52a2-bed1-415c00a31a37123"
|
||||
},
|
||||
{
|
||||
"name": "Протеин",
|
||||
"image": "product.png",
|
||||
"price": "300",
|
||||
"details": "Test details",
|
||||
"id": "09b2f5bb-683e-5c39-ae89-b8e152fa8bcf123"
|
||||
},
|
||||
{
|
||||
"name": "Протеин",
|
||||
"image": "product.png",
|
||||
"price": "100",
|
||||
"details": "Test details",
|
||||
"id": "cd1b6817-db94-5394-be1d-af88af79749f123"
|
||||
}
|
||||
];
|
||||
|
||||
@js.JSExport()
|
||||
class _MyAppState extends State<MyApp> {
|
||||
final _streamController = StreamController<void>.broadcast();
|
||||
GymLinkScreen _currentGymLinkScreen = GymLinkScreen.mainPage;
|
||||
bool _isLoading = true;
|
||||
|
||||
@override
|
||||
@@ -46,7 +85,7 @@ class _MyAppState extends State<MyApp> {
|
||||
title: 'GymLink Module',
|
||||
theme: myTheme,
|
||||
debugShowCheckedModeBanner: false,
|
||||
home: gymLinkScreenRouter(_currentGymLinkScreen),
|
||||
home: MainPage(isLoading: _isLoading),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -58,55 +97,28 @@ class _MyAppState extends State<MyApp> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Widget gymLinkScreenRouter(GymLinkScreen which) {
|
||||
switch (which) {
|
||||
case GymLinkScreen.mainPage:
|
||||
return MainPage(
|
||||
title: 'Counter',
|
||||
isLoading: _isLoading,
|
||||
changeGymLinkScreenTo: changeGymLinkScreenTo);
|
||||
case GymLinkScreen.basketPage:
|
||||
return BasketPage(changeGymLinkScreenTo: changeGymLinkScreenTo);
|
||||
case GymLinkScreen.historyPage:
|
||||
return HistoryPage(changeGymLinkScreenTo: changeGymLinkScreenTo);
|
||||
}
|
||||
}
|
||||
|
||||
@js.JSExport()
|
||||
void changeGymLinkScreenTo(String screenString) {
|
||||
setState(() {
|
||||
switch (screenString) {
|
||||
case 'main':
|
||||
_currentGymLinkScreen = GymLinkScreen.mainPage;
|
||||
break;
|
||||
case 'basket':
|
||||
_currentGymLinkScreen = GymLinkScreen.basketPage;
|
||||
break;
|
||||
case 'history':
|
||||
_currentGymLinkScreen = GymLinkScreen.historyPage;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class MainPage extends StatefulWidget {
|
||||
final String title;
|
||||
final bool isLoading;
|
||||
final void Function(String) changeGymLinkScreenTo;
|
||||
|
||||
const MainPage(
|
||||
{super.key,
|
||||
required this.title,
|
||||
required this.isLoading,
|
||||
required this.changeGymLinkScreenTo});
|
||||
const MainPage({
|
||||
super.key,
|
||||
required this.isLoading,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MainPage> createState() => _MainPageState();
|
||||
}
|
||||
|
||||
class _MainPageState extends State<MainPage> {
|
||||
Future<void> _goToPage() async {
|
||||
final Uri url = Uri.parse('https://google.com');
|
||||
if (!await launchUrl(url, webOnlyWindowName: '_blank')) {
|
||||
throw 'Could not launch $url';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@@ -153,9 +165,7 @@ class _MainPageState extends State<MainPage> {
|
||||
suffixIcon: Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
debugPrint('search button pressed');
|
||||
},
|
||||
onPressed: _goToPage,
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8, horizontal: 0),
|
||||
@@ -178,9 +188,9 @@ class _MainPageState extends State<MainPage> {
|
||||
const SizedBox(width: 8),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
widget.changeGymLinkScreenTo('basket');
|
||||
});
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => const BasketPage(),
|
||||
));
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.all(0),
|
||||
@@ -202,9 +212,9 @@ class _MainPageState extends State<MainPage> {
|
||||
const SizedBox(width: 8),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
widget.changeGymLinkScreenTo('history');
|
||||
});
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => const HistoryPage(),
|
||||
));
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.all(0),
|
||||
@@ -228,20 +238,32 @@ class _MainPageState extends State<MainPage> {
|
||||
),
|
||||
Expanded(
|
||||
child: GridView.builder(
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount:
|
||||
(MediaQuery.sizeOf(context).width ~/ 300).floor(),
|
||||
),
|
||||
itemCount: 10,
|
||||
itemCount: testData.length,
|
||||
itemBuilder: (context, index) {
|
||||
final product = testData[index];
|
||||
debugPrint(product.toString());
|
||||
return ProductCard(
|
||||
imagePath: Image.asset(
|
||||
'product.png',
|
||||
product['image']!,
|
||||
width: 100,
|
||||
),
|
||||
name: 'Product $index',
|
||||
price: 100,
|
||||
onTap: () => debugPrint('product $index pressed'),
|
||||
name: product['name']!,
|
||||
price: product['price']!,
|
||||
onTap: () => Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => DetailPage(
|
||||
name: product['name']!,
|
||||
description: product['details']!,
|
||||
price: product['price']!,
|
||||
id: product['id']!,
|
||||
image: Image.asset(product['image']!, width: 300),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -251,41 +273,3 @@ class _MainPageState extends State<MainPage> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BasketPage extends StatelessWidget {
|
||||
final void Function(String) changeGymLinkScreenTo;
|
||||
const BasketPage({super.key, required this.changeGymLinkScreenTo});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => changeGymLinkScreenTo('main'),
|
||||
),
|
||||
title: const Text('Корзина'),
|
||||
),
|
||||
body: const Center(
|
||||
child: Text('Корзина'),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class HistoryPage extends StatelessWidget {
|
||||
final void Function(String) changeGymLinkScreenTo;
|
||||
const HistoryPage({super.key, required this.changeGymLinkScreenTo});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => changeGymLinkScreenTo('main'),
|
||||
),
|
||||
title: const Text('История заказов'),
|
||||
),
|
||||
body: const Center(
|
||||
child: Text('История заказов'),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
21
lib/pages/basket.dart
Normal file
21
lib/pages/basket.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BasketPage extends StatelessWidget {
|
||||
const BasketPage({
|
||||
super.key,
|
||||
});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
title: const Text('Корзина'),
|
||||
),
|
||||
body: const Center(
|
||||
child: Text('Корзина'),
|
||||
));
|
||||
}
|
||||
}
|
||||
93
lib/pages/detail.dart
Normal file
93
lib/pages/detail.dart
Normal file
@@ -0,0 +1,93 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DetailPage extends StatelessWidget {
|
||||
final String name;
|
||||
final String description;
|
||||
final String price;
|
||||
final String id;
|
||||
final Image image;
|
||||
const DetailPage(
|
||||
{super.key,
|
||||
required this.name,
|
||||
required this.description,
|
||||
required this.price,
|
||||
required this.id,
|
||||
required this.image});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
title: Text('$name - $id'),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
image,
|
||||
Padding(
|
||||
padding: const EdgeInsetsDirectional.fromSTEB(0, 60, 60, 60),
|
||||
child: SizedBox(
|
||||
width: 340,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
child: Card(
|
||||
elevation: 4,
|
||||
color: const Color(0xFFF2F3F9),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsetsDirectional.fromSTEB(20, 15, 10, 15),
|
||||
child: Text(
|
||||
description,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: const AlignmentDirectional(0, -1),
|
||||
child: Padding(
|
||||
padding: const EdgeInsetsDirectional.fromSTEB(0, 60, 0, 0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Стоимость $price',
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () => {},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
),
|
||||
),
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsetsDirectional.fromSTEB(
|
||||
34, 10, 34, 10)),
|
||||
child: const Text('Добавить в корзину'),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
21
lib/pages/order_history.dart
Normal file
21
lib/pages/order_history.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class HistoryPage extends StatelessWidget {
|
||||
const HistoryPage({
|
||||
super.key,
|
||||
});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
title: const Text('История заказов'),
|
||||
),
|
||||
body: const Center(
|
||||
child: Text('История заказов'),
|
||||
));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user