Filters & Calendars

This commit is contained in:
reinjens 2024-11-07 05:52:03 +01:00
parent 4aa60980a1
commit 798941af12
52 changed files with 4481 additions and 623 deletions

View file

@ -1,32 +1,69 @@
{
"page": {
"start": {
"general": {
"title": "AmBiTo Toolkit",
"links": {
"start": {
"title": "Start"
},
"database": {
"massnahmen": {
"title": "Maßnahmen"
},
"designer": {
"title": "Designer"
"dashboard": {
"title": "Dashboard"
}
},
"spacer": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
},
"start": {
"links": {
"massnahmen": {
"title": "Maßnahmen"
},
"service": {
"title": "Beratung"
},
"network": {
"title": "Netzwerk"
},
"contact": {
"title": "Kontakt"
"dashboard": {
"title": "Dashboard"
}
}
},
"actions": {
"title": "Recherchieren Sie in allen Biodiversitätsmaßnahmen",
"intro": "In dieser Datenbank finden Sie die Maßnahmen, die zu Ihrem Betrieb und Ihrer Region passen."
"actionDetailPage": {
"description": {
"title": "Beschreibung"
},
"background": {
"title": "Hintergrund",
"areaType": "Flächentyp",
"target": "Zielsetzung"
},
"presets": {
"title": "Vorraussetzungen",
"tips": "Tipps"
},
"biodiversity": {
"title": "Biodiversitätsbewertung"
},
"creation":{
"title": "Anlage",
"timeFrame": "Zeitrahmen"
},
"maintenance": {
"title": "Pflege"
},
"funding": {
"title": "Förderungen"
},
"advisor": {
"title": "Ansprechpartner"
},
"factsheet": {
"title": "Factsheet",
"download": "Download"
},
"review": {
"title": "Rezensionen"
},
"material": {
"title": "Material",
"suggested_price": "Preis ca. ",
"add_to_basket": "in den Warenkorb"
}
}
},
"general": {

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 639 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View file

@ -1,14 +1,21 @@
import 'package:ambito/src/packages/ambito_api/base_api.dart';
import 'package:ambito/src/packages/ambito_db/base_db.dart';
import 'package:ambito/src/pages/loading/loading_page.dart';
import 'package:ambito/src/packages/ambito_sharedprefs/ambito_sharedprefs.dart';
import 'package:ambito/src/packages/ambito_theme/ambito_theme.dart';
import 'package:ambito/src/pages/actions/action_detail_page.dart';
import 'package:ambito/src/pages/actions/actions_page.dart';
import 'package:ambito/src/pages/actions/actions_pre_page.dart';
import 'package:ambito/src/pages/calendar/calendar_page.dart';
import 'package:ambito/src/pages/calendar/calendar_page_year.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:get/get_navigation/src/root/get_material_app.dart';
import 'package:get/get.dart';
import 'package:isar/isar.dart';
import 'package:logger/logger.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:syncfusion_localizations/syncfusion_localizations.dart';
final Logger logger = Logger(
@ -16,28 +23,31 @@ final Logger logger = Logger(
);
late Isar isar;
late SharedPreferences prefs;
AmbitoTheme baseTheme = AmbitoTheme();
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await dotenv.load(fileName: '.env');
await AmbitoIsarDB().init();
await AmbitoSharedPrefs.start();
await AmbitoIsarDB.init();
await Future.wait([
/*BaseApi().getContent('tree_type'),
//BaseApi().getContent('tree_type'),
BaseApi().getContent('measure'),
BaseApi().getContent('measure_combination'),
BaseApi().getContent('organism'),
BaseApi().getContent('funding_program'),
BaseApi().getContent('location_requirements'),
BaseApi().getContent('reference_implementation'),
BaseApi().getContent('business'),
BaseApi().getContent('service_provider'),
BaseApi().getContent('service_provider_contact_person'),
BaseApi().getContent('material'),*/
BaseApi().getContent('source'),
//BaseApi().getContent('organism'),
//BaseApi().getContent('funding_program'),
//BaseApi().getContent('location_requirements'),
//BaseApi().getContent('reference_implementation'),
//BaseApi().getContent('business'),
//BaseApi().getContent('service_provider'),
//BaseApi().getContent('service_provider_contact_person'),
//BaseApi().getContent('material'),
//BaseApi().getContent('source'),
]);
await MeasureRepository().buildMeasureFilters();
runApp(const Ambito());
}
@ -64,15 +74,37 @@ class Ambito extends StatelessWidget {
GlobalWidgetsLocalizations.delegate,
SfGlobalLocalizations.delegate,
],
title: 'Flutter Demo',
title: 'AmBiTo',
supportedLocales: const [Locale('de')],
locale: const Locale('de'),
builder: FlutterI18n.rootAppBuilder(),
theme: ThemeData(
scaffoldBackgroundColor: Colors.white,
useMaterial3: true,
),
home: const LoadingPage(),
theme: baseTheme.lightThemeData,
darkTheme: baseTheme.darkThemeData,
themeMode: ThemeMode.light,
initialRoute: '/massnahmen',
getPages: [
GetPage(
name: '/',
page: () => const ActionsPrePage(),
),
GetPage(
name: '/kalender',
page: () => const CalendarPage(),
),
GetPage(
name: '/kalender/jahr',
page: () => const CalendarPageYear(),
),
GetPage(
name: '/massnahmen',
page: () => const ActionsPrePage(),
),
GetPage(
name: '/massnahmendatenbank',
page: () => const ActionsPage(),
),
GetPage(name: '/massnahme/:id', page: () => const ActionDetailPage())
],
);
}
}

View file

@ -0,0 +1,24 @@
import 'package:ambito/src/entity/base_entity.dart';
import 'package:isar/isar.dart';
import 'package:json_annotation/json_annotation.dart';
part 'item_filter.g.dart';
@collection
@JsonSerializable(explicitToJson: true)
class ItemFilter extends BaseEntity with EntityWithId {
ItemFilter();
String? type;
@Index(composite: ['type'], unique: true, hash: true)
String? name;
String? description;
String? image;
String? color;
List<int>? ids = [];
factory ItemFilter.fromJson(Map<String, dynamic> json) =>
_$ItemFilterFromJson(json);
Map<String, dynamic> toJson() => _$ItemFilterToJson(this);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,40 @@
import 'package:ambito/src/entity/entities.dart';
import 'package:ambito/src/packages/ambito_db/base_db.dart';
import 'package:ambito/src/packages/ambito_notifier/notifier/filter_notifier.dart';
import 'package:isar/isar.dart';
import '../../../../main.dart';
import '../../../widgets/form/fields/field_dropdown.dart';
class ItemFilterRepository extends BaseDB {
@override
IsarCollection collection = isar.itemFilters;
List<ItemFilter>? getByType(String type) {
return isar.itemFilters.where().typeEqualTo(type).findAll();
}
List<dynamic>? getIdsByType(String type) {
return isar.itemFilters
.where()
.typeEqualTo(type)
.idsProperty()
.findAll()
.expand((list) => list ?? [])
.toSet()
.toList();
}
FieldDropdown getDropDown(String type, String label) {
List<ItemFilter> filterItems = getByType(type)!;
return FieldDropdown(
name: type,
label: label,
filterValue: ambitoFilterNotifier.activeFilters[type],
onClear: () => ambitoFilterNotifier.removeFilter(type),
onSelected: (value) => ambitoFilterNotifier.setFilter(type, value ?? ''),
entries: filterItems.map((item) => item.name!).toList(),
);
}
}

View file

@ -3,6 +3,7 @@ library ambito_entities;
export '_general/file/file_part.dart';
export '_general/file/thumbnail.dart';
export '_general/file/thumbnails.dart';
export '_general/filter/item_filter.dart';
export '_general/id_value/id_value.dart';
export '_general/id_value_color/id_value_color.dart';
export '_general/id_value_mix/id_value_mix.dart';

View file

@ -51,7 +51,7 @@ class Measure extends BaseEntity with EntityWithId {
@JsonKey(name: "Tipp - Anlage")
String? attachmentTip;
@JsonKey(name: "Zeitrahmen Pflege")
String? timeMaintenance;
List<IdValueColor>? timeMaintenance;
@JsonKey(name: "Arbeitsschritte Pflege")
String? workMaintenance;
@JsonKey(name: "Frequenz Pflege")
@ -159,4 +159,20 @@ extension MeasureExtension on Measure {
}
return image;
}
CachedNetworkImage? getImage() {
CachedNetworkImage? image;
if (files != null && files!.isNotEmpty) {
if (files![0].thumbnails?.cardCover?.url != null) {
image = CachedNetworkImage(
width: 600,
height: 350,
imageUrl: files![0].thumbnails!.cardCover!.url!,
placeholder: (context, url) => const CircularProgressIndicator(),
errorWidget: (context, url, error) => const Icon(Icons.error),
);
}
}
return image;
}
}

View file

@ -100,7 +100,8 @@ const MeasureSchema = IsarGeneratedSchema(
),
IsarPropertySchema(
name: 'timeMaintenance',
type: IsarType.string,
type: IsarType.objectList,
target: 'IdValueColor',
),
IsarPropertySchema(
name: 'workMaintenance',
@ -497,11 +498,20 @@ int serializeMeasure(IsarWriter writer, Measure object) {
}
}
{
final value = object.timeMaintenance;
if (value == null) {
final list = object.timeMaintenance;
if (list == null) {
IsarCore.writeNull(writer, 20);
} else {
IsarCore.writeString(writer, 20, value);
final listWriter = IsarCore.beginList(writer, 20, list.length);
for (var i = 0; i < list.length; i++) {
{
final value = list[i];
final objectWriter = IsarCore.beginObject(listWriter, i);
serializeIdValueColor(objectWriter, value);
IsarCore.endObject(listWriter, objectWriter);
}
}
IsarCore.endList(writer, listWriter);
}
}
{
@ -1123,7 +1133,32 @@ Measure deserializeMeasure(IsarReader reader) {
object.timeAction = IsarCore.readString(reader, 17);
object.serviceProvider = IsarCore.readString(reader, 18);
object.attachmentTip = IsarCore.readString(reader, 19);
object.timeMaintenance = IsarCore.readString(reader, 20);
{
final length = IsarCore.readList(reader, 20, IsarCore.readerPtrPtr);
{
final reader = IsarCore.readerPtr;
if (reader.isNull) {
object.timeMaintenance = null;
} else {
final list =
List<IdValueColor>.filled(length, IdValueColor(), growable: true);
for (var i = 0; i < length; i++) {
{
final objectReader = IsarCore.readObject(reader, i);
if (objectReader.isNull) {
list[i] = IdValueColor();
} else {
final embedded = deserializeIdValueColor(objectReader);
IsarCore.freeReader(objectReader);
list[i] = embedded;
}
}
}
IsarCore.freeReader(reader);
object.timeMaintenance = list;
}
}
}
object.workMaintenance = IsarCore.readString(reader, 21);
{
final length = IsarCore.readList(reader, 22, IsarCore.readerPtrPtr);
@ -1818,7 +1853,32 @@ dynamic deserializeMeasureProp(IsarReader reader, int property) {
case 19:
return IsarCore.readString(reader, 19);
case 20:
return IsarCore.readString(reader, 20);
{
final length = IsarCore.readList(reader, 20, IsarCore.readerPtrPtr);
{
final reader = IsarCore.readerPtr;
if (reader.isNull) {
return null;
} else {
final list = List<IdValueColor>.filled(length, IdValueColor(),
growable: true);
for (var i = 0; i < length; i++) {
{
final objectReader = IsarCore.readObject(reader, i);
if (objectReader.isNull) {
list[i] = IdValueColor();
} else {
final embedded = deserializeIdValueColor(objectReader);
IsarCore.freeReader(objectReader);
list[i] = embedded;
}
}
}
IsarCore.freeReader(reader);
return list;
}
}
}
case 21:
return IsarCore.readString(reader, 21);
case 22:
@ -2497,7 +2557,6 @@ sealed class _MeasureUpdate {
String? timeAction,
String? serviceProvider,
String? attachmentTip,
String? timeMaintenance,
String? workMaintenance,
String? specialsMaintenance,
String? matchingActions,
@ -2546,7 +2605,6 @@ class _MeasureUpdateImpl implements _MeasureUpdate {
Object? timeAction = ignore,
Object? serviceProvider = ignore,
Object? attachmentTip = ignore,
Object? timeMaintenance = ignore,
Object? workMaintenance = ignore,
Object? specialsMaintenance = ignore,
Object? matchingActions = ignore,
@ -2590,7 +2648,6 @@ class _MeasureUpdateImpl implements _MeasureUpdate {
if (timeAction != ignore) 17: timeAction as String?,
if (serviceProvider != ignore) 18: serviceProvider as String?,
if (attachmentTip != ignore) 19: attachmentTip as String?,
if (timeMaintenance != ignore) 20: timeMaintenance as String?,
if (workMaintenance != ignore) 21: workMaintenance as String?,
if (specialsMaintenance != ignore) 23: specialsMaintenance as String?,
if (matchingActions != ignore) 24: matchingActions as String?,
@ -2643,7 +2700,6 @@ sealed class _MeasureUpdateAll {
String? timeAction,
String? serviceProvider,
String? attachmentTip,
String? timeMaintenance,
String? workMaintenance,
String? specialsMaintenance,
String? matchingActions,
@ -2692,7 +2748,6 @@ class _MeasureUpdateAllImpl implements _MeasureUpdateAll {
Object? timeAction = ignore,
Object? serviceProvider = ignore,
Object? attachmentTip = ignore,
Object? timeMaintenance = ignore,
Object? workMaintenance = ignore,
Object? specialsMaintenance = ignore,
Object? matchingActions = ignore,
@ -2734,7 +2789,6 @@ class _MeasureUpdateAllImpl implements _MeasureUpdateAll {
if (timeAction != ignore) 17: timeAction as String?,
if (serviceProvider != ignore) 18: serviceProvider as String?,
if (attachmentTip != ignore) 19: attachmentTip as String?,
if (timeMaintenance != ignore) 20: timeMaintenance as String?,
if (workMaintenance != ignore) 21: workMaintenance as String?,
if (specialsMaintenance != ignore) 23: specialsMaintenance as String?,
if (matchingActions != ignore) 24: matchingActions as String?,
@ -2788,7 +2842,6 @@ sealed class _MeasureQueryUpdate {
String? timeAction,
String? serviceProvider,
String? attachmentTip,
String? timeMaintenance,
String? workMaintenance,
String? specialsMaintenance,
String? matchingActions,
@ -2837,7 +2890,6 @@ class _MeasureQueryUpdateImpl implements _MeasureQueryUpdate {
Object? timeAction = ignore,
Object? serviceProvider = ignore,
Object? attachmentTip = ignore,
Object? timeMaintenance = ignore,
Object? workMaintenance = ignore,
Object? specialsMaintenance = ignore,
Object? matchingActions = ignore,
@ -2879,7 +2931,6 @@ class _MeasureQueryUpdateImpl implements _MeasureQueryUpdate {
if (timeAction != ignore) 17: timeAction as String?,
if (serviceProvider != ignore) 18: serviceProvider as String?,
if (attachmentTip != ignore) 19: attachmentTip as String?,
if (timeMaintenance != ignore) 20: timeMaintenance as String?,
if (workMaintenance != ignore) 21: workMaintenance as String?,
if (specialsMaintenance != ignore) 23: specialsMaintenance as String?,
if (matchingActions != ignore) 24: matchingActions as String?,
@ -2940,7 +2991,6 @@ class _MeasureQueryBuilderUpdateImpl implements _MeasureQueryUpdate {
Object? timeAction = ignore,
Object? serviceProvider = ignore,
Object? attachmentTip = ignore,
Object? timeMaintenance = ignore,
Object? workMaintenance = ignore,
Object? specialsMaintenance = ignore,
Object? matchingActions = ignore,
@ -2984,7 +3034,6 @@ class _MeasureQueryBuilderUpdateImpl implements _MeasureQueryUpdate {
if (timeAction != ignore) 17: timeAction as String?,
if (serviceProvider != ignore) 18: serviceProvider as String?,
if (attachmentTip != ignore) 19: attachmentTip as String?,
if (timeMaintenance != ignore) 20: timeMaintenance as String?,
if (workMaintenance != ignore) 21: workMaintenance as String?,
if (specialsMaintenance != ignore) 23: specialsMaintenance as String?,
if (matchingActions != ignore) 24: matchingActions as String?,
@ -6344,180 +6393,18 @@ extension MeasureQueryFilter
});
}
QueryBuilder<Measure, Measure, QAfterFilterCondition> timeMaintenanceEqualTo(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
EqualCondition(
property: 20,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Measure, Measure, QAfterFilterCondition>
timeMaintenanceGreaterThan(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
GreaterCondition(
property: 20,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Measure, Measure, QAfterFilterCondition>
timeMaintenanceGreaterThanOrEqualTo(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
GreaterOrEqualCondition(
property: 20,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Measure, Measure, QAfterFilterCondition> timeMaintenanceLessThan(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
LessCondition(
property: 20,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Measure, Measure, QAfterFilterCondition>
timeMaintenanceLessThanOrEqualTo(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
LessOrEqualCondition(
property: 20,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Measure, Measure, QAfterFilterCondition> timeMaintenanceBetween(
String? lower,
String? upper, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
BetweenCondition(
property: 20,
lower: lower,
upper: upper,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Measure, Measure, QAfterFilterCondition>
timeMaintenanceStartsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
StartsWithCondition(
property: 20,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Measure, Measure, QAfterFilterCondition> timeMaintenanceEndsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
EndsWithCondition(
property: 20,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Measure, Measure, QAfterFilterCondition> timeMaintenanceContains(
String value,
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
ContainsCondition(
property: 20,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Measure, Measure, QAfterFilterCondition> timeMaintenanceMatches(
String pattern,
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
MatchesCondition(
property: 20,
wildcard: pattern,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Measure, Measure, QAfterFilterCondition>
timeMaintenanceIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const EqualCondition(
property: 20,
value: '',
),
);
});
return not().group(
(q) => q.timeMaintenanceIsNull().or().timeMaintenanceIsNotEmpty(),
);
}
QueryBuilder<Measure, Measure, QAfterFilterCondition>
timeMaintenanceIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const GreaterCondition(
property: 20,
value: '',
),
const GreaterOrEqualCondition(property: 20, value: null),
);
});
}
@ -11325,27 +11212,6 @@ extension MeasureQuerySortBy on QueryBuilder<Measure, Measure, QSortBy> {
});
}
QueryBuilder<Measure, Measure, QAfterSortBy> sortByTimeMaintenance(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(
20,
caseSensitive: caseSensitive,
);
});
}
QueryBuilder<Measure, Measure, QAfterSortBy> sortByTimeMaintenanceDesc(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(
20,
sort: Sort.desc,
caseSensitive: caseSensitive,
);
});
}
QueryBuilder<Measure, Measure, QAfterSortBy> sortByWorkMaintenance(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
@ -12010,20 +11876,6 @@ extension MeasureQuerySortThenBy
});
}
QueryBuilder<Measure, Measure, QAfterSortBy> thenByTimeMaintenance(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(20, caseSensitive: caseSensitive);
});
}
QueryBuilder<Measure, Measure, QAfterSortBy> thenByTimeMaintenanceDesc(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(20, sort: Sort.desc, caseSensitive: caseSensitive);
});
}
QueryBuilder<Measure, Measure, QAfterSortBy> thenByWorkMaintenance(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
@ -12436,13 +12288,6 @@ extension MeasureQueryWhereDistinct
});
}
QueryBuilder<Measure, Measure, QAfterDistinct> distinctByTimeMaintenance(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(20, caseSensitive: caseSensitive);
});
}
QueryBuilder<Measure, Measure, QAfterDistinct> distinctByWorkMaintenance(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
@ -12702,7 +12547,8 @@ extension MeasureQueryProperty1 on QueryBuilder<Measure, Measure, QProperty> {
});
}
QueryBuilder<Measure, String?, QAfterProperty> timeMaintenanceProperty() {
QueryBuilder<Measure, List<IdValueColor>?, QAfterProperty>
timeMaintenanceProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(20);
});
@ -13126,7 +12972,7 @@ extension MeasureQueryProperty2<R> on QueryBuilder<Measure, R, QAfterProperty> {
});
}
QueryBuilder<Measure, (R, String?), QAfterProperty>
QueryBuilder<Measure, (R, List<IdValueColor>?), QAfterProperty>
timeMaintenanceProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(20);
@ -13564,7 +13410,7 @@ extension MeasureQueryProperty3<R1, R2>
});
}
QueryBuilder<Measure, (R1, R2, String?), QOperations>
QueryBuilder<Measure, (R1, R2, List<IdValueColor>?), QOperations>
timeMaintenanceProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(20);
@ -13907,7 +13753,9 @@ Measure _$MeasureFromJson(Map<String, dynamic> json) => Measure()
..timeAction = json['Fachgerechte Umsetzung_Anlage_Kosten_Zeit'] as String?
..serviceProvider = json['Dienstleister redundant'] as String?
..attachmentTip = json['Tipp - Anlage'] as String?
..timeMaintenance = json['Zeitrahmen Pflege'] as String?
..timeMaintenance = (json['Zeitrahmen Pflege'] as List<dynamic>?)
?.map((e) => IdValueColor.fromJson(e as Map<String, dynamic>))
.toList()
..workMaintenance = json['Arbeitsschritte Pflege'] as String?
..frequencyMaintenance = (json['Frequenz Pflege'] as List<dynamic>?)
?.map((e) => IdValueColor.fromJson(e as Map<String, dynamic>))
@ -14025,7 +13873,8 @@ Map<String, dynamic> _$MeasureToJson(Measure instance) => <String, dynamic>{
'Fachgerechte Umsetzung_Anlage_Kosten_Zeit': instance.timeAction,
'Dienstleister redundant': instance.serviceProvider,
'Tipp - Anlage': instance.attachmentTip,
'Zeitrahmen Pflege': instance.timeMaintenance,
'Zeitrahmen Pflege':
instance.timeMaintenance?.map((e) => e.toJson()).toList(),
'Arbeitsschritte Pflege': instance.workMaintenance,
'Frequenz Pflege':
instance.frequencyMaintenance?.map((e) => e.toJson()).toList(),

View file

@ -1,4 +1,6 @@
import 'package:ambito/src/entity/_general/filter/item_filter_repository.dart';
import 'package:ambito/src/entity/entities.dart';
import 'package:ambito/src/extensions/extensions.dart';
import 'package:ambito/src/packages/ambito_db/base_db.dart';
import 'package:isar/isar.dart';
@ -7,4 +9,96 @@ import '../../../../main.dart';
class MeasureRepository extends BaseDB {
@override
IsarCollection collection = isar.measures;
Future<bool> buildMeasureFilters() async {
Map<String, List<int>> filtersAreaType = {};
Map<String, List<int>> filtersMeasureGroup = {};
Map<String, List<int>> filterMonths = {};
Map<String, List<int>> filterFundingPrograms = {};
Map<String, String> colors = {};
var measures = getAll();
for (Measure measure in measures) {
measure.factsheetAreaType?.forEach((ivc) {
filtersAreaType.putIfAbsent(ivc.value!, () => []).add(measure.id);
colors[ivc.value!] = ivc.color!;
});
if (measure.actionGroup != null) {
filtersMeasureGroup
.putIfAbsent(measure.actionGroup!.value!, () => [])
.add(measure.id);
colors[measure.actionGroup!.value!] = measure.actionGroup!.color!;
}
measure.timeFrame?.forEach((ivc) {
filterMonths.putIfAbsent(ivc.value!, () => []).add(measure.id);
colors[ivc.value!] = ivc.color!;
});
measure.fundingPrograms?.forEach((ivc) {
filterFundingPrograms.putIfAbsent(ivc.value!, () => []).add(measure.id);
});
}
final itemFilterRepo = ItemFilterRepository();
final autoIncrement = isar.itemFilters.autoIncrement;
itemFilterRepo.putAll(filtersAreaType.entries
.map((entry) => ItemFilter()
..id = autoIncrement()
..name = entry.key
..type = 'areaType'
..description =
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.'
..image =
'images/actions/areatype/${entry.key.toLowerCase().replaceUmlauts()}.jpg'
..color = colors[entry.key]
..ids = entry.value)
.toList());
itemFilterRepo.putAll(filtersMeasureGroup.entries
.map((entry) => ItemFilter()
..id = autoIncrement()
..name = entry.key
..type = 'group'
..description =
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.'
..image =
'images/actions/areatype/${entry.key.toLowerCase().replaceUmlauts()}.jpg'
..color = colors[entry.key]
..ids = entry.value)
.toList());
itemFilterRepo.putAll(filterMonths.entries
.map((entry) => ItemFilter()
..id = autoIncrement()
..name = entry.key
..type = 'month'
..ids = entry.value)
.toList());
itemFilterRepo.putAll(filterFundingPrograms.entries
.map((entry) => ItemFilter()
..id = autoIncrement()
..name = entry.key
..type = 'fundingProgram'
..ids = entry.value)
.toList());
return true;
}
int getMeasureCount() {
return isar.measures.where().count();
}
List<Measure?> getByIds(List<int> ids) {
return isar.measures.getAll(ids);
}
List<Measure> getAllOrdered() {
return isar.measures.where().sortByName().findAll();
}
}

View file

@ -68,4 +68,7 @@ extension DateHelpers on DateTime {
DateTime lastDayOfYear() {
return DateTime(year + 1, 1, 0);
}
DateTime get lastDayOfMonth =>
month < 12 ? DateTime(year, month + 1, 0) : DateTime(year + 1, 1, 0);
}

View file

@ -5,3 +5,4 @@ import 'package:flutter_i18n/flutter_i18n.dart';
part 'datetime_extensions.dart';
part 'i18n_extensions.dart';
part 'string_extensions.dart';

View file

@ -0,0 +1,23 @@
part of 'extensions.dart';
extension StringExtensions on String {
replaceUmlauts() {
return replaceAll("ü", "ue")
.replaceAll("ö", "oe")
.replaceAll("ä", "ae")
.replaceAll("ß", "ss")
.replaceAll("Ü(?=[a-zäöüß ])", "Ue")
.replaceAll("Ö(?=[a-zäöüß ])", "Oe")
.replaceAll("Ä(?=[a-zäöüß ])", "Ae")
.replaceAll("Ü", "UE")
.replaceAll("Ö", "OE")
.replaceAll("Ä", "AE");
}
Color hexToColor() {
final buffer = StringBuffer();
if (length == 6 || length == 7) buffer.write('ff');
buffer.write(replaceFirst('#', ''));
return Color(int.parse(buffer.toString(), radix: 16));
}
}

View file

@ -4,7 +4,6 @@ import 'package:ambito/src/entity/entities.dart';
import 'package:ambito/src/packages/ambito_api/restclient.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import '../../../main.dart';
import '../ambito_db/base_db.dart';
class BaseApi {
@ -27,9 +26,9 @@ class BaseApi {
var json = _jsonDecoded(response.body);
if (table == 'source') {
logger.d(json);
}
//if (table == 'measure') {
//logger.d(json);
//}
var results = json['results'];

View file

@ -1,4 +1,3 @@
import 'package:ambito/src/entity/approval_requirement/approval_requirement.dart';
import 'package:ambito/src/entity/entities.dart';
import 'package:flutter/foundation.dart';
import 'package:isar/isar.dart';
@ -9,7 +8,7 @@ import '../../../main.dart';
export 'repositories/_repositories.dart';
class AmbitoIsarDB {
init() async {
static init() async {
await Isar.initialize();
String dir = kIsWeb
? Isar.sqliteInMemory
@ -19,8 +18,11 @@ class AmbitoIsarDB {
schemas: [
ApprovalRequirementSchema,
BusinessSchema,
ExperienceReportSchema,
FundingProgramSchema,
ItemFilterSchema,
LocationRequirementsSchema,
MaterialSchema,
MeasureSchema,
MeasureCombinationSchema,
NumberFactsheetSchema,

View file

@ -0,0 +1,38 @@
import 'package:ambito/main.dart';
import 'package:ambito/src/entity/_general/filter/item_filter_repository.dart';
import 'package:flutter/cupertino.dart';
AmbitoFilterNotifier ambitoFilterNotifier = AmbitoFilterNotifier();
class AmbitoFilterNotifier extends ChangeNotifier {
AmbitoFilterNotifier();
AmbitoFilterNotifier.create(BuildContext context);
Map<String, String?> activeFilters = {};
Map<String, List<dynamic>?> activeIds = {};
List<int> mergedIds = [];
void setFilter(String type, String value) {
prefs.setString('filter_$type', value).then((_) {
activeFilters[type] = value;
activeIds[type] = ItemFilterRepository().getIdsByType(type);
notifyListeners();
});
}
void removeFilter(String type) {
prefs.remove('filter_$type').then((_) {
activeFilters[type] = null;
activeIds[type] = null;
notifyListeners();
});
}
List<int>? getMergedIds() {}
String? getFilter(String type) {
return activeFilters[type];
}
}

View file

@ -0,0 +1,10 @@
import 'package:shared_preferences/shared_preferences.dart';
import '../../../main.dart';
class AmbitoSharedPrefs {
static Future<SharedPreferences> start() async {
prefs = await SharedPreferences.getInstance();
return prefs;
}
}

View file

@ -0,0 +1,237 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
final actionGroupColors = {
'Bauelemente': const Color(0xffFFD269).withOpacity(.4),
'Begrünung': const Color(0xff40DD74).withOpacity(.4),
'Bewirtschaftung': const Color(0xffBF72ED).withOpacity(.4),
'Nisthilfe': const Color(0xffDAE3FD).withOpacity(.4),
'Pflanzung': const Color(0xff40D6E9).withOpacity(.4),
'Sondermaßnahmen': const Color(0xff689EF1).withOpacity(.4),
};
final actionAreaColors = {
'Landschaft': const Color(0xfff8e0aa).withOpacity(.6),
'Weinberg': const Color(0xffacc11e).withOpacity(.6),
'Betriebsfläche': const Color(0xffca414c).withOpacity(.6),
'Betriebsstätte': const Color(0xffCCCDCC).withOpacity(.6),
};
final actionAreaFGColors = {
'Landschaft': const Color(0xffec863a),
'Weinberg': const Color(0xff3d693f),
'Betriebsfläche': const Color(0xff883443),
'Betriebsstätte': const Color(0xff999999),
};
class AmbitoTheme {
static ThemeMode appThemeMode = ThemeMode.light;
ColorScheme get lightColorScheme => const ColorScheme(
brightness: Brightness.light,
primary: Color(0xFF60845E),
onPrimary: Color(0xFFFFFFFF),
primaryContainer: Color(0xFFDCE3C9),
onPrimaryContainer: Color(0xFF001E2D),
secondary: Color(0xFFF5F5F5),
onSecondary: Color(0xFFFFFFFF),
secondaryContainer: Color(0xFFD2E5F4),
onSecondaryContainer: Color(0xFF0A1D28),
tertiary: Color(0xFFD9D9D9),
onTertiary: Color(0xFFFFFFFF),
tertiaryContainer: Color(0xFFB8F483),
onTertiaryContainer: Color(0xFF0D2000),
error: Color(0xFFBA1A1A),
errorContainer: Color(0xFFFFDAD6),
onError: Color(0xFFFFFFFF),
onErrorContainer: Color(0xFF410002),
surface: Color(0xFFffffff),
onSurface: Color(0xFF656565),
surfaceContainerHighest: Color(0xFFDDE3EA),
onSurfaceVariant: Color(0xFF41484D),
outline: Color(0xFF71787E),
onInverseSurface: Color(0xFFF0F1F3),
inverseSurface: Color(0xFF2E3133),
inversePrimary: Color(0xFF82CFFF),
shadow: Color(0xFF000000),
surfaceTint: Color(0xFF00658D),
outlineVariant: Color(0xFFC1C7CE),
scrim: Color(0xFF000000),
);
ColorScheme get darkColorScheme => const ColorScheme(
brightness: Brightness.dark,
primary: Color(0xFF82CFFF),
onPrimary: Color(0xFF00344B),
primaryContainer: Color(0xFF004C6B),
onPrimaryContainer: Color(0xFFC6E7FF),
secondary: Color(0xFFB6C9D8),
onSecondary: Color(0xFF21323E),
secondaryContainer: Color(0xFF374955),
onSecondaryContainer: Color(0xFFD2E5F4),
tertiary: Color(0xFF9DD76A),
onTertiary: Color(0xFF1A3700),
tertiaryContainer: Color(0xFF285000),
onTertiaryContainer: Color(0xFFB8F483),
error: Color(0xFFFFB4AB),
errorContainer: Color(0xFF93000A),
onError: Color(0xFF690005),
onErrorContainer: Color(0xFFFFDAD6),
surface: Color(0xFF191C1E),
onSurface: Color(0xFFE2E2E5),
surfaceContainerHighest: Color(0xFF41484D),
onSurfaceVariant: Color(0xFFC1C7CE),
outline: Color(0xFF8B9198),
onInverseSurface: Color(0xFF191C1E),
inverseSurface: Color(0xFFE2E2E5),
inversePrimary: Color(0xFF00658D),
shadow: Color(0xFF000000),
surfaceTint: Color(0xFF82CFFF),
outlineVariant: Color(0xFF41484D),
scrim: Color(0xFF000000),
);
TextStyle get defaultFont => GoogleFonts.roboto();
TextStyle get displayLarge => textTheme.displayLarge!;
TextStyle get displayMedium => textTheme.displayMedium!;
TextStyle get displaySmall => textTheme.displaySmall!;
TextStyle get headlineLarge => textTheme.headlineLarge!;
TextStyle get headlineMedium => textTheme.headlineMedium!;
TextStyle get headlineSmall => textTheme.headlineSmall!;
TextStyle get titleLarge => textTheme.titleLarge!;
TextStyle get titleMedium => textTheme.titleMedium!;
TextStyle get titleSmall => textTheme.titleSmall!;
TextStyle get labelLarge => textTheme.labelLarge!;
TextStyle get labelMedium => textTheme.labelMedium!;
TextStyle get labelSmall => textTheme.labelSmall!;
TextStyle get bodyLarge => textTheme.bodyLarge!;
TextStyle get bodyMedium => textTheme.bodyMedium!;
TextStyle get bodySmall => textTheme.bodySmall!;
TextTheme get textTheme => TextTheme(
displayLarge: GoogleFonts.openSans(
fontSize: 57,
height: 1.12,
fontWeight: FontWeight.w400,
letterSpacing: -.25),
displayMedium: GoogleFonts.openSans(
fontSize: 45,
height: 1.15,
fontWeight: FontWeight.w400,
letterSpacing: 0,
),
displaySmall: GoogleFonts.openSans(
fontSize: 36,
height: 1.22,
fontWeight: FontWeight.w400,
letterSpacing: 0,
),
headlineLarge: GoogleFonts.openSans(
fontSize: 44,
height: 1.25,
fontWeight: FontWeight.w400,
letterSpacing: 0,
),
headlineMedium: GoogleFonts.openSans(
fontSize: 28,
height: 1.29,
fontWeight: FontWeight.w400,
letterSpacing: 0,
),
headlineSmall: GoogleFonts.openSans(
fontSize: 24,
height: 1.33,
fontWeight: FontWeight.w400,
letterSpacing: 0,
),
titleLarge: GoogleFonts.openSans(
fontSize: 22,
height: 1.27,
fontWeight: FontWeight.w400,
letterSpacing: 0,
),
titleMedium: GoogleFonts.openSans(
fontSize: 16,
height: 1.5,
fontWeight: FontWeight.w500,
letterSpacing: 0.15,
),
titleSmall: GoogleFonts.openSans(
fontSize: 14,
height: 1.42,
fontWeight: FontWeight.w500,
letterSpacing: 0.1,
),
labelLarge: GoogleFonts.openSans(
fontSize: 14,
height: 1.42,
fontWeight: FontWeight.w500,
letterSpacing: 0.1,
),
labelMedium: GoogleFonts.openSans(
fontSize: 12,
height: 1.33,
fontWeight: FontWeight.w500,
letterSpacing: 0.15,
),
labelSmall: GoogleFonts.openSans(
fontSize: 11,
height: 1.45,
fontWeight: FontWeight.w500,
letterSpacing: 0.1,
),
bodyLarge: GoogleFonts.openSans(
fontSize: 16,
height: 1.5,
fontWeight: FontWeight.w400,
letterSpacing: 0.5,
),
bodyMedium: GoogleFonts.openSans(
fontSize: 14,
height: 1.42,
fontWeight: FontWeight.w400,
letterSpacing: 0.25,
),
bodySmall: GoogleFonts.openSans(
fontSize: 12,
height: 1.33,
fontWeight: FontWeight.w400,
letterSpacing: 0.4,
),
);
EdgeInsets get padding => const EdgeInsets.all(16);
EdgeInsets get paddingSmall => const EdgeInsets.all(8);
Widget get horizontalSpacer => const SizedBox(
width: 16,
);
Widget get horizontalSpacerSmall => const SizedBox(
width: 8,
);
Widget get verticalSpacer => const SizedBox(
height: 16,
);
Widget get verticalSpacerSmall => const SizedBox(
height: 8,
);
Widget get verticalSpacerMax => const SizedBox(
height: 48,
);
ThemeData get darkThemeData => ThemeData(
useMaterial3: true, colorScheme: darkColorScheme, textTheme: textTheme);
ThemeData get lightThemeData => ThemeData(
useMaterial3: true, colorScheme: lightColorScheme, textTheme: textTheme);
ThemeData get currentThemeData =>
(AmbitoTheme.appThemeMode == ThemeMode.light)
? lightThemeData
: darkThemeData;
ThemeMode get mode => AmbitoTheme.appThemeMode;
ColorScheme get currentColorScheme =>
(AmbitoTheme.appThemeMode == ThemeMode.light)
? lightColorScheme
: darkColorScheme;
}

View file

@ -0,0 +1,188 @@
import 'package:ambito/src/entity/entities.dart';
import 'package:ambito/src/entity/measure/measure_repository.dart';
import 'package:ambito/src/pages/actions/cards/background_card.dart';
import 'package:ambito/src/pages/actions/cards/biodiverisity_card.dart';
import 'package:ambito/src/pages/actions/cards/creation_card.dart';
import 'package:ambito/src/pages/actions/cards/description_card.dart';
import 'package:ambito/src/pages/actions/cards/factsheet_card.dart';
import 'package:ambito/src/pages/actions/cards/funding_card.dart';
import 'package:ambito/src/pages/actions/cards/maintenance_card.dart';
import 'package:ambito/src/pages/actions/cards/presets_card.dart';
import 'package:ambito/src/pages/actions/cards/review_card.dart';
import 'package:flutter/material.dart';
import 'package:flutter_breadcrumb/flutter_breadcrumb.dart';
import 'package:get/get.dart';
import '../../../main.dart';
import '../../widgets/appbar/ambito_appbar.dart';
import '../ambito_page.dart';
import 'cards/advisor_card.dart';
import 'cards/material_card.dart';
class ActionDetailPage extends AmbitoPage {
const ActionDetailPage({super.key});
@override
final String path = 'massnahme';
@override
final String title = 'Maßname';
@override
State<StatefulWidget> createState() => ActionDetailPageState();
}
class ActionDetailPageState extends State<ActionDetailPage> {
late String id;
Widget content = const SizedBox();
Measure? massnahme;
@override
void initState() {
id = Get.parameters['id'] ?? '';
if (id != '') {
massnahme = MeasureRepository().get(int.parse(id)) as Measure;
setState(() {
if (massnahme != null) {
content = _buildInfoPage(massnahme!);
}
});
}
logger.d(id);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AmbitoAppbar(
links: const ['dashboard', 'massnahmen'],
),
body: SingleChildScrollView(
child: content,
),
);
}
Widget _buildInfoPage(Measure massnahme) {
return Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: BreadCrumb(
items: <BreadCrumbItem>[
BreadCrumbItem(
content: TextButton(
onPressed: () {
Get.offAndToNamed('/');
},
child: const Text('Start'),
),
),
BreadCrumbItem(
content: TextButton(
onPressed: () {
Get.offAndToNamed('/massnahmendatenbank');
},
child: const Text('Massnahmen'),
),
),
BreadCrumbItem(
content: Text(
massnahme.name ?? '',
),
),
],
divider: const Icon(Icons.chevron_right),
),
),
Container(
width: double.infinity,
height: 400,
color: baseTheme.currentColorScheme.primary,
child: massnahme.getImage(),
),
SizedBox(
width: 1140,
child: Expanded(
child: Column(
children: [
baseTheme.verticalSpacer,
Align(
alignment: Alignment.centerLeft,
child: Text(
massnahme.name!,
style: baseTheme.currentThemeData.textTheme.titleLarge,
),
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
children: [
DescriptionCard(
massnahme: massnahme,
),
baseTheme.verticalSpacer,
BackgroundCard(
massnahme: massnahme,
),
baseTheme.verticalSpacer,
PresetsCard(
massnahme: massnahme,
),
baseTheme.verticalSpacer,
BiodiverisityCard(
massnahme: massnahme,
),
baseTheme.verticalSpacer,
CreationCard(
massnahme: massnahme,
),
baseTheme.verticalSpacer,
MaintenanceCard(
massnahme: massnahme,
),
baseTheme.verticalSpacer,
FundingCard(
massnahme: massnahme,
),
baseTheme.verticalSpacer,
],
),
),
baseTheme.horizontalSpacer,
SizedBox(
width: 300,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
AdvisorCard(
massnahme: massnahme,
),
baseTheme.verticalSpacer,
MaterialCard(
massnahme: massnahme,
),
baseTheme.verticalSpacer,
FactsheetCard(
massnahme: massnahme,
),
baseTheme.verticalSpacer,
ReviewCard(
massnahme: massnahme,
),
],
),
),
],
),
],
),
),
),
],
);
}
}

View file

@ -1,51 +1,122 @@
import 'package:ambito/src/entity/_general/filter/item_filter_repository.dart';
import 'package:ambito/src/entity/measure/measure_repository.dart';
import 'package:ambito/src/widgets/form/fields/field_dropdown.dart';
import 'package:ambito/src/widgets/form/fields/field_monthsrangepicker.dart';
import 'package:ambito/src/packages/ambito_notifier/notifier/filter_notifier.dart';
import 'package:ambito/src/pages/ambito_page.dart';
import 'package:ambito/src/widgets/appbar/ambito_appbar.dart';
import 'package:ambito/src/widgets/form/fields/field_title.dart';
import 'package:ambito/src/widgets/form/form_widget.dart';
import 'package:ambito/src/widgets/form/form_widget_type.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:expandable_text/expandable_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_breadcrumb/flutter_breadcrumb.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:get/get.dart';
import 'package:highlight_text/highlight_text.dart';
import '../../../main.dart';
import '../../entity/entities.dart';
import '../../packages/ambito_theme/ambito_theme.dart';
class ActionsPage extends StatefulWidget {
class ActionsPage extends AmbitoPage {
const ActionsPage({super.key});
@override
final String path = 'massnahmendatenbank';
@override
final String title = 'Maßnamendatenbank';
@override
State<StatefulWidget> createState() => ActionsPageState();
}
class ActionsPageState extends State<ActionsPage> {
Map<int, bool> visible = {};
List<String> effort = [];
List<String> effect = [];
Set<String> type = {};
String? filterType;
Set<String> areaType = {};
String? filterAreaType;
List<String> region = [];
String? filterSupport;
Set<String> support = {};
String? filterMonths;
Set<String> months = {};
List<String> effort = [], effect = [], region = [];
Set<String> type = {}, areaType = {}, support = {}, months = {};
String? filterType,
filterAreaType,
filterSupport,
filterMonths,
searchText = '';
List<String>? selectedMonths;
List massnahmen = [];
Map<String, HighlightedWord> words = {};
String? preselect;
final TextEditingController _searchController = TextEditingController();
final FocusNode _searchFocusNode = FocusNode();
@override
void initState() {
ambitoFilterNotifier.addListener(_changeListener);
setState(() {
preselect = prefs.getString('selected_areaType');
if (preselect != null && preselect!.isNotEmpty) {
filterAreaType = preselect;
ambitoFilterNotifier.setFilter('areaType', preselect!);
}
});
_initializeData();
super.initState();
massnahmen = MeasureRepository().getAll();
effort = [];
effect = [];
type = {};
areaType = {};
region = [];
support = {};
}
buildCards() {}
void _changeListener() {
setState(() {
filterAreaType = ambitoFilterNotifier.getFilter('areaType');
filterType = ambitoFilterNotifier.getFilter('group');
});
logger.d(ambitoFilterNotifier.activeIds);
}
@override
void dispose() {
//ambitoFilterNotifier.dispose();
super.dispose();
}
void _initializeData() {
massnahmen = MeasureRepository().getAll();
_updateFilterSets();
}
void _updateFilterSets() {
final updatedTypes = <String>{}, updatedAreaTypes = <String>{};
final updatedSupports = <String>{}, updatedMonths = <String>{};
for (final massnahme in massnahmen) {
if (massnahme.actionGroup?.value != null) {
updatedTypes.add(massnahme.actionGroup!.value!);
}
massnahme.factsheetAreaType?.forEach((aType) {
if (aType.value != null) updatedAreaTypes.add(aType.value!);
});
massnahme.fundingPrograms?.forEach((aType) {
if (aType.value != null) updatedSupports.add(aType.value!);
});
massnahme.timeFrame?.forEach((tfType) {
if (tfType.value != null) updatedMonths.add(tfType.value!);
});
}
setState(() {
type = updatedTypes;
areaType = updatedAreaTypes;
support = updatedSupports;
months = updatedMonths;
});
}
void _onSearchTextChanged(String value) {
setState(() {
searchText = value;
words = {
for (var word in value.split(' '))
word: HighlightedWord(
textStyle: Theme.of(context).textTheme.headlineSmall?.copyWith(
color: Colors.white, backgroundColor: Colors.green.shade800))
};
});
}
@override
Widget build(BuildContext context) {
@ -80,6 +151,21 @@ class ActionsPageState extends State<ActionsPage> {
});
final actionCards = massnahmen.map((massnahme) {
List<String> possibleMonths = List.generate(
12,
(i) => FlutterI18n.translate(
context,
'general.lists.months.${i + 1}',
),
);
if (massnahme.timeFrame != null && massnahme.timeFrame.isNotEmpty) {
possibleMonths = [];
for (IdValueColor month in massnahme.timeFrame) {
possibleMonths.add(month.value!);
}
}
final typeMatches =
filterType == null || massnahme.actionGroup?.value == filterType;
final areaTypeMatches = filterAreaType == null ||
@ -91,61 +177,82 @@ class ActionsPageState extends State<ActionsPage> {
?.any((aType) => aType.value == filterSupport) ??
false);
final searchMatches = searchText == '' ||
((massnahme.name.toLowerCase().contains(searchText?.toLowerCase())) ??
false) ||
((massnahme.factsheetDefinition
.toLowerCase()
.contains(searchText?.toLowerCase())) ??
false);
final monthMatches = (selectedMonths == [] || selectedMonths == null) ||
(_hasCommonItems(selectedMonths!, possibleMonths));
setState(() {
visible[massnahme.id] =
typeMatches && areaTypeMatches && supportMatches;
visible[massnahme.id] = typeMatches &&
areaTypeMatches &&
supportMatches &&
searchMatches &&
monthMatches;
});
return getCard(context, massnahme);
}).toList();
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
getSpacer(),
Center(
child: SearchBar(
leading: const Icon(Icons.search),
onChanged: (value) {
for (Measure massnahme in massnahmen) {
if (!massnahme.name!.contains(value)) {
logger.d('$value not in ${massnahme.name}');
setState(() {
visible[massnahme.id] = false;
});
} else {
logger.d('$value in ${massnahme.name}');
setState(() {
visible[massnahme.id] = true;
});
}
}
},
),
),
getSpacer(),
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,
return Scaffold(
appBar: AmbitoAppbar(
links: const ['dashboard', 'massnahmen'],
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Align(
alignment: Alignment.centerLeft,
child: BreadCrumb(
items: <BreadCrumbItem>[
BreadCrumbItem(
content: TextButton(
onPressed: () {
Get.offAndToNamed('/');
},
child: const Text('Start'),
),
),
),
],
BreadCrumbItem(
content: const Text(
'Maßnahmen',
),
),
],
divider: const Icon(Icons.chevron_right),
),
),
),
getSpacer(),
],
getSpacer(),
_buildSearchBar(),
getSpacer(),
getSpacer(),
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(width: 300, child: _buildFilter(context)),
const SizedBox(width: 16),
Expanded(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: actionCards,
),
),
),
],
),
),
getSpacer(),
],
),
),
);
}
@ -156,170 +263,99 @@ class ActionsPageState extends State<ActionsPage> {
);
}
Widget getFilter(BuildContext context) {
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(),
Widget _buildSearchBar() {
return Center(
child: SearchBar(
controller: _searchController,
focusNode: _searchFocusNode,
elevation: WidgetStateProperty.all(0.0),
backgroundColor: WidgetStateProperty.all(Colors.white),
side: WidgetStateProperty.all(const BorderSide(color: Colors.black)),
leading: const Icon(Icons.search),
trailing: [
if (_searchFocusNode.hasFocus && _searchController.text.isNotEmpty)
IconButton(
onPressed: () {
_searchController.clear();
_searchFocusNode.unfocus();
_onSearchTextChanged('');
},
icon: const Icon(Icons.clear, color: Colors.grey, size: 20),
),
],
onChanged: _onSearchTextChanged,
),
);
}
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(),
),
Widget _buildFilter(BuildContext context) {
return FormWidget(
type: FormWidgetType.vertical,
fields: [
FieldTitle(text: 'Filter'),
ItemFilterRepository().getDropDown('areaType', 'Ort der Maßnahme'),
ItemFilterRepository().getDropDown('group', 'Art der Maßnahme'),
ItemFilterRepository().getDropDown('fundingProgram', 'Förderprogramm'),
ItemFilterRepository().getDropDown('month', 'Beginn der Maßnahme'),
],
);
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'));
}
fields.add(
FieldMonthsRangepicker(
name: 'months',
label: 'Beginn der Maßnahme',
filterValue: filterMonths,
onClear: () {},
onSelected: (String? value) {
logger.d(value);
},
entries: monthsSorted,
),
);
return FormWidget(type: FormWidgetType.vertical, fields: fields);
}
Widget getCard(BuildContext context, Measure massnahme) {
final Map<String, Color> actionGroupColors = {
'Baulelemente': const Color(0xffFFD269).withOpacity(.4),
'Begrünung': const Color(0xff40DD74).withOpacity(.4),
'Bewirtschaftung': const Color(0xffBF72ED).withOpacity(.4),
'Nisthilfe': const Color(0xffDAE3FD).withOpacity(.4),
'Pflanzung': const Color(0xff40D6E9).withOpacity(.4),
'Sondermaßnahmen': const Color(0xff689EF1).withOpacity(.4),
};
Color background =
final background =
actionGroupColors[massnahme.actionGroup?.value] ?? Colors.white;
CachedNetworkImage? image = massnahme.getThumbnail();
final image = massnahme.getThumbnail();
return Visibility(
visible: visible[massnahme.id] ?? false,
child: SizedBox(
width: 800,
child: Card(
elevation: 2,
color: Colors.white,
child: ClipPath(
clipper: ShapeBorderClipper(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: InkWell(
onHover: (hovered) {},
onTap: () async {
Get.toNamed('/massnahme/${massnahme.id}');
},
child: SizedBox(
width: 800,
child: Card(
elevation: 2,
color: Colors.white,
child: Container(
decoration: BoxDecoration(
border: Border(
left: BorderSide(
color: background,
width: 15,
),
),
border: Border(left: BorderSide(color: background, width: 15)),
),
child: Padding(
padding: const EdgeInsets.all(32),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(image != null)
? image
: const SizedBox(
width: 300,
height: 140,
),
const SizedBox(
width: 16,
padding: const EdgeInsets.all(32),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
image ?? const SizedBox(width: 300, height: 140),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextHighlight(
text: massnahme.name!,
words: words,
textStyle: Theme.of(context).textTheme.headlineSmall,
),
const SizedBox(height: 8),
TextHighlight(
text: massnahme.factsheetDefinition ?? '',
words: words,
textStyle: Theme.of(context).textTheme.bodyMedium,
),
],
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
massnahme.name!,
style: Theme.of(context).textTheme.headlineSmall,
),
const SizedBox(
height: 8,
),
ExpandableText(
style: Theme.of(context).textTheme.bodyLarge,
massnahme.factsheetDefinition ?? '',
maxLines: 4,
expandText: 'mehr',
collapseText: 'weniger',
)
],
),
)
],
),
),
],
),
),
),
/*child: ,*/
),
),
);
}
bool _hasCommonItems(List listOne, List listTwo) {
return listOne.toSet().intersection(listTwo.toSet()).isNotEmpty;
}
}

