ambito/lib/src/pages/actions/actions_page.dart

294 lines
8.2 KiB
Dart
Raw Normal View History

2024-09-18 15:07:08 +02:00
import 'package:ambito/src/domain/entity/massnahme/massnahme.dart';
2024-10-07 11:01:02 +02:00
import 'package:ambito/src/extensions/extensions.dart';
import 'package:ambito/src/packages/ambito_db/repositories/massnahme_repository.dart';
2024-09-27 15:30:39 +02:00
import 'package:ambito/src/widgets/form/fields/field_dropdown.dart';
2024-09-27 15:40:55 +02:00
import 'package:ambito/src/widgets/form/fields/field_monthsrangepicker.dart';
2024-09-27 15:30:39 +02:00
import 'package:ambito/src/widgets/form/form_widget.dart';
import 'package:ambito/src/widgets/form/form_widget_type.dart';
2024-09-18 15:07:08 +02:00
import 'package:cached_network_image/cached_network_image.dart';
import 'package:expandable_text/expandable_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
2024-09-18 15:07:08 +02:00
import '../../../main.dart';
class ActionsPage extends StatefulWidget {
2024-09-24 15:29:01 +02:00
const ActionsPage({super.key});
2024-09-18 15:07:08 +02:00
@override
State<StatefulWidget> createState() => ActionsPageState();
}
class ActionsPageState extends State<ActionsPage> {
Map<int, bool> visible = {};
List<String> effort = [];
List<String> effect = [];
2024-09-24 15:29:01 +02:00
Set<String> type = {};
2024-09-18 15:07:08 +02:00
String? filterType;
2024-09-24 15:29:01 +02:00
Set<String> areaType = {};
2024-09-18 15:07:08 +02:00
String? filterAreaType;
List<String> region = [];
2024-09-24 15:29:01 +02:00
String? filterSupport;
Set<String> support = {};
2024-09-27 15:30:39 +02:00
String? filterMonths;
Set<String> months = {};
List massnahmen = [];
2024-09-18 15:07:08 +02:00
@override
void initState() {
2024-09-24 15:29:01 +02:00
super.initState();
massnahmen = MassnahmeRepository().getAll();
2024-09-18 15:07:08 +02:00
effort = [];
effect = [];
2024-09-24 15:29:01 +02:00
type = {};
areaType = {};
2024-09-18 15:07:08 +02:00
region = [];
2024-09-24 15:29:01 +02:00
support = {};
2024-09-18 15:07:08 +02:00
}
Widget build(BuildContext context) {
// Step 1: Collect all distinct values in each Set in a single loop
final updatedTypes = <String>{};
final updatedAreaTypes = <String>{};
final updatedSupports = <String>{};
final updatedMonths = <String>{};
2024-09-18 15:07:08 +02:00
for (final massnahme in massnahmen) {
if (massnahme.actionGroup?.value != null) {
2024-09-24 15:29:01 +02:00
updatedTypes.add(massnahme.actionGroup!.value!);
2024-09-18 15:07:08 +02:00
}
2024-09-24 15:29:01 +02:00
massnahme.factsheetAreaType?.forEach((aType) {
updatedAreaTypes.add(aType.value!);
});
massnahme.fundingPrograms?.forEach((aType) {
updatedSupports.add(aType.value!);
});
massnahme.timeFrame?.forEach((tfType) {
updatedMonths.add(tfType.value!);
});
}
// Step 2: Update state with collected data in a single setState() call
2024-09-24 15:29:01 +02:00
setState(() {
type.addAll(updatedTypes);
areaType.addAll(updatedAreaTypes);
support.addAll(updatedSupports);
months.addAll(updatedMonths);
2024-09-24 15:29:01 +02:00
});
// Step 3: Generate the list of action cards with matching filters
final actionCards = massnahmen.map((massnahme) {
final typeMatches =
filterType == null || massnahme.actionGroup?.value == filterType;
final areaTypeMatches = filterAreaType == null ||
2024-09-24 15:29:01 +02:00
(massnahme.factsheetAreaType
?.any((aType) => aType.value == filterAreaType) ??
false);
final supportMatches = filterSupport == null ||
2024-09-24 15:29:01 +02:00
(massnahme.fundingPrograms
?.any((aType) => aType.value == filterSupport) ??
false);
// Update visibility in a single batch setState()
2024-09-18 15:07:08 +02:00
setState(() {
2024-09-24 15:29:01 +02:00
visible[massnahme.id] =
typeMatches && areaTypeMatches && supportMatches;
2024-09-18 15:07:08 +02:00
});
2024-09-24 15:29:01 +02:00
return getCard(context, massnahme);
}).toList();
2024-09-18 15:07:08 +02:00
// Step 4: Return UI widget structure
2024-09-18 15:07:08 +02:00
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
2024-09-18 15:07:08 +02:00
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.translate('page.actions.title'),
style: Theme.of(context).textTheme.headlineLarge,
),
getSpacer(),
Text(
context.translate('page.actions.intro'),
style: Theme.of(context).textTheme.titleLarge,
),
getSpacer(),
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(width: 300, child: getFilter(context)),
const SizedBox(width: 16),
Expanded(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: actionCards,
),
),
),
],
2024-09-18 15:07:08 +02:00
),
),
getSpacer(),
2024-09-18 15:07:08 +02:00
],
),
);
}
Widget getSpacer() {
return const SizedBox(
height: 8,
);
}
Widget getFilter(BuildContext context) {
2024-09-27 15:30:39 +02:00
List<FormWidgetField> fields = [];
fields.add(
FieldDropdown(
name: 'ort',
label: 'Ort der Maßnahme',
filterValue: filterAreaType,
onClear: () {
setState(() {
filterAreaType = null;
});
},
onSelected: ((String? value) {
setState(() {
filterAreaType = value;
});
}),
entries: areaType.toList(),
),
);
fields.add(
FieldDropdown(
name: 'art',
label: 'Art der Maßnahme',
filterValue: filterType,
onClear: () {
setState(() {
filterType = null;
});
},
onSelected: ((String? value) {
setState(() {
filterType = value;
});
}),
entries: type.toList(),
),
);
fields.add(
FieldDropdown(
name: 'support',
label: 'Förderprogramm',
filterValue: filterSupport,
onClear: () {
setState(() {
filterSupport = null;
});
},
onSelected: ((String? value) {
setState(() {
filterSupport = value;
});
}),
entries: support.toList(),
),
);
List<String> monthsSorted = [];
for (int i = 1; i <= 12; i++) {
monthsSorted
.add(FlutterI18n.translate(context, 'general.lists.months.$i'));
}
2024-09-27 15:30:39 +02:00
fields.add(
2024-09-27 15:40:55 +02:00
FieldMonthsRangepicker(
2024-09-27 15:30:39 +02:00
name: 'months',
label: 'Beginn der Maßnahme',
filterValue: filterMonths,
onClear: () {},
onSelected: (String? value) {
logger.d(value);
},
entries: monthsSorted,
2024-09-27 15:30:39 +02:00
),
);
return FormWidget(type: FormWidgetType.vertical, fields: fields);
2024-09-18 15:07:08 +02:00
}
Widget getCard(BuildContext context, Massnahme massnahme) {
2024-09-24 15:29:01 +02:00
final Map<String, Color> actionGroupColors = {
'Baulelemente': const Color(0xffFFD269),
'Begrünung': const Color(0xff40DD74),
'Bewirtschaftung': const Color(0xffBF72ED),
'Nisthilfe': const Color(0xffDAE3FD),
'Pflanzung': const Color(0xff40D6E9),
'Sondermaßnahmen': const Color(0xff689EF1),
};
2024-09-18 15:07:08 +02:00
2024-09-24 15:29:01 +02:00
Color background =
actionGroupColors[massnahme.actionGroup?.value] ?? Colors.white;
CachedNetworkImage? image = massnahme.getThumbnail();
2024-09-18 15:07:08 +02:00
return Visibility(
visible: visible[massnahme.id] ?? false,
child: SizedBox(
width: 800,
2024-09-18 15:07:08 +02:00
child: Card(
color: background,
child: Padding(
padding: const EdgeInsets.all(32),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
2024-09-18 15:07:08 +02:00
children: [
(image != null)
? image
: const SizedBox(
width: 300,
height: 140,
),
2024-09-18 15:07:08 +02:00
const SizedBox(
width: 16,
2024-09-18 15:07:08 +02:00
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(massnahme.name!,
style: Theme.of(context).textTheme.headlineSmall),
const SizedBox(
height: 8,
),
ExpandableText(
massnahme.factsheetDefinition ?? '',
maxLines: 3,
expandText: 'mehr',
collapseText: 'weniger',
)
],
),
2024-09-18 15:07:08 +02:00
)
],
),
),
),
),
);
}
}