import 'dart:async'; import 'dart:js_interop' as js; 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/theme.dart'; void main() { runApp(const MyApp()); } enum GymLinkScreen { mainPage, basketPage, historyPage } class MyApp extends StatefulWidget { const MyApp({super.key}); // This widget is the root of your application. @override State createState() => _MyAppState(); } @js.JSExport() class _MyAppState extends State { final _streamController = StreamController.broadcast(); GymLinkScreen _currentGymLinkScreen = GymLinkScreen.mainPage; bool _isLoading = true; @override void initState() { super.initState(); final export = js.createJSInteropWrapper(this); js.globalContext['_appState'] = export; js.globalContext.callMethod('_stateSet'.toJS); } @override void dispose() { _streamController.close(); super.dispose(); } @override Widget build(BuildContext context) { return MaterialApp( title: 'GymLink Module', theme: myTheme, debugShowCheckedModeBanner: false, home: gymLinkScreenRouter(_currentGymLinkScreen), ); } @js.JSExport() void onTokenReceived(String token) { if (token == 'token123') { setState(() { _isLoading = false; }); } } 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}); @override State createState() => _MainPageState(); } class _MainPageState extends State { @override Widget build(BuildContext context) { return Scaffold( appBar: widget.isLoading ? null : AppBar( backgroundColor: Colors.white, 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: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 5), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Expanded( child: TextField( decoration: InputDecoration( hintText: 'Search', border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), ), suffixIcon: Padding( padding: const EdgeInsets.only(right: 8), child: ElevatedButton( onPressed: () { debugPrint('search button pressed'); }, style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric( vertical: 8, horizontal: 0), minimumSize: const Size(50, kMinInteractiveDimension), backgroundColor: Theme.of(context).primaryColor, shape: const CircleBorder(), ), child: const Icon( Icons.search, color: Colors.white, size: 24, ), ), ), ), ), ), const SizedBox(width: 8), ElevatedButton( onPressed: () { setState(() { widget.changeGymLinkScreenTo('basket'); }); }, 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.shopping_basket, color: Colors.white, size: 24, ), ), const SizedBox(width: 8), ElevatedButton( onPressed: () { setState(() { widget.changeGymLinkScreenTo('history'); }); }, 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, ), ), ], ), ), Expanded( child: GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, ), itemCount: 10, itemBuilder: (context, index) { return ProductCard( imagePath: Image.asset( 'product.png', width: 100, ), name: 'Product $index', price: 100, onTap: () => debugPrint('product $index pressed'), ); }, ), ), ], ), ); } } 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('История заказов'), )); } }