Files
GymLink_Flutter/lib/pages/order_info.dart
2024-06-18 15:14:37 +03:00

363 lines
16 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:gymlink_module_web/components/app_bar.dart';
import 'package:gymlink_module_web/components/heading.dart';
import 'package:gymlink_module_web/components/order_detail_item_card.dart';
import 'package:gymlink_module_web/interfaces/items.dart';
import 'package:gymlink_module_web/tools/history.dart';
import 'package:url_launcher/url_launcher.dart';
final GymHistoryItemDetail item = GymHistoryItemDetail.fromJson({
"id": "12345",
"date": "01.01.1970",
"sum": "45000",
"pay_url": "https://example.org",
"receiver": "Иванов Иван Иванович",
"email": "a@a.ru",
"address": "г. Москва, ул. Пушкина, д. 17",
"providers": [
{
"id": "123",
"name": "Поставщик 1",
"status": "Доставлен",
"items": [
{"photo": "url", "id": "123", "count": 2, "price": "15000"},
{"photo": "url", "id": "123", "count": 2, "price": "15000"}
]
},
{
"id": "123",
"name": "Поставщик 1",
"status": "Доставляется",
"items": [
{"photo": "url", "id": "123", "count": 2, "price": "15000"}
]
}
]
});
class OrderInfoPage extends StatefulWidget {
final String id;
const OrderInfoPage({super.key, required this.id});
@override
State<StatefulWidget> createState() => _OrderInfoPageState();
}
class _OrderInfoPageState extends State<OrderInfoPage> {
GymHistoryItemDetail? detail;
final _scrollController = ScrollController();
late Timer _updateTimer;
bool _isRefreshing = false;
@override
void initState() {
super.initState();
_updateTimer = Timer.periodic(const Duration(minutes: 1), _onRefresh);
_onRefresh(_updateTimer);
}
@override
void dispose() {
_updateTimer.cancel();
super.dispose();
}
Future<void> _onRefresh(Timer timer) async {
return Future.delayed(const Duration(milliseconds: 1000), () async {
var orderInfo = await getHistoryDetail(widget.id);
setState(() {
detail = orderInfo;
_isRefreshing = false;
});
});
}
Future<void> _goToPage() async {
if (detail?.payUrl != null) {
final Uri url = Uri.parse(detail?.payUrl ?? 'example.org');
detail!.payUrl = null;
if (!await launchUrl(url, webOnlyWindowName: '_blank')) {
throw 'Could not launch $url';
}
_onRefresh(_updateTimer);
}
}
Widget _buildContent() {
return Column(
children: [
GymLinkHeader(title: "Заказ #${detail?.id} от ${detail?.date}"),
Expanded(
child: RefreshIndicator(
onRefresh: () => _onRefresh(_updateTimer),
edgeOffset: 55,
child: Scrollbar(
controller: _scrollController,
child: ListView(
controller: _scrollController,
children: [
const SizedBox(height: 10),
kIsWeb
? Center(
child: ElevatedButton(
onPressed: () {
setState(() {
_isRefreshing = true;
});
_onRefresh(_updateTimer);
},
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).primaryColor,
shape: const RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(50)),
),
foregroundColor: Colors.white,
fixedSize: const Size(180, 40),
),
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Text('Обновить'),
Spacer(),
Icon(Icons.refresh),
Spacer()
],
),
),
)
: const SizedBox.shrink(),
const SizedBox(height: 5),
_isRefreshing
? const Center(
child: CircularProgressIndicator(),
)
: const SizedBox.shrink(),
const SizedBox(height: 5),
ListView.builder(
itemCount: detail!.providers.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
final provider = detail!.providers[index];
return Padding(
padding: const EdgeInsetsDirectional.symmetric(
vertical: 10,
horizontal: 5,
),
child: Card(
elevation: 3,
child: Column(
children: [
MarkdownBody(data: '# ${provider.name}'),
MarkdownBody(
data: '## Статус: ${provider.status}'),
const MarkdownBody(data: '### Состав:'),
for (final item in provider.items)
OrderDetailCardItemCard(
image: FutureBuilder(
future: precacheImage(
const AssetImage('assets/product.png'),
context),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.done) {
return const Image(
image:
AssetImage('assets/product.png'),
width: 50,
);
} else {
return const CircularProgressIndicator();
}
},
),
name: 'Протеин',
count: item.count,
price: double.parse(item.price),
),
],
),
),
);
},
),
const SizedBox(
height: 10,
),
SizedBox(
height: 200,
child: Padding(
padding: const EdgeInsetsDirectional.symmetric(
horizontal: 5,
),
child: Card(
elevation: 4,
child: Padding(
padding: const EdgeInsetsDirectional.symmetric(
horizontal: 10, vertical: 20),
child: Column(
// mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
// crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MarkdownBody(
data:
"### Адрес получателя: __${detail!.address}__"),
MarkdownBody(
data: '### Почта: __${detail!.email}__'),
MarkdownBody(
data: '### ФИО: _${detail!.receiver}_'),
],
),
detail?.payUrl == null
? const SizedBox.shrink()
: Center(
child: ElevatedButton(
onPressed: () async {
await _goToPage();
debugPrint('clicked');
},
style: ElevatedButton.styleFrom(
backgroundColor:
Theme.of(context).primaryColor,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(50)),
),
foregroundColor: Colors.white,
fixedSize: const Size(180, 40),
),
child: const Text('Оплатить заказ'),
),
),
],
),
),
),
),
),
],
),
),
),
),
],
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const GymLinkAppBar(),
body: detail == null
? const Center(child: CircularProgressIndicator())
: _buildContent(),
);
}
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// appBar: const GymLinkAppBar(),
// body: detail == null
// ? const Center(child: CircularProgressIndicator())
// : Column(
// mainAxisAlignment: MainAxisAlignment.start,
// children: [
// GymLinkHeader(title: "Заказ #${detail?.id} от ${detail?.date}"),
// Expanded(
// child: RefreshIndicator(
// onRefresh: () => _onRefresh(),
// edgeOffset: 55,
// child: Scrollbar(
// controller: _scrollController,
// child: ListView(
// shrinkWrap: true,
// controller: _scrollController,
// children: [
// detail != null
// ? ListView.builder(
// itemCount: (detail!.providers.length + 1),
// shrinkWrap: true,
// physics: const NeverScrollableScrollPhysics(),
// itemBuilder: (context, index) {
// final provider = detail!.providers[0];
// return Card(
// elevation: 3,
// child: Column(
// children: [
// MarkdownBody(
// data: '# ${provider.name}'),
// MarkdownBody(
// data:
// '## Статус: ${provider.status}'),
// const MarkdownBody(
// data: '### Состав:'),
// for (final item in provider.items)
// OrderDetailCardItemCard(
// image: FutureBuilder(
// future: precacheImage(
// const AssetImage(
// 'assets/product.png'),
// context),
// builder: (context, snapshot) {
// if (snapshot
// .connectionState ==
// ConnectionState.done) {
// return const Image(
// image: AssetImage(
// 'assets/product.png'),
// width: 50,
// );
// } else {
// return const CircularProgressIndicator();
// }
// },
// ),
// name: 'Протеин',
// count: item.count,
// price: double.parse(item.price),
// ),
// ],
// ),
// );
// },
// )
// : const SizedBox.shrink(),
// Card(
// elevation: 4,
// child: Padding(
// padding: const EdgeInsetsDirectional.symmetric(
// horizontal: 10, vertical: 20),
// child: Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// MarkdownBody(
// data:
// "### Адрес получателя: _${detail!.address}_"),
// Markdown(
// data: '### Почта: _${detail!.email}_'),
// // Markdown(
// // data: '### ФИО: _${detail!.receiver}_'),
// ],
// ),
// ),
// ),
// ],
// ),
// ),
// ),
// ),
// ],
// ),
// );
// }
}