Filters & Calendars
This commit is contained in:
parent
4aa60980a1
commit
798941af12
52 changed files with 4481 additions and 623 deletions
|
@ -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": {
|
||||
|
|
BIN
assets/images/actions/areatype/betriebsflaeche.jpg
Normal file
BIN
assets/images/actions/areatype/betriebsflaeche.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 901 KiB |
BIN
assets/images/actions/areatype/betriebsstaette.jpg
Normal file
BIN
assets/images/actions/areatype/betriebsstaette.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 706 KiB |
BIN
assets/images/actions/areatype/landschaft.jpg
Normal file
BIN
assets/images/actions/areatype/landschaft.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 639 KiB |
BIN
assets/images/actions/areatype/weinberg.jpg
Normal file
BIN
assets/images/actions/areatype/weinberg.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
|
@ -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())
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
24
lib/src/entity/_general/filter/item_filter.dart
Normal file
24
lib/src/entity/_general/filter/item_filter.dart
Normal 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);
|
||||
}
|
1896
lib/src/entity/_general/filter/item_filter.g.dart
Normal file
1896
lib/src/entity/_general/filter/item_filter.g.dart
Normal file
File diff suppressed because it is too large
Load diff
40
lib/src/entity/_general/filter/item_filter_repository.dart
Normal file
40
lib/src/entity/_general/filter/item_filter_repository.dart
Normal 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(),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -5,3 +5,4 @@ import 'package:flutter_i18n/flutter_i18n.dart';
|
|||
|
||||
part 'datetime_extensions.dart';
|
||||
part 'i18n_extensions.dart';
|
||||
part 'string_extensions.dart';
|
||||
|
|
23
lib/src/extensions/string_extensions.dart
Normal file
23
lib/src/extensions/string_extensions.dart
Normal 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));
|
||||
}
|
||||
}
|
|
@ -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'];
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
0
lib/src/packages/ambito_notifier/ambito_notifier.dart
Normal file
0
lib/src/packages/ambito_notifier/ambito_notifier.dart
Normal 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];
|
||||
}
|
||||
}
|
10
lib/src/packages/ambito_sharedprefs/ambito_sharedprefs.dart
Normal file
10
lib/src/packages/ambito_sharedprefs/ambito_sharedprefs.dart
Normal 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;
|
||||
}
|
||||
}
|
237
lib/src/packages/ambito_theme/ambito_theme.dart
Normal file
237
lib/src/packages/ambito_theme/ambito_theme.dart
Normal 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;
|
||||
}
|
188
lib/src/pages/actions/action_detail_page.dart
Normal file
188
lib/src/pages/actions/action_detail_page.dart
Normal 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
154
lib/src/pages/actions/actions_pre_page.dart
Normal file
154
lib/src/pages/actions/actions_pre_page.dart
Normal 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,
|
||||
),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
42
lib/src/pages/actions/cards/advisor_card.dart
Normal file
42
lib/src/pages/actions/cards/advisor_card.dart
Normal 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
57
lib/src/pages/actions/cards/background_card.dart
Normal file
57
lib/src/pages/actions/cards/background_card.dart
Normal 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
42
lib/src/pages/actions/cards/biodiverisity_card.dart
Normal file
42
lib/src/pages/actions/cards/biodiverisity_card.dart
Normal 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
51
lib/src/pages/actions/cards/creation_card.dart
Normal file
51
lib/src/pages/actions/cards/creation_card.dart
Normal 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
42
lib/src/pages/actions/cards/description_card.dart
Normal file
42
lib/src/pages/actions/cards/description_card.dart
Normal 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
63
lib/src/pages/actions/cards/factsheet_card.dart
Normal file
63
lib/src/pages/actions/cards/factsheet_card.dart
Normal 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,
|
||||
);
|
||||
}
|
||||
}
|
38
lib/src/pages/actions/cards/funding_card.dart
Normal file
38
lib/src/pages/actions/cards/funding_card.dart
Normal 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,
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
38
lib/src/pages/actions/cards/maintenance_card.dart
Normal file
38
lib/src/pages/actions/cards/maintenance_card.dart
Normal 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,
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
71
lib/src/pages/actions/cards/material_card.dart
Normal file
71
lib/src/pages/actions/cards/material_card.dart
Normal 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,
|
||||
);
|
||||
}
|
||||
}
|
52
lib/src/pages/actions/cards/presets_card.dart
Normal file
52
lib/src/pages/actions/cards/presets_card.dart
Normal 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
66
lib/src/pages/actions/cards/review_card.dart
Normal file
66
lib/src/pages/actions/cards/review_card.dart
Normal 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
8
lib/src/pages/ambito_page.dart
Normal file
8
lib/src/pages/ambito_page.dart
Normal 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});
|
||||
}
|
175
lib/src/pages/calendar/calendar_page.dart
Normal file
175
lib/src/pages/calendar/calendar_page.dart
Normal 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;
|
||||
}*/
|
171
lib/src/pages/calendar/calendar_page_year.dart
Normal file
171
lib/src/pages/calendar/calendar_page_year.dart
Normal 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,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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')),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
98
lib/src/widgets/appbar/ambito_appbar.dart
Normal file
98
lib/src/widgets/appbar/ambito_appbar.dart
Normal 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,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
47
lib/src/widgets/form/fields/field_searchbar.dart
Normal file
47
lib/src/widgets/form/fields/field_searchbar.dart
Normal 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,
|
||||
);
|
||||
}
|
||||
}
|
23
lib/src/widgets/form/fields/field_title.dart
Normal file
23
lib/src/widgets/form/fields/field_title.dart
Normal 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,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"))
|
||||
}
|
||||
|
|
134
pubspec.lock
134
pubspec.lock
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -98,8 +98,7 @@
|
|||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!--<div class="loader"></div>-->
|
||||
|
||||
<div class="loader"></div>
|
||||
<script src="flutter_bootstrap.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue