Skip to content

Commit

Permalink
62: Implement tools screen
Browse files Browse the repository at this point in the history
  • Loading branch information
steffenkleinle committed Feb 6, 2025
1 parent 9295d90 commit 9e104ab
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 34 deletions.
2 changes: 1 addition & 1 deletion lib/app/constants/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class Routes {
static GoRoute mfaTokenScan = buildRoute('token-scan', t.mfa.tokenScan.title, TokenScanScreen());
static GoRoute mfaTokenInput = buildRoute('token-input', t.mfa.tokenInput.title, TokenInputScreen());
static GoRoute mfa = buildRoute('/mfa', t.mfa.mfa, MfaScreen(), routes: [mfaTokenScan, mfaTokenInput]);
static GoRoute tools = buildRoute('/tools', t.tools.tools, ToolsScreen());
static GoRoute tools = buildRoute('/tools', t.tools.tools, ToolsScreen(), withMainLayout: false);
static GoRoute login = buildRoute('/login', t.login.login, LoginScreen(), withMainLayout: false);
static GoRoute support = buildRoute('support', t.settings.support.support, SupportScreen());
static GoRoute settings = buildRoute(
Expand Down
24 changes: 21 additions & 3 deletions lib/features/settings/screens/support_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,41 @@ class SupportScreen extends StatelessWidget {
SettingsCard(
title: t.settings.support.generalFeedback,
subtitle: supportEnabled ? grueneSupportMail : '',
icon: 'assets/icons/gruene.png',
icon: Image.asset(
'assets/icons/gruene.png',
height: 48,
width: 48,
color: supportEnabled ? null : Colors.grey,
colorBlendMode: supportEnabled ? null : BlendMode.saturation,
),
onPress: () => openMail(grueneSupportMail, context),
isExternal: true,
isEnabled: supportEnabled,
),
SettingsCard(
title: t.settings.support.campaignSupport,
subtitle: supportEnabled ? pollionSupportMail : '',
icon: 'assets/icons/pollion.png',
icon: Image.asset(
'assets/icons/pollion.png',
height: 48,
width: 48,
color: supportEnabled ? null : Colors.grey,
colorBlendMode: supportEnabled ? null : BlendMode.saturation,
),
onPress: () => openMail(pollionSupportMail, context),
isExternal: true,
isEnabled: supportEnabled,
),
SettingsCard(
title: t.settings.support.otherSupport,
subtitle: supportEnabled ? verdigadoSupportMail : '',
icon: 'assets/icons/verdigado.png',
icon: Image.asset(
'assets/icons/verdigado.png',
height: 48,
width: 48,
color: supportEnabled ? null : Colors.grey,
colorBlendMode: supportEnabled ? null : BlendMode.saturation,
),
onPress: () => openMail(verdigadoSupportMail, context),
isExternal: true,
isEnabled: supportEnabled,
Expand Down
32 changes: 14 additions & 18 deletions lib/features/settings/widgets/settings_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ import 'package:flutter/material.dart';
import 'package:gruene_app/app/theme/theme.dart';

class SettingsCard extends StatelessWidget {
final String icon;
final Widget icon;
final String title;
final String subtitle;
final bool isExternal;
final bool isEnabled;
final void Function() onPress;
final void Function()? onPress;

const SettingsCard({
super.key,
required this.icon,
required this.title,
required this.subtitle,
required this.onPress,
this.onPress,
this.isExternal = false,
this.isEnabled = true,
});
Expand All @@ -40,7 +40,7 @@ class SettingsCard extends StatelessWidget {
borderRadius: BorderRadius.circular(10),
),
child: ListTile(
onTap: isEnabled ? onPress : null,
onTap: isEnabled && onPress != null ? onPress : null,
contentPadding: EdgeInsets.symmetric(horizontal: 12),
title: Text(
title,
Expand All @@ -49,21 +49,17 @@ class SettingsCard extends StatelessWidget {
subtitle: Text(subtitle, style: TextStyle(color: isEnabled ? ThemeColors.text : ThemeColors.textDisabled)),
leading: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.asset(
icon,
height: 48,
width: 48,
color: isEnabled ? null : Colors.grey,
colorBlendMode: isEnabled ? null : BlendMode.saturation,
),
),
trailing: Padding(
padding: const EdgeInsets.only(right: 10),
child: Icon(
isExternal ? Icons.open_in_browser_outlined : Icons.chevron_right_outlined,
color: theme.disabledColor,
),
child: icon,
),
trailing: onPress != null
? Padding(
padding: const EdgeInsets.only(right: 10),
child: Icon(
isExternal ? Icons.open_in_browser_outlined : Icons.chevron_right_outlined,
color: theme.disabledColor,
),
)
: null,
),
),
);
Expand Down
13 changes: 13 additions & 0 deletions lib/features/tools/domain/tools_api_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:gruene_app/app/services/gruene_api_core.dart';
import 'package:gruene_app/swagger_generated_code/gruene_api.swagger.dart';

Future<List<GnetzApplication>> fetchTools() async => getFromApi(
request: (api) => api.v1GnetzApplicationsGet(),
map: (data) => data.data,
);

List<GnetzApplicationCategory> getToolCategories(List<GnetzApplication> tools) {
final categories = tools.map((tool) => tool.categories).expand((it) => it).toSet().toList();
categories.sort((a, b) => a.order.compareTo(b.order));
return categories;
}
34 changes: 22 additions & 12 deletions lib/features/tools/screens/tools_screen.dart
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
import 'package:flutter/material.dart';
import 'package:gruene_app/app/theme/theme.dart';
import 'package:gruene_app/i18n/translations.g.dart';
import 'package:gruene_app/app/screens/future_loading_screen.dart';
import 'package:gruene_app/app/screens/tab_screen.dart';
import 'package:gruene_app/app/widgets/main_layout.dart';
import 'package:gruene_app/app/widgets/tab_bar.dart';
import 'package:gruene_app/features/tools/domain/tools_api_service.dart';
import 'package:gruene_app/features/tools/widgets/tools_list.dart';
import 'package:gruene_app/swagger_generated_code/gruene_api.swagger.dart';

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

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Padding(
padding: const EdgeInsets.fromLTRB(24, 33, 24, 26),
child: Center(
child: Text(
t.common.notImplementedYet,
style: theme.textTheme.bodyLarge?.apply(color: ThemeColors.text),
textAlign: TextAlign.center,
),
),
return FutureLoadingScreen(
load: fetchTools,
layoutBuilder: (Widget child) => MainLayout(child: child),
buildChild: (List<GnetzApplication> data) {
final tabs = getToolCategories(data)
.map(
(category) => TabModel(
label: category.title,
view: ToolsList(tools: data.where((tool) => tool.categories.contains(category)).toList()),
),
)
.toList();

return TabScreen(tabs: tabs);
},
);
}
}
32 changes: 32 additions & 0 deletions lib/features/tools/widgets/tools_list.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gruene_app/app/constants/config.dart';
import 'package:gruene_app/app/utils/open_url.dart';
import 'package:gruene_app/features/settings/widgets/settings_card.dart';
import 'package:gruene_app/swagger_generated_code/gruene_api.swagger.dart';

class ToolsList extends StatelessWidget {
final List<GnetzApplication> tools;

const ToolsList({super.key, required this.tools});

@override
Widget build(BuildContext context) {
return ListView(
padding: const EdgeInsets.all(16),
children: tools.map(
(tool) {
final icon = tool.icon;
final url = tool.url;
return SettingsCard(
title: tool.title,
subtitle: tool.shortDescription[Config.defaultLocale] as String? ?? '',
onPress: url != null ? () => openUrl(url, context) : null,
isExternal: true,
icon: icon != null ? SvgPicture.string(icon, width: 48, height: 48) : SizedBox(width: 48, height: 48),
);
},
).toList(),
);
}
}

0 comments on commit 9e104ab

Please sign in to comment.