diff --git a/wien_talks/wien_talks_flutter/lib/create_event_screen.dart b/wien_talks/wien_talks_flutter/lib/create_event_screen.dart index 58f2947..b08093c 100644 --- a/wien_talks/wien_talks_flutter/lib/create_event_screen.dart +++ b/wien_talks/wien_talks_flutter/lib/create_event_screen.dart @@ -15,7 +15,7 @@ class CreateEventScreen extends StatelessWidget { return ScreenWidget( child: Column( children: [ - NewsInputForm(onSubmit: (newsEventModel) {}), + NewsInputForm(), StreamBuilder(stream: LocationMgr().stream, builder: (BuildContext context, AsyncSnapshot snapshot) => Text(snapshot.data.toString())), Expanded( child: GetLocationWidget( diff --git a/wien_talks/wien_talks_flutter/lib/go_router.dart b/wien_talks/wien_talks_flutter/lib/helper/go_router.dart similarity index 100% rename from wien_talks/wien_talks_flutter/lib/go_router.dart rename to wien_talks/wien_talks_flutter/lib/helper/go_router.dart diff --git a/wien_talks/wien_talks_flutter/lib/location_mgr.dart b/wien_talks/wien_talks_flutter/lib/location_mgr.dart index c43dab0..21d3289 100644 --- a/wien_talks/wien_talks_flutter/lib/location_mgr.dart +++ b/wien_talks/wien_talks_flutter/lib/location_mgr.dart @@ -93,6 +93,7 @@ class LocationMgr { iconMarker = null; viewModel?.dispose(); viewModel = null; + _lastLocationData = null; } Stream get stream => _subject.stream; diff --git a/wien_talks/wien_talks_flutter/lib/main.dart b/wien_talks/wien_talks_flutter/lib/main.dart index d39a4a8..e898d02 100644 --- a/wien_talks/wien_talks_flutter/lib/main.dart +++ b/wien_talks/wien_talks_flutter/lib/main.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:serverpod_flutter/serverpod_flutter.dart'; import 'package:wien_talks_client/wien_talks_client.dart'; -import 'package:wien_talks_flutter/go_router.dart'; +import 'package:wien_talks_flutter/helper/go_router.dart'; /// Sets up a global client object that can be used to talk to the server from /// anywhere in our app. The client is generated from your server code @@ -38,7 +38,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp.router( - title: 'Serverpod Demo', + title: 'Wien Talks', theme: ThemeData(primarySwatch: Colors.blue), routerConfig: router, //home: NewsScreen(), diff --git a/wien_talks/wien_talks_flutter/lib/news_input_form.dart b/wien_talks/wien_talks_flutter/lib/news_input_form.dart index 0a99302..ed48bb7 100644 --- a/wien_talks/wien_talks_flutter/lib/news_input_form.dart +++ b/wien_talks/wien_talks_flutter/lib/news_input_form.dart @@ -1,10 +1,13 @@ import 'package:flutter/material.dart'; -import 'package:wien_talks_flutter/models/news_event_model.dart'; +import 'package:loader_overlay/loader_overlay.dart'; +import 'package:location/location.dart'; +import 'package:wien_talks_client/wien_talks_client.dart'; +import 'package:wien_talks_flutter/location_mgr.dart'; +import 'package:wien_talks_flutter/main.dart'; +import 'package:wien_talks_flutter/widgets/error_snackbar.dart'; class NewsInputForm extends StatefulWidget { - final Function(NewsEventModel) onSubmit; - - const NewsInputForm({Key? key, required this.onSubmit}) : super(key: key); + const NewsInputForm({super.key}); @override _NewsInputFormState createState() => _NewsInputFormState(); @@ -20,16 +23,29 @@ class _NewsInputFormState extends State { super.dispose(); } - void _submitForm() { + void _submitForm() async { + LocationData? locationData = LocationMgr().lastLocation; + if (locationData == null || locationData.latitude == null || locationData.longitude == null) { + ErrorSnackbar().show(context, "No location available, please retry later"); + return; + } if (_formKey.currentState!.validate()) { - final newsData = NewsEventModel( - content: _newsController.text.trim(), - timestamp: DateTime.now(), - latitude: 0.0, - longitude: 0.0, - ); - widget.onSubmit(newsData); - _newsController.clear(); + var handler = context.loaderOverlay..show(); + try { + final newsData = CreateQuoteRequest( + text: _newsController.text.trim(), + lat: LocationMgr().lastLocation!.latitude!, + lng: LocationMgr().lastLocation!.longitude!, + ); + await client.quote.createQuote(newsData); + _newsController.clear(); + } catch (error) { + if (mounted) { + ErrorSnackbar().show(context, error.toString()); + } + } finally { + handler.hide(); + } } } diff --git a/wien_talks/wien_talks_flutter/lib/news_screen.dart b/wien_talks/wien_talks_flutter/lib/news_screen.dart index 4fcb635..93dad3b 100644 --- a/wien_talks/wien_talks_flutter/lib/news_screen.dart +++ b/wien_talks/wien_talks_flutter/lib/news_screen.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'package:wien_talks_flutter/main.dart'; +import 'package:wien_talks_flutter/show_latest_news_widget.dart'; import 'package:wien_talks_flutter/widgets/heading_text.dart'; import 'package:wien_talks_flutter/widgets/screen_widget.dart'; @@ -28,15 +28,22 @@ class NewsScreen extends StatelessWidget { ); return ScreenWidget( child: SingleChildScrollView( - child: StreamBuilder( - stream: client.quote.quoteUpdates(), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.active) { - return Text(snapshot.data?.text ?? 'Empty Text'); - } - - return Text('Empty or Error'); - })), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + HeadingText(text: "Latest news"), + ShowLatestNewsWidget(), + SizedBox( + height: 30, + ), + ElevatedButton( + onPressed: () { + context.pushNamed("create_event"); + }, + child: Text("Submit your own event")), + ], + ), + ), ); } } diff --git a/wien_talks/wien_talks_flutter/lib/show_latest_news_widget.dart b/wien_talks/wien_talks_flutter/lib/show_latest_news_widget.dart new file mode 100644 index 0000000..1b99ebe --- /dev/null +++ b/wien_talks/wien_talks_flutter/lib/show_latest_news_widget.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:wien_talks_flutter/main.dart'; + +class ShowLatestNewsWidget extends StatelessWidget { + const ShowLatestNewsWidget({super.key}); + + @override + Widget build(BuildContext context) { + return StreamBuilder( + stream: client.quote.stream, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } + return Text(snapshot.data ?? "Be the first to submit amazing news!", style: TextStyle(fontSize: 20, color: Theme.of(context).colorScheme.error)); + return Placeholder(); + }); + } +} diff --git a/wien_talks/wien_talks_flutter/lib/widgets/error_snackbar.dart b/wien_talks/wien_talks_flutter/lib/widgets/error_snackbar.dart new file mode 100644 index 0000000..3529899 --- /dev/null +++ b/wien_talks/wien_talks_flutter/lib/widgets/error_snackbar.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +class ErrorSnackbar { + void show(BuildContext context, String message) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(message, style: TextStyle(color: Theme.of(context).colorScheme.onError)), + showCloseIcon: true, + duration: Duration(seconds: 30), + backgroundColor: Theme.of(context).colorScheme.error, + )); + } +} diff --git a/wien_talks/wien_talks_flutter/lib/widgets/screen_widget.dart b/wien_talks/wien_talks_flutter/lib/widgets/screen_widget.dart index 3237ce3..4750baa 100644 --- a/wien_talks/wien_talks_flutter/lib/widgets/screen_widget.dart +++ b/wien_talks/wien_talks_flutter/lib/widgets/screen_widget.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:wien_talks_flutter/widgets/add-quote-fab.dart'; +import 'package:loader_overlay/loader_overlay.dart'; class ScreenWidget extends StatelessWidget { final Widget child; @@ -12,11 +12,11 @@ class ScreenWidget extends StatelessWidget { appBar: AppBar( title: const Text('News'), ), - floatingActionButton: AddQuoteFab(), +// floatingActionButton: AddQuoteFab(), body: SafeArea( child: Padding( padding: const EdgeInsets.all(8.0), - child: child, + child: LoaderOverlay(child: child), )), ); } diff --git a/wien_talks/wien_talks_flutter/pubspec.yaml b/wien_talks/wien_talks_flutter/pubspec.yaml index d32cc2e..81a1e48 100644 --- a/wien_talks/wien_talks_flutter/pubspec.yaml +++ b/wien_talks/wien_talks_flutter/pubspec.yaml @@ -27,6 +27,8 @@ dependencies: go_router: ^16.1.0 + loader_overlay: ^5.0.0 + location: ^8.0.1 mapsforge_flutter: ^3.0.2