Fix UI camera notch clipping, embed Bürgerforum Oggau logo, and align branding with Bürgerliste Oggau

This commit is contained in:
2026-09-13 16:06:54 +02:00
parent 588309649c
commit 50a6025937
6 changed files with 160 additions and 66 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

+6 -2
View File
@@ -83,8 +83,12 @@ class _ContactScreenState extends State<ContactScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(
title: const Text('Kontakt Bürgerforum'),
centerTitle: true,
),
body: SingleChildScrollView( body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
child: Form( child: Form(
key: _formKey, key: _formKey,
child: Column( child: Column(
@@ -102,7 +106,7 @@ class _ContactScreenState extends State<ContactScreen> {
SizedBox(width: 12), SizedBox(width: 12),
Expanded( Expanded(
child: Text( child: Text(
'Hier können Sie auch ohne Anmeldung direkt mit der Bürgerliste / Gemeindevertretung in Kontakt treten.', 'Hier kannst du direkt mit dem Bürgerforum Oggau in Kontakt treten. Wir freuen uns über deine Anregungen und Fragen!',
style: TextStyle(fontSize: 13), style: TextStyle(fontSize: 13),
), ),
), ),
+3 -3
View File
@@ -16,11 +16,11 @@ class _HomeScreenState extends State<HomeScreen> {
final List<Widget> _pages = const [ final List<Widget> _pages = const [
PostListScreen( PostListScreen(
collectionName: 'News', collectionName: 'News',
title: 'Nachrichten & Aktuelles', title: 'Bürgerforum Aktuelles',
), ),
PostListScreen( PostListScreen(
collectionName: 'Issues', collectionName: 'Issues',
title: 'Mängel & Bürgeranliegen', title: 'Mängel & Anliegen',
), ),
PostListScreen( PostListScreen(
collectionName: 'CitizensForum', collectionName: 'CitizensForum',
@@ -75,7 +75,7 @@ class _HomeScreenState extends State<HomeScreen> {
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.info_outline), icon: Icon(Icons.info_outline),
activeIcon: Icon(Icons.info), activeIcon: Icon(Icons.info),
label: 'Informationen', label: 'Bürgerforum',
), ),
], ],
), ),
+128 -55
View File
@@ -22,13 +22,13 @@ class _InfoScreenState extends State<InfoScreen> {
showDialog( showDialog(
context: context, context: context,
builder: (dialogCtx) => AlertDialog( builder: (dialogCtx) => AlertDialog(
title: const Text('Gemeinde-Zugang freischalten'), title: const Text('Bürgerforum-Zugang'),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( const Text(
'Geben Sie das Passwort bzw. den Zugangscode der Marktgemeinde Oggau ein, um Mängel zu melden und im Bürgerforum mitzuwirken.', 'Gib den Zugangscode des Bürgerforums Oggau ein, um Mängel zu melden und eigene Ideen einzubringen.',
style: TextStyle(fontSize: 13), style: TextStyle(fontSize: 13),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
@@ -36,7 +36,7 @@ class _InfoScreenState extends State<InfoScreen> {
controller: _codeController, controller: _codeController,
obscureText: true, obscureText: true,
decoration: const InputDecoration( decoration: const InputDecoration(
labelText: 'Gemeinde-Passwort', labelText: 'Zugangscode',
border: OutlineInputBorder(), border: OutlineInputBorder(),
hintText: 'z.B. oggau', hintText: 'z.B. oggau',
), ),
@@ -59,7 +59,7 @@ class _InfoScreenState extends State<InfoScreen> {
SnackBar( SnackBar(
content: Text(success content: Text(success
? 'Zugang erfolgreich freigeschaltet!' ? 'Zugang erfolgreich freigeschaltet!'
: 'Ungültiges Passwort. Bitte kontaktieren Sie das Gemeindeamt.'), : 'Ungültiger Code. Bitte wende dich an das Bürgerforum Oggau.'),
backgroundColor: success ? Colors.green : Colors.red, backgroundColor: success ? Colors.green : Colors.red,
), ),
); );
@@ -76,25 +76,60 @@ class _InfoScreenState extends State<InfoScreen> {
final auth = Provider.of<AuthService>(context); final auth = Provider.of<AuthService>(context);
return Scaffold( return Scaffold(
appBar: AppBar(
title: const Text('Bürgerforum Oggau'),
centerTitle: true,
),
body: ListView( body: ListView(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
children: [ children: [
// Community Access Card // Bürgerforum Logo & Branding Header
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.asset(
'assets/images/logo.png',
height: 72,
fit: BoxFit.contain,
),
),
const SizedBox(height: 8),
const Text(
'Bürgerforum Oggau',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 2),
Text(
'Unabhängige Bürgerliste für Oggau am Neusiedler See',
style: TextStyle(fontSize: 12, color: Colors.grey.shade700),
textAlign: TextAlign.center,
),
],
),
),
const SizedBox(height: 8),
// Bürgerforum Access Status Card
Card( Card(
color: auth.isCommunityUnlocked ? Colors.green.shade50 : Colors.blue.shade50, color: auth.isCommunityUnlocked ? Colors.green.shade50 : Colors.blue.shade50,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: Padding( child: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(14.0),
child: Row( child: Row(
children: [ children: [
Icon( Icon(
auth.isCommunityUnlocked auth.isCommunityUnlocked
? Icons.verified_user ? Icons.verified_user
: Icons.lock_outline, : Icons.lock_outline,
color: auth.isCommunityUnlocked ? Colors.green : Colors.blue, color: auth.isCommunityUnlocked ? Colors.green.shade700 : Colors.blue.shade800,
size: 36, size: 32,
), ),
const SizedBox(width: 16), const SizedBox(width: 14),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -104,12 +139,13 @@ class _InfoScreenState extends State<InfoScreen> {
? 'Bürgerzugang: Aktiv' ? 'Bürgerzugang: Aktiv'
: 'Gastmodus (Nur Lesen)', : 'Gastmodus (Nur Lesen)',
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 16), fontWeight: FontWeight.bold, fontSize: 15),
), ),
const SizedBox(height: 2),
Text( Text(
auth.isCommunityUnlocked auth.isCommunityUnlocked
? 'Sie können Mängel und Ideen einreichen.' ? 'Du kannst Mängel und Ideen einreichen.'
: 'Gemeinde-Passwort eingeben zum Freischalten.', : 'Code eingeben, um Beiträge zu erstellen.',
style: TextStyle( style: TextStyle(
fontSize: 12, color: Colors.grey.shade700), fontSize: 12, color: Colors.grey.shade700),
), ),
@@ -117,6 +153,9 @@ class _InfoScreenState extends State<InfoScreen> {
), ),
), ),
ElevatedButton( ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
),
onPressed: () { onPressed: () {
if (auth.isCommunityUnlocked) { if (auth.isCommunityUnlocked) {
auth.lockCommunityAccess(); auth.lockCommunityAccess();
@@ -124,17 +163,62 @@ class _InfoScreenState extends State<InfoScreen> {
_showUnlockDialog(context); _showUnlockDialog(context);
} }
}, },
child: Text(auth.isCommunityUnlocked ? 'Sperren' : 'Anmelden'), child: Text(auth.isCommunityUnlocked ? 'Sperren' : 'Freischalten'),
), ),
], ],
), ),
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 14),
// Gemeinde Info Header // About Bürgerforum Oggau
Card( Card(
elevation: 2, elevation: 1.5,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(Icons.campaign, color: Colors.blue.shade800, size: 24),
const SizedBox(width: 8),
const Text(
'Über das Bürgerforum Oggau',
style: TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
),
],
),
const SizedBox(height: 10),
const Text(
'Das Bürgerforum Oggau ist eine unabhängige Bürgerliste für unsere Marktgemeinde Oggau am Neusiedler See.\n\n'
'Wir stehen für Bürgernähe, Transparenz und eine zukunftsorientierte Gemeindepolitik. '
'Mit dieser App (unserem digitalen „Gemeindetrommler“) wollen wir allen Bürgerinnen und Bürgern eine unkomplizierte Möglichkeit geben, Mängel im Ort aufzuzeigen, Ideen einzubringen und sich zu informieren.',
style: TextStyle(fontSize: 13, height: 1.45),
),
const SizedBox(height: 12),
const Divider(),
const SizedBox(height: 8),
Row(
children: [
const Icon(Icons.group, size: 16, color: Colors.grey),
const SizedBox(width: 8),
Text(
'Gemeindevertretung & Team Bürgerforum',
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold, color: Colors.grey.shade800),
),
],
),
],
),
),
),
const SizedBox(height: 14),
// Gemeinde Bürgerservice (Nützliche Kontakte)
Card(
elevation: 1,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: const Padding( child: const Padding(
padding: EdgeInsets.all(16.0), padding: EdgeInsets.all(16.0),
@@ -142,33 +226,29 @@ class _InfoScreenState extends State<InfoScreen> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'Marktgemeinde Oggau am Neusiedler See', 'Gemeindeamt & Bürgerservice Oggau',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
), ),
SizedBox(height: 8), SizedBox(height: 8),
Text('Hauptstraße 52, 7063 Oggau'), Text('Adresse: Hauptstraße 52, 7063 Oggau', style: TextStyle(fontSize: 13)),
Text('Telefon: +43 2685 7201'), Text('Telefon: +43 2685 7201', style: TextStyle(fontSize: 13)),
Text('E-Mail: post@oggau.bgld.gv.at'), Text('Web: www.oggau.at', style: TextStyle(fontSize: 13)),
Text('Web: www.oggau.at'),
SizedBox(height: 12),
Divider(),
SizedBox(height: 8), SizedBox(height: 8),
Text( Text(
'Parteienverkehr / Öffnungszeiten:', 'Öffnungszeiten Gemeindeamt:',
style: TextStyle(fontWeight: FontWeight.bold), style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
), ),
SizedBox(height: 4), Text('Mo – Fr: 08:00 – 12:00 Uhr | Di zusätzlich: 13:00 – 17:00 Uhr',
Text('Montag bis Freitag: 08:00 – 12:00 Uhr'), style: TextStyle(fontSize: 12)),
Text('Dienstag zusätzlich: 13:00 – 17:00 Uhr'),
], ],
), ),
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 14),
// Notrufnummern // Wichtige Notrufnummern
Card( Card(
elevation: 2, elevation: 1,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: const Padding( child: const Padding(
padding: EdgeInsets.all(16.0), padding: EdgeInsets.all(16.0),
@@ -177,9 +257,9 @@ class _InfoScreenState extends State<InfoScreen> {
children: [ children: [
Text( Text(
'Wichtige Notrufnummern', 'Wichtige Notrufnummern',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.red), style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold, color: Colors.red),
), ),
SizedBox(height: 12), SizedBox(height: 10),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@@ -187,7 +267,7 @@ class _InfoScreenState extends State<InfoScreen> {
Text('122', style: TextStyle(fontWeight: FontWeight.bold)), Text('122', style: TextStyle(fontWeight: FontWeight.bold)),
], ],
), ),
Divider(), Divider(height: 16),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@@ -195,7 +275,7 @@ class _InfoScreenState extends State<InfoScreen> {
Text('133', style: TextStyle(fontWeight: FontWeight.bold)), Text('133', style: TextStyle(fontWeight: FontWeight.bold)),
], ],
), ),
Divider(), Divider(height: 16),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@@ -203,7 +283,7 @@ class _InfoScreenState extends State<InfoScreen> {
Text('144', style: TextStyle(fontWeight: FontWeight.bold)), Text('144', style: TextStyle(fontWeight: FontWeight.bold)),
], ],
), ),
Divider(), Divider(height: 16),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@@ -211,19 +291,11 @@ class _InfoScreenState extends State<InfoScreen> {
Text('112', style: TextStyle(fontWeight: FontWeight.bold)), Text('112', style: TextStyle(fontWeight: FontWeight.bold)),
], ],
), ),
Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Ärztefunkdienst'),
Text('141', style: TextStyle(fontWeight: FontWeight.bold)),
],
),
], ],
), ),
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 14),
// Impressum // Impressum
Card( Card(
@@ -235,22 +307,23 @@ class _InfoScreenState extends State<InfoScreen> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'Impressum & Rechtliches', 'Impressum',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
), ),
SizedBox(height: 8), SizedBox(height: 6),
Text( Text(
'Medieninhaber & Herausgeber:\n' 'Medieninhaber & Herausgeber:\n'
'Marktgemeinde Oggau am Neusiedler See\n' 'Bürgerforum Oggau (Unabhängige Bürgerliste Oggau)\n'
'Hauptstraße 52, A-7063 Oggau\n\n' '7063 Oggau am Neusiedler See\n\n'
'Erstellt als Gemeinde-Informationssystem für Bürgerinnen und Bürger.\n' 'Zweck der App:\n'
'Alle Rechte vorbehalten.', 'Informations- und Mitmach-Plattform für Bürgerinnen und Bürger der Marktgemeinde Oggau am Neusiedler See.',
style: TextStyle(fontSize: 12, color: Colors.black87), style: TextStyle(fontSize: 12, color: Colors.black87, height: 1.4),
), ),
], ],
), ),
), ),
), ),
const SizedBox(height: 16),
], ],
), ),
); );
+21 -2
View File
@@ -124,13 +124,32 @@ class _PostListScreenState extends State<PostListScreen> {
autofocus: true, autofocus: true,
style: const TextStyle(color: Colors.black87), style: const TextStyle(color: Colors.black87),
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Suche nach ${widget.title}...', hintText: 'Suche in ${widget.title}...',
border: InputBorder.none, border: InputBorder.none,
hintStyle: TextStyle(color: Colors.grey.shade600), hintStyle: TextStyle(color: Colors.grey.shade600),
), ),
onChanged: (val) => setState(() => _searchQuery = val.trim()), onChanged: (val) => setState(() => _searchQuery = val.trim()),
) )
: Text(widget.title), : Row(
mainAxisSize: MainAxisSize.min,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.asset(
'assets/images/logo.png',
height: 26,
fit: BoxFit.contain,
),
),
const SizedBox(width: 8),
Flexible(
child: Text(
widget.title,
overflow: TextOverflow.ellipsis,
),
),
],
),
actions: [ actions: [
IconButton( IconButton(
icon: Icon(_isSearchActive ? Icons.close : Icons.search), icon: Icon(_isSearchActive ? Icons.close : Icons.search),
+2 -4
View File
@@ -78,10 +78,8 @@ flutter:
# the material Icons class. # the material Icons class.
uses-material-design: true uses-material-design: true
# To add assets to your application, add an assets section, like this: assets:
# assets: - assets/images/
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see # An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware # https://flutter.dev/assets-and-images/#resolution-aware