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:gymlink_module_web/tools/text.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 createState() => _OrderInfoPageState(); } class _OrderInfoPageState extends State { 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 _onRefresh(Timer timer) async { return Future.delayed(const Duration(milliseconds: 1000), () async { var orderInfo = await getHistoryDetail(widget.id); setState(() { detail = orderInfo; _isRefreshing = false; }); }); } Future _goToPage() async { if (detail?.payUrl != null) { final Uri url = Uri.parse(detail?.payUrl ?? 'https://example.org'); 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( NetworkImage(item.photo), context), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { return Image( image: NetworkImage(item.photo), width: 50, ); } else { return const CircularProgressIndicator(); } }, ), name: shortString(item.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: '## Итого: ${double.parse(detail!.sum).toStringAsFixed(2)} руб.'), 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(); await payOrder(detail!.id); }, 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(), ); } }