View file

@ -0,0 +1,154 @@
import 'package:ambito/src/entity/_general/filter/item_filter_repository.dart';
import 'package:ambito/src/entity/entities.dart';
import 'package:ambito/src/entity/measure/measure_repository.dart';
import 'package:ambito/src/pages/ambito_page.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../main.dart';
import '../../packages/ambito_theme/ambito_theme.dart';
import '../../widgets/appbar/ambito_appbar.dart';
class ActionsPrePage extends AmbitoPage {
const ActionsPrePage({super.key});
@override
final String path = 'massnahmen';
@override
final String title = 'Maßnamen';
@override
State<StatefulWidget> createState() => ActionsPrePageState();
}
class ActionsPrePageState extends State<ActionsPrePage> {
List<Widget> cards = [];
Map<String, int> counter = {};
Map<String, int> ids = {};
int counterComplete = 0;
@override
void initState() {
List<ItemFilter>? filters = ItemFilterRepository().getByType('areaType');
counterComplete = MeasureRepository().getMeasureCount();
for (ItemFilter filter in filters!) {
setState(() {
cards.add(
InkWell(
onTap: () {
prefs.setString('selected_areaType', filter.name!).then((value) {
Get.toNamed('/massnahmendatenbank');
setState(() {});
});
},
onHover: (value) {},
child: SizedBox(
width: 300,
height: 400,
child: Card(
color: actionAreaColors[filter.name!],
child: Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.asset(
filter.image!,
),
),
baseTheme.verticalSpacer,
Padding(
padding: const EdgeInsets.only(left: 16, right: 16),
child: Text(
filter.name!,
style: baseTheme.currentThemeData.textTheme.titleLarge
?.copyWith(
color: actionAreaFGColors[filter.name!],
fontWeight: FontWeight.bold,
),
),
),
baseTheme.verticalSpacer,
Padding(
padding: const EdgeInsets.only(left: 16, right: 16),
child: Text(
filter.description!,
style: baseTheme.currentThemeData.textTheme.bodyMedium
?.copyWith(
color: baseTheme.currentColorScheme.onSurface,
),
),
),
const Spacer(),
Padding(
padding: const EdgeInsets.only(
left: 16, right: 16, bottom: 16),
child: Text(
'Anzahl: ${filter.ids!.length}',
style: baseTheme.currentThemeData.textTheme.titleMedium
?.copyWith(
color: actionAreaFGColors[filter.name!],
fontWeight: FontWeight.bold,
),
),
),
],
),
),
),
),
);
});
}
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AmbitoAppbar(
links: const ['dashboard', 'massnahmen'],
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
baseTheme.verticalSpacerMax,
Text(
'Maßnahmenkategorien',
textAlign: TextAlign.start,
style:
baseTheme.currentThemeData.textTheme.headlineLarge?.copyWith(
color: baseTheme.currentColorScheme.onSurface,
),
),
baseTheme.verticalSpacerMax,
Wrap(
alignment: WrapAlignment.center,
spacing: 16,
children: cards,
),
baseTheme.verticalSpacerMax,
TextButton(
onPressed: () async {
await prefs.setString('selected_areaType', '');
await Get.toNamed('/massnahmendatenbank');
},
child: Text(
'Zeig mir alle $counterComplete Maßnahmen...',
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.blueAccent,
),
))
],
),
),
);
}
}

