Skip to content

Commit

Permalink
185: add first campaign screen
Browse files Browse the repository at this point in the history
  • Loading branch information
Stift committed Nov 15, 2024
1 parent 2de110b commit 8643ba0
Show file tree
Hide file tree
Showing 13 changed files with 368 additions and 14 deletions.
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"FSharp.suggestGitignore": false,
"cSpell.words": [
"gruene"
],
"files.eol": "\n"
}
7 changes: 7 additions & 0 deletions assets/icons/refresh.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions devtools_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
25 changes: 18 additions & 7 deletions lib/app/theme/theme.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';

class ThemeColors {
Expand Down Expand Up @@ -31,7 +32,7 @@ class ThemeColors {
}

class _ThemeTextStyles {
// TOOD use GrueneType font
// TODO use GrueneType font
static TextStyle displayMedium = GoogleFonts.ptSans(
textStyle: TextStyle(
fontSize: 18,
Expand Down Expand Up @@ -78,12 +79,12 @@ final ThemeData appTheme = ThemeData.light().copyWith(
primaryColor: ThemeColors.primary,
disabledColor: ThemeColors.textDisabled,
colorScheme: ThemeData.light().colorScheme.copyWith(
primary: ThemeColors.primary,
secondary: ThemeColors.secondary,
tertiary: ThemeColors.tertiary,
surface: ThemeColors.background,
surfaceDim: ThemeColors.backgroundSecondary,
),
primary: ThemeColors.primary,
secondary: ThemeColors.secondary,
tertiary: ThemeColors.tertiary,
surface: ThemeColors.background,
surfaceDim: ThemeColors.backgroundSecondary,
),
textTheme: TextTheme(
displayLarge: _ThemeTextStyles.displayLarge,
displayMedium: _ThemeTextStyles.displayMedium,
Expand All @@ -101,4 +102,14 @@ final ThemeData appTheme = ThemeData.light().copyWith(
unselectedLabelStyle: _ThemeTextStyles.labelSmall,
),
scaffoldBackgroundColor: ThemeColors.backgroundSecondary,
actionIconTheme: ActionIconThemeData(
backButtonIconBuilder: (BuildContext context) => SvgPicture.asset('assets/icons/back.svg'),
),
tabBarTheme: TabBarTheme(
indicatorColor: ThemeColors.primary,
indicatorSize: TabBarIndicatorSize.tab,
labelStyle: _ThemeTextStyles.titleMedium,
unselectedLabelStyle: _ThemeTextStyles.titleMedium,
labelColor: ThemeColors.primary,
),
);
18 changes: 16 additions & 2 deletions lib/app/widgets/app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,28 @@ class MainAppBar extends StatelessWidget implements PreferredSizeWidget {
final currentRoute = GoRouterState.of(context);
final theme = Theme.of(context);
return AppBar(
title: Text(currentRoute.name ?? '', style: theme.textTheme.displayMedium?.apply(color: theme.colorScheme.surface)),
title: Text(
currentRoute.name ?? '',
style: theme.textTheme.displayMedium?.apply(color: theme.colorScheme.surface),
),
foregroundColor: theme.colorScheme.surface,
backgroundColor: theme.primaryColor,
centerTitle: true,
actions: [
if (currentRoute.path == Routes.campaigns)
IconButton(
icon: CustomIcon(
path: 'assets/icons/refresh.svg',
color: ThemeColors.background,
),
onPressed: null,
),
if (currentRoute.path != Routes.settings)
IconButton(
icon: CustomIcon(path: 'assets/icons/settings.svg', color: ThemeColors.background),
icon: CustomIcon(
path: 'assets/icons/settings.svg',
color: ThemeColors.background,
),
onPressed: () => context.push(Routes.settings),
),
],
Expand Down
89 changes: 85 additions & 4 deletions lib/features/campaigns/screens/campaigns_screen.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,93 @@
import 'package:flutter/material.dart';
import 'package:gruene_app/app/theme/theme.dart';
import 'package:gruene_app/features/campaigns/screens/doors_screen.dart';
import 'package:gruene_app/features/campaigns/screens/flyer_screen.dart';
import 'package:gruene_app/features/campaigns/screens/posters_screen.dart';
import 'package:gruene_app/features/campaigns/screens/statistics_screen.dart';
import 'package:gruene_app/features/campaigns/screens/teams_screen.dart';
import 'package:gruene_app/i18n/translations.g.dart';

class CampaignsScreen extends StatelessWidget {
const CampaignsScreen({super.key});
class CampaignsScreen extends StatefulWidget {
CampaignsScreen({super.key});
@override
State<CampaignsScreen> createState() => _CampaignsScreen();
}

class _CampaignsScreen extends State<CampaignsScreen> with SingleTickerProviderStateMixin {
final List<CampaignMenuModel> campaignTabs = <CampaignMenuModel>[
CampaignMenuModel(t.campaigns.door.label, true, DoorsScreen()),
CampaignMenuModel(t.campaigns.posters.label, true, PostersScreen()),
CampaignMenuModel(t.campaigns.flyer.label, true, FlyerScreen()),
CampaignMenuModel(t.campaigns.team.label, false, TeamsScreen()),
CampaignMenuModel(t.campaigns.statistic.label, false, StatisticsScreen()),
];
late TabController _tabController;

@override
void initState() {
_tabController = TabController(length: campaignTabs.length, vsync: this);
super.initState();
}

@override
void dispose() {
super.dispose();
_tabController.dispose();
}

void onTap(int index) {
setState(() {
_tabController.index = !campaignTabs[index]._enabled ? _tabController.previousIndex : index;
});
}

@override
Widget build(BuildContext context) {
return const Center(
child: Text('Campaigns Screen'),
return DefaultTabController(
initialIndex: 0,
length: campaignTabs.length,
child: Scaffold(
backgroundColor: ThemeColors.background,
appBar: AppBar(
shape: Border(bottom: BorderSide(color: ThemeColors.textLight, width: 2)),
toolbarHeight: 0,
backgroundColor: ThemeColors.backgroundSecondary,
bottom: TabBar(
controller: _tabController,
tabs: campaignTabs
.map(
(CampaignMenuModel item) => Tab(
child: Semantics(
child: Text(
item._tabTitle,
style: item._enabled ? null : TextStyle(color: ThemeColors.textDisabled),
),
),
),
)
.toList(),
isScrollable: true,
tabAlignment: TabAlignment.start,
indicatorWeight: 4,
onTap: (int index) => onTap(index),
),
),
body: TabBarView(
controller: _tabController,
physics: NeverScrollableScrollPhysics(),
children: campaignTabs.map((CampaignMenuModel tab) {
return tab._view;
}).toList(),
),
),
);
}
}

class CampaignMenuModel {
final String _tabTitle;
final bool _enabled;
final Widget _view;

const CampaignMenuModel(this._tabTitle, this._enabled, this._view);
}
28 changes: 28 additions & 0 deletions lib/features/campaigns/screens/doors_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:flutter/material.dart';
import 'package:gruene_app/features/campaigns/widgets/filter_chip_widget.dart';
import 'package:gruene_app/i18n/translations.g.dart';

class DoorsScreen extends StatelessWidget {
DoorsScreen({super.key});

final List<FilterChipModel> doorsFilter = [
FilterChipModel(t.campaigns.filters.visited_areas, false),
FilterChipModel(t.campaigns.filters.routes, false),
FilterChipModel(t.campaigns.filters.focusAreas, true),
FilterChipModel(t.campaigns.filters.experience_areas, false),
];
final Map<String, List<String>> doorsExclusions = <String, List<String>>{
t.campaigns.filters.focusAreas: [t.campaigns.filters.visited_areas],
t.campaigns.filters.visited_areas: [t.campaigns.filters.focusAreas],
};

@override
Widget build(BuildContext context) {
return Column(
children: [
FilterChipCampaign(doorsFilter, doorsExclusions),
Center(child: Text(t.campaigns.door.label)),
],
);
}
}
23 changes: 23 additions & 0 deletions lib/features/campaigns/screens/flyer_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import 'package:flutter/widgets.dart';
import 'package:gruene_app/features/campaigns/widgets/filter_chip_widget.dart';
import 'package:gruene_app/i18n/translations.g.dart';

class FlyerScreen extends StatelessWidget {
FlyerScreen({super.key});

final List<FilterChipModel> flyerFilter = [
FilterChipModel(t.campaigns.filters.visited_areas, false),
FilterChipModel(t.campaigns.filters.routes, false),
FilterChipModel(t.campaigns.filters.experience_areas, false),
];

@override
Widget build(BuildContext context) {
return Column(
children: [
FilterChipCampaign(flyerFilter, <String, List<String>>{}),
Center(child: Text(t.campaigns.flyer.label)),
],
);
}
}
22 changes: 22 additions & 0 deletions lib/features/campaigns/screens/posters_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import 'package:flutter/widgets.dart';
import 'package:gruene_app/features/campaigns/widgets/filter_chip_widget.dart';
import 'package:gruene_app/i18n/translations.g.dart';

class PostersScreen extends StatelessWidget {
PostersScreen({super.key});

final List<FilterChipModel> postersFilter = [
FilterChipModel(t.campaigns.filters.routes, false),
FilterChipModel(t.campaigns.filters.polling_stations, false),
FilterChipModel(t.campaigns.filters.experience_areas, false),
];
@override
Widget build(BuildContext context) {
return Column(
children: [
FilterChipCampaign(postersFilter, <String, List<String>>{}),
Center(child: Text(t.campaigns.posters.label)),
],
);
}
}
20 changes: 20 additions & 0 deletions lib/features/campaigns/screens/statistics_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
import 'package:gruene_app/app/theme/theme.dart';
import 'package:gruene_app/i18n/translations.g.dart';

class StatisticsScreen extends StatelessWidget {
const StatisticsScreen({super.key});

@override
Widget build(BuildContext context) {
return Placeholder(
color: Colors.red,
child: Center(
child: Text(
t.campaigns.statistic.label,
style: TextStyle(fontSize: 20, color: ThemeColors.primary),
),
),
);
}
}
20 changes: 20 additions & 0 deletions lib/features/campaigns/screens/teams_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
import 'package:gruene_app/app/theme/theme.dart';
import 'package:gruene_app/i18n/translations.g.dart';

class TeamsScreen extends StatelessWidget {
const TeamsScreen({super.key});

@override
Widget build(BuildContext context) {
return Placeholder(
color: Colors.red,
child: Center(
child: Text(
t.campaigns.team.label,
style: TextStyle(fontSize: 20, color: ThemeColors.primary),
),
),
);
}
}
Loading

0 comments on commit 8643ba0

Please sign in to comment.