import 'package:flutter/material.dart'; import 'models/train_data.dart'; import 'train_info_display.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Info Tren', theme: ThemeData( primarySwatch: Colors.blue, brightness: Brightness.dark, primaryColor: Colors.blue.shade600, accentColor: Colors.blue.shade700, ), home: MainPageWrapper(), ); } } class MainPageWrapper extends StatelessWidget { @override Widget build(BuildContext context) { return TrainDataSourceWidget( child: MainPage() ); } } class MainPage extends StatefulWidget { @override _MainPageState createState() => _MainPageState(); } class _MainPageState extends State { final trainNumberController = TextEditingController(); bool showAlternate = false; bool get shouldTap { return trainNumberController.text.isNotEmpty; } onTap(BuildContext context) { FocusScope.of(context).requestFocus(FocusNode()); TrainDataSourceWidget.of(context).lookup(trainNumberController.text, showAlternate); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Info Tren"), centerTitle: true, actions: [ IconButton( icon: Icon(Icons.settings), onPressed: () { showModalBottomSheet(context: context, builder: (context) { return StatefulBuilder( builder: (context, ssSheet) => SafeArea( bottom: true, top: false, left: true, right: true, child: Column( mainAxisSize: MainAxisSize.min, children: [ ListTile( title: Text( showAlternate ? "Afișează rezultatul principal" : "Afișează rezultatul alternativ" ), onTap: () { showAlternate = !showAlternate; setState(() {}); ssSheet(() {}); }, ) ], ), ), ); }); }, ) ], ), body: Column( children: [ Row( children: [ Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: TextField( controller: trainNumberController, onChanged: (_) => setState(() => {}), autofocus: true, decoration: InputDecoration( labelText: "Numărul trenului", border: OutlineInputBorder(), hintText: "Scrieți doar numărul" ), onSubmitted: (_) { if (shouldTap) { onTap(context); } }, keyboardType: TextInputType.numberWithOptions(), textInputAction: TextInputAction.search, ), ), ), Padding( padding: const EdgeInsets.all(8.0), child: RaisedButton( child: Text("Caută"), onPressed: (() { if (!shouldTap) return null; return () { onTap(context); }; })(), ), ) ], ), Text( showAlternate ? "Se va afișa rezultatul alternativ\nla următoarea căutare" : "Se va afișa rezultatul principal\nla următoarea căutare", style: Theme.of(context).textTheme.caption.copyWith(fontStyle: FontStyle.italic), textAlign: TextAlign.center, ), Divider( color: Theme.of(context).accentColor, height: 4, ), Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: TrainInfoDisplay(), ), ) ], ), ); } } class TrainInfoDisplay extends StatelessWidget { @override Widget build(BuildContext context) { return StreamBuilder( stream: TrainDataSourceWidget.of(context).dataStream, builder: (context, snapshot) { if (snapshot.connectionState != ConnectionState.active) { return Container(); } if (snapshot.hasError) { final error = snapshot.error as TrainDataEvent; if (error.kind == TrainDataEventKind.NOT_FOUND) { return Center( child: Text( "Train number ${error.trainNumber}\nwas not found!", style: Theme.of(context).textTheme.headline, textAlign: TextAlign.center, ) ); } if (error.kind == TrainDataEventKind.TIMEOUT) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.all(8.0), child: Text( "The request has timed out!", style: Theme.of(context).textTheme.headline, textAlign: TextAlign.center, ), ), Padding( padding: const EdgeInsets.all(8.0), child: RaisedButton( child: Text("Retry"), onPressed: () { TrainDataSourceWidget.of(context).lookup(error.trainNumber); }, ), ) ], ) ); } if (error.kind == TrainDataEventKind.UNKNOWN_ERROR) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.all(8.0), child: Text("An unknown error with the status code ${error.errorStatusCode} has occured."), ), Padding( padding: const EdgeInsets.all(8.0), child: RaisedButton( child: Text("Retry"), onPressed: () { TrainDataSourceWidget.of(context).lookup(error.trainNumber); }, ), ) ], ), ); } } if (snapshot.hasData) { if (snapshot.data.kind == TrainDataEventKind.LOADING) { return Center( child: CircularProgressIndicator(), ); } if (snapshot.data.kind == TrainDataEventKind.GOT_DATA) { return TrainInfoDisplayData(snapshot.data.trainData); } } return Placeholder(); }, ); } }