View file

@ -0,0 +1,42 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../main.dart';
import '../../../entity/entities.dart';
class AdvisorCard extends StatelessWidget {
const AdvisorCard({super.key, required this.massnahme});
final Measure massnahme;
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 0,
color: baseTheme.currentColorScheme.tertiary,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.translate('page.actionDetailPage.advisor.title'),
style: baseTheme.currentThemeData.textTheme.titleMedium,
),
baseTheme.verticalSpacer,
Text(
'Max Mustermann',
style: baseTheme.currentThemeData.textTheme.bodyMedium,
),
],
),
),
),
);
}
}

View file

@ -0,0 +1,57 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../main.dart';
import '../../../entity/entities.dart';
class BackgroundCard extends StatelessWidget {
const BackgroundCard({super.key, required this.massnahme});
final Measure massnahme;
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 0,
color: baseTheme.currentColorScheme.secondary,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.translate('page.actionDetailPage.background.title'),
style: baseTheme.currentThemeData.textTheme.titleMedium,
),
baseTheme.verticalSpacer,
Text(
context.translate('page.actionDetailPage.background.areaType'),
style: baseTheme.currentThemeData.textTheme.titleSmall,
),
baseTheme.verticalSpacerSmall,
Text(
massnahme.factsheetLocation.toString(),
style: baseTheme.currentThemeData.textTheme.bodyMedium,
),
baseTheme.verticalSpacer,
Text(
context.translate('page.actionDetailPage.background.target'),
style: baseTheme.currentThemeData.textTheme.titleSmall,
),
baseTheme.verticalSpacerSmall,
Text(
massnahme.factsheetTarget.toString(),
style: baseTheme.currentThemeData.textTheme.bodyMedium,
),
],
),
),
),
);
}
}

