mirror of
https://github.com/timokz/flutter-vienna-hackathon-25.git
synced 2025-11-08 21:04:20 +01:00
Compare commits
2 commits
07870891da
...
35edff13ef
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35edff13ef | ||
|
|
5f686b7b96 |
9 changed files with 146 additions and 79 deletions
30
wien_talks/wien_talks_flutter/lib/helper/funmap_mgr.dart
Normal file
30
wien_talks/wien_talks_flutter/lib/helper/funmap_mgr.dart
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import 'package:serverpod_flutter/serverpod_flutter.dart';
|
||||||
|
import 'package:wien_talks_client/wien_talks_client.dart';
|
||||||
|
|
||||||
|
class FunmapMgr {
|
||||||
|
static FunmapMgr? _instance;
|
||||||
|
|
||||||
|
FunmapMgr._() {
|
||||||
|
configure();
|
||||||
|
}
|
||||||
|
|
||||||
|
late Client client;
|
||||||
|
|
||||||
|
factory FunmapMgr() {
|
||||||
|
if (_instance != null) return _instance!;
|
||||||
|
_instance = FunmapMgr._();
|
||||||
|
return _instance!;
|
||||||
|
}
|
||||||
|
|
||||||
|
void configure() {
|
||||||
|
// When you are running the app on a physical device, you need to set the
|
||||||
|
// server URL to the IP address of your computer. You can find the IP
|
||||||
|
// address by running `ipconfig` on Windows or `ifconfig` on Mac/Linux.
|
||||||
|
// You can set the variable when running or building your app like this:
|
||||||
|
// E.g. `flutter run --dart-define=SERVER_URL=https://api.example.com/`
|
||||||
|
const serverUrlFromEnv = String.fromEnvironment('SERVER_URL');
|
||||||
|
final serverUrl = serverUrlFromEnv.isEmpty ? 'http://localhost:8080/' : serverUrlFromEnv;
|
||||||
|
|
||||||
|
client = Client(serverUrl, connectionTimeout: const Duration(seconds: 5))..connectivityMonitor = FlutterConnectivityMonitor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,34 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
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/helper/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
|
|
||||||
/// and is set up to connect to a Serverpod running on a local server on
|
|
||||||
/// the default port. You will need to modify this to connect to staging or
|
|
||||||
/// production servers.
|
|
||||||
/// In a larger app, you may want to use the dependency injection of your choice
|
|
||||||
/// instead of using a global client object. This is just a simple example.
|
|
||||||
late final Client client;
|
|
||||||
|
|
||||||
late String serverUrl;
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// When you are running the app on a physical device, you need to set the
|
|
||||||
// server URL to the IP address of your computer. You can find the IP
|
|
||||||
// address by running `ipconfig` on Windows or `ifconfig` on Mac/Linux.
|
|
||||||
// You can set the variable when running or building your app like this:
|
|
||||||
// E.g. `flutter run --dart-define=SERVER_URL=https://api.example.com/`
|
|
||||||
const serverUrlFromEnv = String.fromEnvironment('SERVER_URL');
|
|
||||||
final serverUrl =
|
|
||||||
serverUrlFromEnv.isEmpty ? 'http://$localhost:8080/' : serverUrlFromEnv;
|
|
||||||
|
|
||||||
client = Client(serverUrl)
|
|
||||||
..connectivityMonitor = FlutterConnectivityMonitor();
|
|
||||||
|
|
||||||
client.openStreamingConnection();
|
|
||||||
|
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,44 +11,9 @@ class MyApp extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp.router(
|
return MaterialApp.router(
|
||||||
title: 'Wien Talks',
|
title: 'Wien Talks FunMap',
|
||||||
theme: ThemeData(primarySwatch: Colors.blue),
|
theme: ThemeData(primarySwatch: Colors.blue),
|
||||||
routerConfig: router,
|
routerConfig: router,
|
||||||
//home: NewsScreen(),
|
|
||||||
//home: const MyHomePage(title: 'Serverpod Example'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ResultDisplays shows the result of the call. Either the returned result
|
|
||||||
/// from the `example.greeting` endpoint method or an error message.
|
|
||||||
class ResultDisplay extends StatelessWidget {
|
|
||||||
final String? resultMessage;
|
|
||||||
final String? errorMessage;
|
|
||||||
|
|
||||||
const ResultDisplay({super.key, this.resultMessage, this.errorMessage});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
String text;
|
|
||||||
Color backgroundColor;
|
|
||||||
if (errorMessage != null) {
|
|
||||||
backgroundColor = Colors.red[300]!;
|
|
||||||
text = errorMessage!;
|
|
||||||
} else if (resultMessage != null) {
|
|
||||||
backgroundColor = Colors.green[300]!;
|
|
||||||
text = resultMessage!;
|
|
||||||
} else {
|
|
||||||
backgroundColor = Colors.grey[300]!;
|
|
||||||
text = 'No server response yet.';
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConstrainedBox(
|
|
||||||
constraints: const BoxConstraints(minHeight: 50),
|
|
||||||
child: Container(
|
|
||||||
color: backgroundColor,
|
|
||||||
child: Center(child: Text(text)),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:loader_overlay/loader_overlay.dart';
|
import 'package:loader_overlay/loader_overlay.dart';
|
||||||
import 'package:location/location.dart';
|
import 'package:location/location.dart';
|
||||||
import 'package:wien_talks_client/wien_talks_client.dart';
|
import 'package:wien_talks_client/wien_talks_client.dart';
|
||||||
|
import 'package:wien_talks_flutter/helper/funmap_mgr.dart';
|
||||||
import 'package:wien_talks_flutter/location_mgr.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';
|
import 'package:wien_talks_flutter/widgets/error_snackbar.dart';
|
||||||
|
|
||||||
class NewsInputForm extends StatefulWidget {
|
class NewsInputForm extends StatefulWidget {
|
||||||
|
|
@ -37,7 +37,7 @@ class _NewsInputFormState extends State<NewsInputForm> {
|
||||||
lat: LocationMgr().lastLocation!.latitude!,
|
lat: LocationMgr().lastLocation!.latitude!,
|
||||||
lng: LocationMgr().lastLocation!.longitude!,
|
lng: LocationMgr().lastLocation!.longitude!,
|
||||||
);
|
);
|
||||||
await client.quote.createQuote(newsData);
|
await FunmapMgr().client.quote.createQuote(newsData);
|
||||||
_newsController.clear();
|
_newsController.clear();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:wien_talks_flutter/show_latest_news_widget.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/intro_text_widget.dart';
|
||||||
import 'package:wien_talks_flutter/widgets/screen_widget.dart';
|
import 'package:wien_talks_flutter/widgets/screen_widget.dart';
|
||||||
|
|
||||||
class NewsScreen extends StatelessWidget {
|
class NewsScreen extends StatelessWidget {
|
||||||
|
|
@ -16,7 +16,7 @@ class NewsScreen extends StatelessWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
HeadingText(text: "Latest news"),
|
IntroTextWidget(),
|
||||||
ShowLatestNewsWidget(),
|
ShowLatestNewsWidget(),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 30,
|
height: 30,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:wien_talks_flutter/main.dart';
|
import 'package:wien_talks_flutter/widgets/heading_text.dart';
|
||||||
|
|
||||||
|
import 'helper/funmap_mgr.dart';
|
||||||
|
|
||||||
class ShowLatestNewsWidget extends StatelessWidget {
|
class ShowLatestNewsWidget extends StatelessWidget {
|
||||||
const ShowLatestNewsWidget({super.key});
|
const ShowLatestNewsWidget({super.key});
|
||||||
|
|
@ -7,13 +9,16 @@ class ShowLatestNewsWidget extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return StreamBuilder(
|
return StreamBuilder(
|
||||||
stream: client.quote.stream,
|
stream: FunmapMgr().client.quote.stream,
|
||||||
builder: (BuildContext context, AsyncSnapshot snapshot) {
|
builder: (BuildContext context, AsyncSnapshot snapshot) {
|
||||||
if (snapshot.hasError) {
|
return Column(
|
||||||
return Text('Error: ${snapshot.error}');
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
}
|
children: [
|
||||||
return Text(snapshot.data ?? "Be the first to submit amazing news!", style: TextStyle(fontSize: 20, color: Theme.of(context).colorScheme.error));
|
HeadingText(text: "Latest news"),
|
||||||
return Placeholder();
|
if (snapshot.hasError) Text('Error: ${snapshot.error}'),
|
||||||
|
Text(snapshot.data ?? "Be the first to submit amazing news!", style: TextStyle(fontSize: 20, color: Theme.of(context).colorScheme.error)),
|
||||||
|
],
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:wien_talks_client/wien_talks_client.dart';
|
import 'package:wien_talks_client/wien_talks_client.dart';
|
||||||
import 'package:wien_talks_flutter/main.dart';
|
import 'package:wien_talks_flutter/helper/funmap_mgr.dart';
|
||||||
|
|
||||||
class AddQuoteFab extends StatelessWidget {
|
class AddQuoteFab extends StatelessWidget {
|
||||||
const AddQuoteFab({
|
const AddQuoteFab({
|
||||||
|
|
@ -10,8 +10,7 @@ class AddQuoteFab extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FloatingActionButton(onPressed: () {
|
return FloatingActionButton(onPressed: () {
|
||||||
client.quote.createQuote(
|
FunmapMgr().client.quote.createQuote(CreateQuoteRequest(text: 'Quote Text', lat: 22, lng: 140));
|
||||||
CreateQuoteRequest(text: 'Quote Text', lat: 22, lng: 140));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
class IntroTextWidget extends StatelessWidget {
|
||||||
|
const IntroTextWidget({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Card(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Welcome to FunMap!",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 26,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Text(
|
||||||
|
"Ever experienced something funny, weird, or just too good not to share? "
|
||||||
|
"With FunMap, you can pin your funniest moments and strange encounters right on the map! 🗺️😂",
|
||||||
|
style: GoogleFonts.roboto(fontSize: 16, height: 1.5),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
"Share hilarious events from your daily life, discover what others nearby have spotted, "
|
||||||
|
"and explore a world full of smiles and surprises. Whether it’s a quirky street performer, "
|
||||||
|
"an awkward sign, or a random act of comedy — every little story has its place here.",
|
||||||
|
style: GoogleFonts.roboto(fontSize: 16, height: 1.5),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
"👉 Add your event, mark the spot, and let the community enjoy the laughter with you.",
|
||||||
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
height: 1.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
"Because the world’s a lot more fun when we laugh together. 🌍✨",
|
||||||
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: 16,
|
||||||
|
fontStyle: FontStyle.italic,
|
||||||
|
height: 1.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||||
import 'package:loader_overlay/loader_overlay.dart';
|
import 'package:loader_overlay/loader_overlay.dart';
|
||||||
|
|
||||||
class ScreenWidget extends StatelessWidget {
|
class ScreenWidget extends StatelessWidget {
|
||||||
|
|
@ -10,13 +13,42 @@ class ScreenWidget extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('News'),
|
title: const Text('FunMap'),
|
||||||
),
|
),
|
||||||
// floatingActionButton: AddQuoteFab(),
|
// floatingActionButton: AddQuoteFab(),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: LoaderOverlay(child: child),
|
child: LoaderOverlay(
|
||||||
|
overlayWidgetBuilder: (_) {
|
||||||
|
switch (Random().nextInt(5)) {
|
||||||
|
case 0:
|
||||||
|
return Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
case 1:
|
||||||
|
return Center(
|
||||||
|
child: SpinKitCubeGrid(size: 50, color: Theme.of(context).primaryColor),
|
||||||
|
);
|
||||||
|
case 2:
|
||||||
|
return Center(
|
||||||
|
child: SpinKitWave(color: Theme.of(context).primaryColor),
|
||||||
|
);
|
||||||
|
case 3:
|
||||||
|
return Center(
|
||||||
|
child: SpinKitHourGlass(color: Theme.of(context).primaryColor),
|
||||||
|
);
|
||||||
|
case 4:
|
||||||
|
return Center(
|
||||||
|
child: SpinKitFadingCircle(color: Theme.of(context).primaryColor),
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return Center(
|
||||||
|
child: SpinKitPulsingGrid(color: Theme.of(context).primaryColor),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: child),
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,10 @@ dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
|
flutter_spinkit: ^5.2.2
|
||||||
|
|
||||||
|
google_fonts: ^6.3.0
|
||||||
|
|
||||||
go_router: ^16.1.0
|
go_router: ^16.1.0
|
||||||
|
|
||||||
loader_overlay: ^5.0.0
|
loader_overlay: ^5.0.0
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue