Stub for creating and queriing from server implemented

This commit is contained in:
mikes222 2025-08-16 15:54:36 +02:00
parent b427b44e4c
commit c36081eddf
10 changed files with 86 additions and 29 deletions

View file

@ -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<LocationData> snapshot) => Text(snapshot.data.toString())),
Expanded(
child: GetLocationWidget(

View file

@ -93,6 +93,7 @@ class LocationMgr {
iconMarker = null;
viewModel?.dispose();
viewModel = null;
_lastLocationData = null;
}
Stream<LocationData> get stream => _subject.stream;

View file

@ -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(),

View file

@ -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<NewsInputForm> {
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,
var handler = context.loaderOverlay..show();
try {
final newsData = CreateQuoteRequest(
text: _newsController.text.trim(),
lat: LocationMgr().lastLocation!.latitude!,
lng: LocationMgr().lastLocation!.longitude!,
);
widget.onSubmit(newsData);
await client.quote.createQuote(newsData);
_newsController.clear();
} catch (error) {
if (mounted) {
ErrorSnackbar().show(context, error.toString());
}
} finally {
handler.hide();
}
}
}

View file

@ -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")),
],
),
),
);
}
}

View file

@ -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();
});
}
}

View file

@ -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,
));
}
}

View file

@ -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),
)),
);
}

View file

@ -27,6 +27,8 @@ dependencies:
go_router: ^16.1.0
loader_overlay: ^5.0.0
location: ^8.0.1
mapsforge_flutter: ^3.0.2