View file

@ -0,0 +1,42 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../main.dart';
import '../../../entity/entities.dart';
class BiodiverisityCard extends StatelessWidget {
const BiodiverisityCard({super.key, required this.massnahme});
final Measure massnahme;
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 0,
color: baseTheme.currentColorScheme.secondary,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.translate('page.actionDetailPage.biodiversity.title'),
style: baseTheme.currentThemeData.textTheme.titleMedium,
),
baseTheme.verticalSpacer,
Text(
massnahme.oekologischeRelevanzBackground.toString(),
style: baseTheme.currentThemeData.textTheme.bodyMedium,
),
],
),
),
),
);
}
}

View file

@ -0,0 +1,51 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../main.dart';
import '../../../entity/entities.dart';
class CreationCard extends StatelessWidget {
const CreationCard({super.key, required this.massnahme});
final Measure massnahme;
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 0,
color: baseTheme.currentColorScheme.secondary,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.translate('page.actionDetailPage.creation.title'),
style: baseTheme.currentThemeData.textTheme.titleMedium,
),
baseTheme.verticalSpacer,
Text(
context.translate('page.actionDetailPage.creation.timeFrame'),
style: baseTheme.currentThemeData.textTheme.titleSmall,
),
baseTheme.verticalSpacer,
Text(
massnahme.timeFrame
?.map((item) => item.value)
.toList()
.join(', ') ??
'',
style: baseTheme.currentThemeData.textTheme.bodyMedium,
),
],
),
),
),
);
}
}

View file

@ -0,0 +1,42 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../main.dart';
import '../../../entity/entities.dart';
class DescriptionCard extends StatelessWidget {
const DescriptionCard({super.key, required this.massnahme});
final Measure massnahme;
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 0,
color: baseTheme.currentColorScheme.secondary,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.translate('page.actionDetailPage.description.title'),
style: baseTheme.currentThemeData.textTheme.titleMedium,
),
baseTheme.verticalSpacer,
Text(
massnahme.factsheetDefinition ?? '',
style: baseTheme.currentThemeData.textTheme.bodyMedium,
),
],
),
),
),
);
}
}

View file

@ -0,0 +1,63 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../main.dart';
import '../../../entity/entities.dart';
class FactsheetCard extends StatelessWidget {
const FactsheetCard({super.key, required this.massnahme});
final Measure massnahme;
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 0,
color: baseTheme.currentColorScheme.tertiary,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.translate('page.actionDetailPage.factsheet.title'),
style: baseTheme.currentThemeData.textTheme.titleMedium,
),
baseTheme.verticalSpacer,
],
),
),
),
);
}
_getSortedMaterials(BuildContext context) {
List<String> items = [];
if (massnahme.materialAction != null) {
for (IdValueColor ivc in massnahme.materialAction!) {
items.add(ivc.value!);
}
}
items.sort((a, b) => a.toString().compareTo(b.toString()));
List<ListTile> tiles = [];
for (String item in items) {
tiles.add(
ListTile(
leading: Icon(Icons.fiber_manual_record),
title: Text(
item,
style: Theme.of(context).textTheme.bodyMedium,
),
),
);
}
return Column(
children: tiles,
);
}
}

View file

@ -0,0 +1,38 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../main.dart';
import '../../../entity/entities.dart';
class FundingCard extends StatelessWidget {
const FundingCard({super.key, required this.massnahme});
final Measure massnahme;
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 0,
color: baseTheme.currentColorScheme.secondary,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.translate('page.actionDetailPage.funding.title'),
style: baseTheme.currentThemeData.textTheme.titleMedium,
),
baseTheme.verticalSpacer,
],
),
),
),
);
}
}

View file

@ -0,0 +1,38 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../main.dart';
import '../../../entity/entities.dart';
class MaintenanceCard extends StatelessWidget {
const MaintenanceCard({super.key, required this.massnahme});
final Measure massnahme;
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 0,
color: baseTheme.currentColorScheme.secondary,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.translate('page.actionDetailPage.maintenance.title'),
style: baseTheme.currentThemeData.textTheme.titleMedium,
),
baseTheme.verticalSpacer,
],
),
),
),
);
}
}

View file

@ -0,0 +1,71 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../main.dart';
import '../../../entity/entities.dart';
class MaterialCard extends StatelessWidget {
const MaterialCard({super.key, required this.massnahme});
final Measure massnahme;
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 0,
color: baseTheme.currentColorScheme.tertiary,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.translate('page.actionDetailPage.material.title'),
style: baseTheme.currentThemeData.textTheme.titleMedium,
),
baseTheme.verticalSpacer,
_getSortedMaterials(context),
baseTheme.verticalSpacer,
if (massnahme.costsMaterial != null)
Text(context.translate(
'page.actionDetailPage.material.suggested_price') +
massnahme.costsMaterial +
''),
baseTheme.verticalSpacer,
],
),
),
),
);
}
_getSortedMaterials(BuildContext context) {
List<String> items = [];
if (massnahme.materialAction != null) {
for (IdValueColor ivc in massnahme.materialAction!) {
items.add(ivc.value!);
}
}
items.sort((a, b) => a.toString().compareTo(b.toString()));
List<ListTile> tiles = [];
for (String item in items) {
tiles.add(
ListTile(
leading: Icon(Icons.fiber_manual_record),
title: Text(
item,
style: Theme.of(context).textTheme.bodyMedium,
),
),
);
}
return Column(
children: tiles,
);
}
}

View file

@ -0,0 +1,52 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../main.dart';
import '../../../entity/entities.dart';
class PresetsCard extends StatelessWidget {
const PresetsCard({super.key, required this.massnahme});
final Measure massnahme;
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 0,
color: baseTheme.currentColorScheme.secondary,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.translate('page.actionDetailPage.presets.title'),
style: baseTheme.currentThemeData.textTheme.titleMedium,
),
baseTheme.verticalSpacer,
Text(
massnahme.remarkablePresets.toString(),
style: baseTheme.currentThemeData.textTheme.bodyMedium,
),
baseTheme.verticalSpacer,
Text(
context.translate('page.actionDetailPage.presets.tips'),
style: baseTheme.currentThemeData.textTheme.titleSmall,
),
baseTheme.verticalSpacerSmall,
Text(
massnahme.tipsPresets.toString(),
style: baseTheme.currentThemeData.textTheme.bodyMedium,
),
],
),
),
),
);
}
}

View file

@ -0,0 +1,66 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import 'package:flutter_rating_stars/flutter_rating_stars.dart';
import '../../../../main.dart';
import '../../../entity/entities.dart';
class ReviewCard extends StatelessWidget {
const ReviewCard({super.key, required this.massnahme});
final Measure massnahme;
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 0,
color: baseTheme.currentColorScheme.tertiary,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.translate('page.actionDetailPage.review.title'),
style: baseTheme.currentThemeData.textTheme.titleMedium,
),
baseTheme.verticalSpacer,
RatingStars(
value: 4.5,
onValueChanged: (v) {},
starBuilder: (index, color) => Icon(
Icons.star,
color: color,
),
starCount: 5,
starSize: 32,
valueLabelColor: const Color(0xff9b9b9b),
valueLabelTextStyle: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w400,
fontStyle: FontStyle.normal,
fontSize: 12.0),
valueLabelRadius: 10,
maxValue: 5,
starSpacing: 2,
maxValueVisibility: true,
valueLabelVisibility: false,
animationDuration: const Duration(milliseconds: 1000),
valueLabelPadding:
const EdgeInsets.symmetric(vertical: 1, horizontal: 8),
valueLabelMargin: const EdgeInsets.only(right: 8),
starOffColor: const Color(0xffe7e8ea),
starColor: Colors.grey.shade600,
),
],
),
),
),
);
}
}

View file

@ -0,0 +1,8 @@
import 'package:flutter/cupertino.dart';
abstract class AmbitoPage extends StatefulWidget {
abstract final String path;
abstract final String title;
const AmbitoPage({super.key});
}

View file

@ -0,0 +1,175 @@
import 'package:ambito/src/entity/_general/filter/item_filter.dart';
import 'package:ambito/src/entity/_general/filter/item_filter_repository.dart';
import 'package:ambito/src/entity/measure/measure.dart';
import 'package:ambito/src/entity/measure/measure_repository.dart';
import 'package:ambito/src/extensions/extensions.dart';
import 'package:ambito/src/packages/ambito_theme/ambito_theme.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_calendar/calendar.dart';
import '../../widgets/appbar/ambito_appbar.dart';
class CalendarPage extends StatefulWidget {
const CalendarPage({super.key});
@override
State<StatefulWidget> createState() => CalendarPageState();
}
class CalendarPageState extends State<CalendarPage> {
List<Appointment> appointments = <Appointment>[];
List<String> months = [
'Januar',
'Februar',
'März',
'April',
'Mai',
'Juni',
'Juli',
'August',
'September',
'Oktober',
'November',
'Dezember',
];
List<ItemFilter>? monthFilter = [];
@override
void initState() {
initDataSource();
super.initState();
}
initDataSource() {
monthFilter = ItemFilterRepository().getByType('month');
for (String month in months) {
DateTime now = DateTime.now();
int monthInt = months.indexOf(month) + 1;
DateTime startDate = DateTime(now.year, monthInt, 1, 0, 0, 0);
DateTime endDate = DateTime(
now.year, monthInt, startDate.lastDayOfMonth.day, 23, 59, 59);
ItemFilter? itemFilter =
monthFilter?.firstWhereOrNull((item) => item.name == month);
if (itemFilter != null) {
List<Measure?> currentMeasures =
MeasureRepository().getByIds(itemFilter.ids!);
for (var measure in currentMeasures) {
appointments.add(
Appointment(
startTime: startDate,
endTime: endDate,
isAllDay: true,
subject: measure!.name ?? '',
color: actionGroupColors[measure.actionGroup!.value!]!,
),
);
}
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AmbitoAppbar(
links: const ['dashboard', 'massnahmen'],
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(32),
child: SfCalendar(
firstDayOfWeek: 1,
showNavigationArrow: true,
view: CalendarView.month,
dataSource: _AppointmentDataSource(appointments),
monthViewSettings: const MonthViewSettings(
appointmentDisplayMode: MonthAppointmentDisplayMode.appointment,
appointmentDisplayCount: 64,
),
),
),
),
);
}
_AppointmentDataSource _getCalendarDataSource() {
List<Appointment> appointments = <Appointment>[];
appointments.add(Appointment(
startTime: DateTime.now(),
endTime: DateTime.now().add(Duration(minutes: 10)),
subject: 'Meeting',
isAllDay: true,
color: Colors.blue,
startTimeZone: '',
endTimeZone: '',
));
return _AppointmentDataSource(appointments);
}
}
class _AppointmentDataSource extends CalendarDataSource {
_AppointmentDataSource(List<Appointment> source) {
appointments = source;
}
}
/*class ActionDataSource extends CalendarDataSource {
ActionDataSource(List<Action> source) {
appointments = source;
}
@override
DateTime getStartTime(int index) {
return appointments![index].from;
}
@override
DateTime getEndTime(int index) {
return appointments![index].to;
}
@override
bool isAllDay(int index) {
return appointments![index].isAllDay;
}
@override
String getSubject(int index) {
return appointments![index].eventName;
}
@override
String getStartTimeZone(int index) {
return appointments![index].startTimeZone;
}
@override
String getEndTimeZone(int index) {
return appointments![index].endTimeZone;
}
@override
Color getColor(int index) {
return appointments![index].background;
}
}
class Action {
Action(
{this.eventName = '',
required this.from,
required this.to,
required this.background,
this.isAllDay = false});
String eventName;
DateTime from;
DateTime to;
Color background;
bool isAllDay;
}*/

View file

@ -0,0 +1,171 @@
import 'package:ambito/main.dart';
import 'package:ambito/src/entity/_general/filter/item_filter.dart';
import 'package:ambito/src/entity/measure/measure_repository.dart';
import 'package:flutter/material.dart';
import '../../widgets/appbar/ambito_appbar.dart';
class CalendarPageYear extends StatefulWidget {
const CalendarPageYear({super.key});
@override
State<StatefulWidget> createState() => CalendarPageYearState();
}
class CalendarPageYearState extends State<CalendarPageYear> {
List<TableRow> rows = <TableRow>[];
List<String> months = [
'Januar',
'Februar',
'März',
'April',
'Mai',
'Juni',
'Juli',
'August',
'September',
'Oktober',
'November',
'Dezember',
];
List<ItemFilter>? monthFilter = [];
@override
void initState() {
initDataSource();
super.initState();
}
initDataSource() {
List<TableCell> cells = [
TableCell(
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(
'Maßnahme',
style: baseTheme.currentThemeData.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
),
),
];
for (String month in months) {
cells.add(
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: Text(
textAlign: TextAlign.center,
month,
style: baseTheme.currentThemeData.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
),
);
}
rows.add(TableRow(children: cells));
var massnahmen = MeasureRepository().getAllOrdered();
for (var massnahme in massnahmen) {
if (massnahme.name != null && massnahme.name!.isNotEmpty) {
cells = [
TableCell(
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(
massnahme.name!,
),
),
),
];
for (String month in months) {
if (massnahme.timeFrame!
.where((ele) => ele.value == month)
.isNotEmpty) {
cells.add(
TableCell(
child: Container(
width: double.infinity,
height: 44,
color: baseTheme.currentColorScheme.primary,
),
),
);
} else {
cells.add(
TableCell(
child: Container(
width: double.infinity,
height: 44,
color: Colors.transparent,
),
),
);
}
}
rows.add(
TableRow(
children: cells,
),
);
}
}
}
@override
Widget build(BuildContext context) {
double fixedWidth = 120;
return Scaffold(
appBar: AmbitoAppbar(
links: const ['dashboard', 'massnahmen'],
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(32),
child: Table(
border: TableBorder(
top: const BorderSide(
width: 2,
color: Colors.black,
),
left: const BorderSide(
width: 2,
color: Colors.black,
),
right: const BorderSide(
width: 2,
color: Colors.black,
),
bottom: const BorderSide(
width: 2,
color: Colors.black,
),
horizontalInside: BorderSide(
width: 1,
color: Colors.black.withOpacity(.6),
),
),
columnWidths: <int, TableColumnWidth>{
0: FlexColumnWidth(300),
1: FlexColumnWidth(fixedWidth),
2: FlexColumnWidth(fixedWidth),
3: FlexColumnWidth(fixedWidth),
4: FlexColumnWidth(fixedWidth),
5: FlexColumnWidth(fixedWidth),
6: FlexColumnWidth(fixedWidth),
7: FlexColumnWidth(fixedWidth),
8: FlexColumnWidth(fixedWidth),
9: FlexColumnWidth(fixedWidth),
10: FlexColumnWidth(fixedWidth),
11: FlexColumnWidth(fixedWidth),
12: FlexColumnWidth(fixedWidth),
13: FlexColumnWidth(fixedWidth),
},
children: rows,
),
),
),
);
}
}

View file

@ -1,39 +0,0 @@
import 'package:ambito/src/pages/start/start_page.dart';
import 'package:flutter/material.dart';
class LoadingPage extends StatelessWidget {
const LoadingPage({super.key});
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: Future.delayed(
const Duration(seconds: 1),
() {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) {
return const StartPage();
},
),
(route) => false,
);
},
),
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return Center(
child: Hero(
tag: 'logo',
child: Image.asset('assets/images/logo_trans.png')),
);
}
return Center(
child: Hero(
tag: 'logo', child: Image.asset('assets/images/logo_trans.png')),
);
},
);
}
}

View file

@ -1,24 +1,34 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import 'dart:html' as html;
import '../actions/actions_page.dart';
import 'package:ambito/src/extensions/extensions.dart';
import 'package:ambito/src/pages/ambito_page.dart';
import 'package:ambito/src/widgets/appbar/ambito_appbar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_breadcrumb/flutter_breadcrumb.dart';
import 'package:get/get.dart';
import '../../../main.dart';
class StartPage extends StatefulWidget {
const StartPage({super.key});
const StartPage({super.key, required this.activeLink});
final AmbitoPage activeLink;
@override
State<StartPage> createState() => StartPageState();
}
class StartPageState extends State<StartPage> {
String activeLink = '';
Widget content = const SizedBox();
String title = '';
@override
void initState() {
setState(() {
activeLink = 'database';
content = const ActionsPage();
content = widget.activeLink;
logger.d(widget.activeLink.title);
html.window.history.pushState(
null, widget.activeLink.title, '#/${widget.activeLink.path}');
});
super.initState();
}
@ -26,48 +36,41 @@ class StartPageState extends State<StartPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
leading: Padding(
padding: const EdgeInsets.all(8),
child: Hero(
tag: 'logo',
child: Image.asset(
'assets/images/logo_trans.png',
),
),
),
leadingWidth: 80,
centerTitle: true,
title: _linkButton('database'),
toolbarHeight: 80,
backgroundColor: Colors.grey.withOpacity(.4),
actions: [
IconButton(onPressed: () {}, icon: const Icon(Icons.person)),
const SizedBox(
width: 30,
)
],
),
body: const Column(
appBar: AmbitoAppbar(),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: 50),
if (widget.activeLink.path != 'massnahmen')
Align(
alignment: Alignment.centerLeft,
child: BreadCrumb(
items: <BreadCrumbItem>[
BreadCrumbItem(
content: TextButton(
onPressed: () {
Get.offAndToNamed('/');
},
child: const Text('Start'),
),
),
BreadCrumbItem(
content: Text(
widget.activeLink.title,
),
),
],
divider: const Icon(Icons.chevron_right),
),
),
const SizedBox(height: 50),
Expanded(
child: ActionsPage(),
child: content,
),
],
));
}
Widget getContent() {
if (activeLink == 'database') {
return const ActionsPage();
}
return Text(activeLink);
}
Widget _linkButton(String link) {
Widget _linkButton(String link, Widget targetPage) {
double fontSize = 20;
return TextButton(
style: ButtonStyle(
@ -77,16 +80,14 @@ class StartPageState extends State<StartPage> {
}),
),
onPressed: () {
setState(() {
activeLink = link;
});
Get.offAndToNamed('/');
},
child: Text(
context.translate('page.start.links.$link.title'),
style: TextStyle(
fontSize: fontSize,
fontWeight: FontWeight.bold,
color: (activeLink == link) ? Colors.grey.shade800 : Colors.black,
//color: (activeLink == link) ? Colors.grey.shade800 : Colors.black,
),
),
);

View file

@ -0,0 +1,98 @@
import 'package:ambito/main.dart';
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class AmbitoAppbar extends AppBar {
AmbitoAppbar({super.key, List<String>? links})
: super(
automaticallyImplyLeading: false,
leading: Padding(
padding: const EdgeInsets.all(8),
child: Hero(
tag: 'logo',
child: GestureDetector(
onTap: () {
Get.toNamed('/');
},
child: Image.asset(
'assets/images/logo_trans.png',
),
),
),
),
leadingWidth: 80,
centerTitle: true,
title: Builder(
builder: (context) => _links(context, links),
),
toolbarHeight: 80,
backgroundColor: baseTheme.currentColorScheme.primaryContainer,
actions: [
IconButton(
onPressed: () {
Get.toNamed('/kalender/jahr');
},
icon: Icon(
Icons.calendar_view_month,
color: baseTheme.currentColorScheme.primary,
),
),
IconButton(
onPressed: () {
Get.toNamed('/kalender');
},
icon: Icon(
Icons.calendar_month,
color: baseTheme.currentColorScheme.primary,
),
),
IconButton(
onPressed: () {},
icon: Icon(
Icons.person,
color: baseTheme.currentColorScheme.primary,
),
),
const SizedBox(
width: 30,
)
],
);
static Widget _links(BuildContext context, List<String>? links) {
List<Widget> linkButtons = [];
if (links != null && links.isNotEmpty) {
for (String link in links) {
linkButtons.add(_linkButton(context, link));
}
}
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: linkButtons,
);
}
static Widget _linkButton(BuildContext context, String link) {
double fontSize = 20;
return TextButton(
style: ButtonStyle(
overlayColor:
WidgetStateProperty.resolveWith<Color>((Set<WidgetState> states) {
return Colors.transparent;
}),
),
onPressed: () {
Get.offAndToNamed('/$link');
},
child: Text(
context.translate('page.start.links.$link.title'),
style: TextStyle(
fontSize: fontSize,
fontWeight: FontWeight.bold,
//color: (activeLink == link) ? Colors.grey.shade800 : Colors.black,
),
),
);
}
}

View file

@ -27,29 +27,5 @@ class FieldDaterangepicker extends FormWidgetField {
name: name,
firstDate: now.firstDayOfYear(),
lastDate: now.lastDayOfYear());
return FormBuilderDropdown<String>(
name: name,
initialValue: filterValue,
decoration: InputDecoration(
labelText: label,
prefix: IconButton(
icon: const Icon(Icons.cancel_outlined),
onPressed: onClear,
),
hintText: label,
),
onReset: onClear,
onChanged: onSelected,
items: entries
.map(
(entry) => DropdownMenuItem(
value: entry,
alignment: Alignment.centerLeft,
child: Text(entry),
),
)
.toList(),
);
}
}

View file

@ -3,13 +3,14 @@ import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
class FieldDropdown extends FormWidgetField {
FieldDropdown(
{required this.name,
required this.label,
required this.filterValue,
required this.onClear,
required this.onSelected,
required this.entries});
FieldDropdown({
required this.name,
required this.label,
required this.filterValue,
required this.onClear,
required this.onSelected,
required this.entries,
});
final String name;
final String label;
@ -26,7 +27,9 @@ class FieldDropdown extends FormWidgetField {
decoration: InputDecoration(
labelText: label,
prefix: IconButton(
icon: const Icon(Icons.cancel_outlined),
icon: const Icon(
Icons.cancel_outlined,
),
onPressed: onClear,
),
hintText: label,
@ -38,7 +41,9 @@ class FieldDropdown extends FormWidgetField {
(entry) => DropdownMenuItem(
value: entry,
alignment: Alignment.centerLeft,
child: Text(entry),
child: Text(
entry,
),
),
)
.toList(),

View file

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:syncfusion_flutter_datepicker/datepicker.dart';
import '../form_widget.dart';
@ -16,7 +17,7 @@ class FieldMonthsRangepicker extends FormWidgetField {
final String label;
final String? filterValue;
final VoidCallback onClear;
final void Function(String?) onSelected;
final void Function(DateRangePickerSelectionChangedArgs? args) onSelected;
final List<String> entries;
@override
@ -25,9 +26,29 @@ class FieldMonthsRangepicker extends FormWidgetField {
minDate: DateTime(2024, 1),
maxDate: DateTime(2024, 12, 31),
allowViewNavigation: false,
showNavigationArrow: false,
headerHeight: 0,
view: DateRangePickerView.year,
selectionMode: DateRangePickerSelectionMode.range,
onSelectionChanged: (DateRangePickerSelectionChangedArgs args) {},
onSelectionChanged: onSelected,
);
}
static List<String> getMonths(DateTime createdDate, int length) {
DateFormat dateFormat = DateFormat.MMMM('de_DE');
List<String> years = [];
int currentYear = createdDate.year;
int currentMonth = createdDate.month;
for (int i = 0; i < length; i++) {
createdDate = DateTime(currentYear, currentMonth + i);
years.add(dateFormat.format(createdDate));
if (currentMonth + i == 1) {
currentYear += 1;
}
}
return years;
}
}

View file

@ -0,0 +1,47 @@
import 'package:flutter/material.dart';
class FieldSearchBar extends StatelessWidget {
final TextEditingController _searchController = TextEditingController();
final FocusNode _searchFocusNode = FocusNode();
final Function() deleteAction;
final Function(String value) onChange;
final String searchString;
FieldSearchBar(
{super.key,
required this.deleteAction,
required this.onChange,
required this.searchString});
@override
Widget build(BuildContext context) {
return SearchBar(
controller: _searchController,
focusNode: _searchFocusNode,
elevation: WidgetStateProperty.all<double>(0.0),
backgroundColor: WidgetStateProperty.all<Color>(Colors.white),
side: WidgetStateProperty.all<BorderSide>(
const BorderSide(
color: Colors.black,
),
),
leading: const Icon(Icons.search),
trailing: [
if (_searchFocusNode.hasFocus && _searchController.text.isNotEmpty)
IconButton(
onPressed: () {
_searchController.clear();
_searchFocusNode.unfocus();
deleteAction;
},
icon: const Icon(
Icons.clear,
color: Colors.grey,
size: 20,
),
),
],
onChanged: onChange,
);
}
}

View file

@ -0,0 +1,23 @@
import 'package:ambito/main.dart';
import 'package:ambito/src/widgets/form/form_widget.dart';
import 'package:flutter/material.dart';
class FieldTitle extends FormWidgetField {
FieldTitle({
required this.text,
});
final String text;
@override
Widget get() {
return Align(
alignment: Alignment.centerLeft,
child: Text(
text,
textAlign: TextAlign.start,
style: baseTheme.currentThemeData.textTheme.titleLarge,
),
);
}
}

View file

@ -23,11 +23,20 @@ class FormWidget extends StatelessWidget {
key: _formKey,
child: (type == FormWidgetType.vertical)
? Column(
children: fields.map((element) => element.get()).toList(),
children: fields
.map((element) => _getElementVertical(element))
.toList(),
)
: Row(
children: fields.map((element) => element.get()).toList(),
),
));
}
Widget _getElementVertical(FormWidgetField element) {
return Padding(
padding: const EdgeInsets.only(bottom: 16),
child: element.get(),
);
}
}

View file

@ -8,11 +8,13 @@ import Foundation
import geolocator_apple
import isar_flutter_libs
import path_provider_foundation
import shared_preferences_foundation
import sqflite_darwin
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
}

View file

@ -170,12 +170,12 @@ packages:
dependency: transitive
description:
name: code_builder
sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37
sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e"
url: "https://pub.dev"
source: hosted
version: "4.10.0"
version: "4.10.1"
collection:
dependency: transitive
dependency: "direct main"
description:
name: collection
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
@ -307,6 +307,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_breadcrumb:
dependency: "direct main"
description:
name: flutter_breadcrumb
sha256: "1531680034def621878562ad763079933dabe9f9f5d5add5a094190edc33259b"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
flutter_cache_manager:
dependency: transitive
description:
@ -384,6 +392,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "9.1.1"
flutter_rating_stars:
dependency: "direct main"
description:
name: flutter_rating_stars
sha256: "09dfa831aac2e5128fe70c5a8bd63ff4463180d5ff8545f7379c5b209d22ce1d"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
flutter_test:
dependency: "direct dev"
description: flutter
@ -466,6 +482,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.2"
google_fonts:
dependency: "direct main"
description:
name: google_fonts
sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82
url: "https://pub.dev"
source: hosted
version: "6.2.1"
graphs:
dependency: transitive
description:
@ -474,6 +498,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.2"
highlight_text:
dependency: "direct main"
description:
name: highlight_text
sha256: c5c6ae54f89183b10b1029ab33549d32e5f52841524fd0da3df92e11c4534127
url: "https://pub.dev"
source: hosted
version: "1.8.0"
http:
dependency: "direct main"
description:
@ -718,10 +750,10 @@ packages:
dependency: "direct main"
description:
name: path_provider
sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
version: "2.1.5"
path_provider_android:
dependency: transitive
description:
@ -762,6 +794,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.0"
pedantic:
dependency: transitive
description:
name: pedantic
sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602"
url: "https://pub.dev"
source: hosted
version: "1.11.1"
permission_handler:
dependency: "direct main"
description:
@ -890,6 +930,62 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.28.0"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab"
url: "https://pub.dev"
source: hosted
version: "2.3.3"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d"
url: "https://pub.dev"
source: hosted
version: "2.5.3"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e
url: "https://pub.dev"
source: hosted
version: "2.4.2"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
shelf:
dependency: transitive
description:
@ -1015,30 +1111,38 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.0"
syncfusion_flutter_calendar:
dependency: "direct main"
description:
name: syncfusion_flutter_calendar
sha256: "769d3bbf8743922d74b242a968366661bd7b2973b3d34af9b9bc865874a520d9"
url: "https://pub.dev"
source: hosted
version: "27.1.58"
syncfusion_flutter_core:
dependency: transitive
description:
name: syncfusion_flutter_core
sha256: dde81d3a318d914e26b6882051c486b0f5e4fa13e7bc3661741de78f0397fe64
sha256: "31d2ddf410ee41abb3ecf85b7b6e8e1563307ad52ee784ddd91337e30280f715"
url: "https://pub.dev"
source: hosted
version: "27.1.56"
version: "27.1.58"
syncfusion_flutter_datepicker:
dependency: "direct main"
description:
name: syncfusion_flutter_datepicker
sha256: e4d42b03b69e80b5936f44d420f9577542f8b156ba5ee78a05e28b23ed63c850
sha256: e25797401bec43cd64c475150f87150e8bc3e67212d4d1273ff35483ea793a8b
url: "https://pub.dev"
source: hosted
version: "27.1.56"
version: "27.1.58"
syncfusion_localizations:
dependency: "direct main"
description:
name: syncfusion_localizations
sha256: "6dbc2eab1d70fad7b8501c44198bef4d36748cc6860252dfd4c8cfe2f3b10e7b"
sha256: a74b674f8d691927bebc10d19966539ecc92fa3b472c85df57e565f43e18483d
url: "https://pub.dev"
source: hosted
version: "27.1.56"
version: "27.1.58"
synchronized:
dependency: transitive
description:
@ -1063,6 +1167,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.7.2"
timezone:
dependency: "direct main"
description:
name: timezone
sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d"
url: "https://pub.dev"
source: hosted
version: "0.9.4"
timing:
dependency: transitive
description:

View file

@ -43,6 +43,14 @@ dependencies:
syncfusion_flutter_datepicker: ^27.1.50
syncfusion_localizations: ^27.1.52
flutter_dotenv: ^5.2.1
highlight_text: ^1.8.0
shared_preferences: ^2.3.2
flutter_breadcrumb: ^1.0.1
google_fonts: ^6.2.1
collection: ^1.18.0
flutter_rating_stars: ^1.1.0
syncfusion_flutter_calendar: ^27.1.58
timezone: ^0.9.4
dev_dependencies:

View file

@ -98,8 +98,7 @@
</style>
</head>
<body>
<!--<div class="loader"></div>-->
<div class="loader"></div>
<script src="flutter_bootstrap.js" async></script>
</body>
</html>