2024-12-13

This commit is contained in:
reinjens 2024-12-13 09:41:26 +01:00
parent cab7615b08
commit bb16516891
102 changed files with 17054 additions and 1507 deletions

1
assets/fonts Symbolic link
View file

@ -0,0 +1 @@
../fonts

BIN
fonts/OpenSans-Bold.ttf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
fonts/OpenSans-Italic.ttf Normal file

Binary file not shown.

BIN
fonts/OpenSans-Light.ttf Normal file

Binary file not shown.

Binary file not shown.

BIN
fonts/OpenSans-Medium.ttf Normal file

Binary file not shown.

Binary file not shown.

BIN
fonts/OpenSans-Regular.ttf Normal file

Binary file not shown.

BIN
fonts/OpenSans-SemiBold.ttf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -14,7 +14,9 @@
"buttons": {
"delete": "Löschen",
"cancel": "Abbrechen",
"save": "Speichern"
"save": "Speichern",
"print_all": "Alles drucken",
"print": "Drucken"
},
"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."
},
@ -110,7 +112,7 @@
},
"material": {
"title": "Material",
"suggested_price": "Preis ca. ",
"suggested_price": "Richtpreis ca. ",
"add_to_basket": "in den Warenkorb"
}
}

View file

@ -1,6 +1,8 @@
import 'package:ambito/src/config/config.dart';
import 'package:ambito/src/consts/consts.dart';
import 'package:ambito/src/entity/enums/enum_details_type.dart';
import 'package:ambito/src/entity/cart/cart.dart';
import 'package:ambito/src/entity/cart/cart_element.dart';
import 'package:ambito/src/entity/cart/cart_repository.dart';
import 'package:ambito/src/entity/lists/list_measure.dart';
import 'package:ambito/src/entity/lists/list_repository.dart';
import 'package:ambito/src/packages/ambito_api/base_api.dart';
@ -9,6 +11,7 @@ import 'package:ambito/src/packages/ambito_notifier/notifier/theme_manager.dart'
import 'package:ambito/src/packages/ambito_sharedprefs/ambito_sharedprefs.dart';
import 'package:ambito/src/pages/calendar/calendar_page.dart';
import 'package:ambito/src/pages/calendar/calendar_page_year.dart';
import 'package:ambito/src/pages/cart/cart_page.dart';
import 'package:ambito/src/pages/dashboard/areas/dashboard_areas_page.dart';
import 'package:ambito/src/pages/dashboard/dashboard_page.dart';
import 'package:ambito/src/pages/error/error_page.dart';
@ -33,28 +36,48 @@ void main() async {
await AmbitoSharedPrefs.start();
await AmbitoIsarDB.init();
await Future.wait([
//BaseApi().getContent('tree_type'),
BaseApi().getContent('measure_types'),
BaseApi().getContent('measure_types_details'),
BaseApi().getContent('measure_general'),
BaseApi().getContent('measure_details'),
//BaseApi().getContent('measure_combination'),
//BaseApi().getContent('organism'),
BaseApi().getContent('funding_program'),
//BaseApi().getContent('location_requirements'),
//BaseApi().getContent('reference_implementation'),
BaseApi().getContent('business'),
BaseApi().getContent('area'),
//BaseApi().getContent('service_provider'),
//BaseApi().getContent('service_provider_contact_person'),
//BaseApi().getContent('material'),
//BaseApi().getContent('source'),
]);
List<int> myCartIds = [];
var carts = await BaseApi().getContent('cart', false);
for (final cart in carts) {
CartRepository().put(Cart.fromJson(cart));
}
var cart_elements = await BaseApi().getContent('cart_element', false);
for (final element in cart_elements) {
CartRepository().putElement(CartElement.fromJson(element));
}
/*for (final cart in carts) {
if (cart['field_3106997'].first['id'] ==
(prefs.getInt('currentUser') ?? 100)) {
logger.i('Found my cart!');
Cart cartToSave = Cart.fromJson(cart);
myCartIds.add(cartToSave.id);
CartRepository().put(cartToSave);
}
}*/
/*BaseApi().getContent('cart', false).then((carts) {
logger.i(carts);
for (final cart in carts) {
logger.e(cart);
if (cart['field_3106997'].first['id'] ==
(prefs.getInt('currentUser') ?? 100)) {
logger.i('Found my cart!');
CartRepository().put(Cart.fromJson(cart));
}
}
logger.e(CartRepository().getAll().length);
});*/
ListRepository().buildTypeGroupCategoryList();
ListRepository().buildListMeasureSingle();
//await MeasureRepository().getCategoriesAndTypes();
//await MeasureRepository().buildMeasureFilters();
//await MeasureRepository().downloadImages();
ListRepository().putListMeasure(listMeasures);
await MeasureRepository().getCategoriesGroupsAndTypes();
@ -104,6 +127,12 @@ class Ambito extends StatelessWidget {
name: '/',
page: () => const MeasureCategoriesPage(),
),
GetPage(
name: '/warenkorb',
page: () => const CartPage(
measure: null,
),
),
GetPage(
name: '/kalender',
page: () => const CalendarPage(),
@ -179,9 +208,8 @@ class Ambito extends StatelessWidget {
page: () => const MeasureCreatePage(),
),
GetPage(
name: '/massnahme/',
page: () => const MeasureDetailPage(
id: 0, type: EnumDetailsType.measure),
name: '/massnahme/:id',
page: () => const MeasureDetailPage(),
),
GetPage(
name: '/error',

View file

@ -68,4 +68,6 @@ const baserowIds = {
"contact_person": 330832,
"material": 330836,
"source": 334231,
"cart": 406916,
"cart_element": 407428,
};

View file

@ -1,6 +1,8 @@
import 'package:isar/isar.dart';
import 'package:json_annotation/json_annotation.dart';
import '../../../consts/consts.dart';
part 'id_value.g.dart';
@JsonSerializable(explicitToJson: true)
@ -14,5 +16,6 @@ class IdValue {
factory IdValue.fromJson(Map<String, dynamic> json) =>
_$IdValueFromJson(json);
int? toJson() => id;
toJson() =>
(prefs.getBool('extended_json') == true) ? _$IdValueToJson(this) : id;
}

View file

@ -1,6 +1,8 @@
import 'package:isar/isar.dart';
import 'package:json_annotation/json_annotation.dart';
import '../../../consts/consts.dart';
part 'id_value_color.g.dart';
@JsonSerializable(explicitToJson: true)
@ -15,5 +17,7 @@ class IdValueColor {
factory IdValueColor.fromJson(Map<String, dynamic> json) =>
_$IdValueColorFromJson(json);
int? toJson() => id;
toJson() => (prefs.getBool('extended_json') == true)
? _$IdValueColorToJson(this)
: id;
}

View file

@ -10,8 +10,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import '../../packages/ambito_theme/ambito_theme.dart';
class AreaDataSource extends DataGridSource {
AreaDataSource(
{required List<Area> areas, required BuildContext this.context}) {
AreaDataSource({required List<Area> areas, required this.context}) {
dataGridRows = areas
.map<DataGridRow>(
(dataGridRow) => DataGridRow(

View file

@ -0,0 +1,24 @@
import 'package:ambito/src/entity/base_entity.dart';
import 'package:isar/isar.dart';
import 'package:json_annotation/json_annotation.dart';
import '../_general/id_value/id_value.dart';
part 'cart.g.dart';
@JsonSerializable(explicitToJson: true)
@collection
class Cart extends BaseEntity with EntityWithId {
Cart();
@JsonKey(name: 'field_3106992')
String? name;
@JsonKey(name: 'field_3106997')
List<IdValue>? business;
@JsonKey(includeFromJson: false, includeToJson: false)
double? price;
factory Cart.fromJson(Map<String, dynamic> json) => _$CartFromJson(json);
Map<String, dynamic> toJson() => _$CartToJson(this);
}

View file

@ -0,0 +1,881 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'cart.dart';
// **************************************************************************
// _IsarCollectionGenerator
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, invalid_use_of_protected_member, lines_longer_than_80_chars, constant_identifier_names, avoid_js_rounded_ints, no_leading_underscores_for_local_identifiers, require_trailing_commas, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_in_if_null_operators, library_private_types_in_public_api, prefer_const_constructors
// ignore_for_file: type=lint
extension GetCartCollection on Isar {
IsarCollection<int, Cart> get carts => this.collection();
}
const CartSchema = IsarGeneratedSchema(
schema: IsarSchema(
name: 'Cart',
idName: 'id',
embedded: false,
properties: [
IsarPropertySchema(
name: 'name',
type: IsarType.string,
),
IsarPropertySchema(
name: 'business',
type: IsarType.objectList,
target: 'IdValue',
),
IsarPropertySchema(
name: 'price',
type: IsarType.double,
),
],
indexes: [],
),
converter: IsarObjectConverter<int, Cart>(
serialize: serializeCart,
deserialize: deserializeCart,
deserializeProperty: deserializeCartProp,
),
embeddedSchemas: [IdValueSchema],
);
@isarProtected
int serializeCart(IsarWriter writer, Cart object) {
{
final value = object.name;
if (value == null) {
IsarCore.writeNull(writer, 1);
} else {
IsarCore.writeString(writer, 1, value);
}
}
{
final list = object.business;
if (list == null) {
IsarCore.writeNull(writer, 2);
} else {
final listWriter = IsarCore.beginList(writer, 2, list.length);
for (var i = 0; i < list.length; i++) {
{
final value = list[i];
final objectWriter = IsarCore.beginObject(listWriter, i);
serializeIdValue(objectWriter, value);
IsarCore.endObject(listWriter, objectWriter);
}
}
IsarCore.endList(writer, listWriter);
}
}
IsarCore.writeDouble(writer, 3, object.price ?? double.nan);
return object.id;
}
@isarProtected
Cart deserializeCart(IsarReader reader) {
final object = Cart();
object.name = IsarCore.readString(reader, 1);
{
final length = IsarCore.readList(reader, 2, IsarCore.readerPtrPtr);
{
final reader = IsarCore.readerPtr;
if (reader.isNull) {
object.business = null;
} else {
final list = List<IdValue>.filled(length, IdValue(), growable: true);
for (var i = 0; i < length; i++) {
{
final objectReader = IsarCore.readObject(reader, i);
if (objectReader.isNull) {
list[i] = IdValue();
} else {
final embedded = deserializeIdValue(objectReader);
IsarCore.freeReader(objectReader);
list[i] = embedded;
}
}
}
IsarCore.freeReader(reader);
object.business = list;
}
}
}
{
final value = IsarCore.readDouble(reader, 3);
if (value.isNaN) {
object.price = null;
} else {
object.price = value;
}
}
object.id = IsarCore.readId(reader);
return object;
}
@isarProtected
dynamic deserializeCartProp(IsarReader reader, int property) {
switch (property) {
case 1:
return IsarCore.readString(reader, 1);
case 2:
{
final length = IsarCore.readList(reader, 2, IsarCore.readerPtrPtr);
{
final reader = IsarCore.readerPtr;
if (reader.isNull) {
return null;
} else {
final list =
List<IdValue>.filled(length, IdValue(), growable: true);
for (var i = 0; i < length; i++) {
{
final objectReader = IsarCore.readObject(reader, i);
if (objectReader.isNull) {
list[i] = IdValue();
} else {
final embedded = deserializeIdValue(objectReader);
IsarCore.freeReader(objectReader);
list[i] = embedded;
}
}
}
IsarCore.freeReader(reader);
return list;
}
}
}
case 3:
{
final value = IsarCore.readDouble(reader, 3);
if (value.isNaN) {
return null;
} else {
return value;
}
}
case 0:
return IsarCore.readId(reader);
default:
throw ArgumentError('Unknown property: $property');
}
}
sealed class _CartUpdate {
bool call({
required int id,
String? name,
double? price,
});
}
class _CartUpdateImpl implements _CartUpdate {
const _CartUpdateImpl(this.collection);
final IsarCollection<int, Cart> collection;
@override
bool call({
required int id,
Object? name = ignore,
Object? price = ignore,
}) {
return collection.updateProperties([
id
], {
if (name != ignore) 1: name as String?,
if (price != ignore) 3: price as double?,
}) >
0;
}
}
sealed class _CartUpdateAll {
int call({
required List<int> id,
String? name,
double? price,
});
}
class _CartUpdateAllImpl implements _CartUpdateAll {
const _CartUpdateAllImpl(this.collection);
final IsarCollection<int, Cart> collection;
@override
int call({
required List<int> id,
Object? name = ignore,
Object? price = ignore,
}) {
return collection.updateProperties(id, {
if (name != ignore) 1: name as String?,
if (price != ignore) 3: price as double?,
});
}
}
extension CartUpdate on IsarCollection<int, Cart> {
_CartUpdate get update => _CartUpdateImpl(this);
_CartUpdateAll get updateAll => _CartUpdateAllImpl(this);
}
sealed class _CartQueryUpdate {
int call({
String? name,
double? price,
});
}
class _CartQueryUpdateImpl implements _CartQueryUpdate {
const _CartQueryUpdateImpl(this.query, {this.limit});
final IsarQuery<Cart> query;
final int? limit;
@override
int call({
Object? name = ignore,
Object? price = ignore,
}) {
return query.updateProperties(limit: limit, {
if (name != ignore) 1: name as String?,
if (price != ignore) 3: price as double?,
});
}
}
extension CartQueryUpdate on IsarQuery<Cart> {
_CartQueryUpdate get updateFirst => _CartQueryUpdateImpl(this, limit: 1);
_CartQueryUpdate get updateAll => _CartQueryUpdateImpl(this);
}
class _CartQueryBuilderUpdateImpl implements _CartQueryUpdate {
const _CartQueryBuilderUpdateImpl(this.query, {this.limit});
final QueryBuilder<Cart, Cart, QOperations> query;
final int? limit;
@override
int call({
Object? name = ignore,
Object? price = ignore,
}) {
final q = query.build();
try {
return q.updateProperties(limit: limit, {
if (name != ignore) 1: name as String?,
if (price != ignore) 3: price as double?,
});
} finally {
q.close();
}
}
}
extension CartQueryBuilderUpdate on QueryBuilder<Cart, Cart, QOperations> {
_CartQueryUpdate get updateFirst =>
_CartQueryBuilderUpdateImpl(this, limit: 1);
_CartQueryUpdate get updateAll => _CartQueryBuilderUpdateImpl(this);
}
extension CartQueryFilter on QueryBuilder<Cart, Cart, QFilterCondition> {
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const IsNullCondition(property: 1));
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameIsNotNull() {
return QueryBuilder.apply(not(), (query) {
return query.addFilterCondition(const IsNullCondition(property: 1));
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameEqualTo(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
EqualCondition(
property: 1,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameGreaterThan(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
GreaterCondition(
property: 1,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameGreaterThanOrEqualTo(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
GreaterOrEqualCondition(
property: 1,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameLessThan(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
LessCondition(
property: 1,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameLessThanOrEqualTo(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
LessOrEqualCondition(
property: 1,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameBetween(
String? lower,
String? upper, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
BetweenCondition(
property: 1,
lower: lower,
upper: upper,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameStartsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
StartsWithCondition(
property: 1,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameEndsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
EndsWithCondition(
property: 1,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameContains(String value,
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
ContainsCondition(
property: 1,
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameMatches(String pattern,
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
MatchesCondition(
property: 1,
wildcard: pattern,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const EqualCondition(
property: 1,
value: '',
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> nameIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const GreaterCondition(
property: 1,
value: '',
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> businessIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const IsNullCondition(property: 2));
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> businessIsNotNull() {
return QueryBuilder.apply(not(), (query) {
return query.addFilterCondition(const IsNullCondition(property: 2));
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> businessIsEmpty() {
return not().group(
(q) => q.businessIsNull().or().businessIsNotEmpty(),
);
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> businessIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const GreaterOrEqualCondition(property: 2, value: null),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> priceIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const IsNullCondition(property: 3));
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> priceIsNotNull() {
return QueryBuilder.apply(not(), (query) {
return query.addFilterCondition(const IsNullCondition(property: 3));
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> priceEqualTo(
double? value, {
double epsilon = Filter.epsilon,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
EqualCondition(
property: 3,
value: value,
epsilon: epsilon,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> priceGreaterThan(
double? value, {
double epsilon = Filter.epsilon,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
GreaterCondition(
property: 3,
value: value,
epsilon: epsilon,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> priceGreaterThanOrEqualTo(
double? value, {
double epsilon = Filter.epsilon,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
GreaterOrEqualCondition(
property: 3,
value: value,
epsilon: epsilon,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> priceLessThan(
double? value, {
double epsilon = Filter.epsilon,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
LessCondition(
property: 3,
value: value,
epsilon: epsilon,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> priceLessThanOrEqualTo(
double? value, {
double epsilon = Filter.epsilon,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
LessOrEqualCondition(
property: 3,
value: value,
epsilon: epsilon,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> priceBetween(
double? lower,
double? upper, {
double epsilon = Filter.epsilon,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
BetweenCondition(
property: 3,
lower: lower,
upper: upper,
epsilon: epsilon,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> idEqualTo(
int value,
) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
EqualCondition(
property: 0,
value: value,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> idGreaterThan(
int value,
) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
GreaterCondition(
property: 0,
value: value,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> idGreaterThanOrEqualTo(
int value,
) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
GreaterOrEqualCondition(
property: 0,
value: value,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> idLessThan(
int value,
) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
LessCondition(
property: 0,
value: value,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> idLessThanOrEqualTo(
int value,
) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
LessOrEqualCondition(
property: 0,
value: value,
),
);
});
}
QueryBuilder<Cart, Cart, QAfterFilterCondition> idBetween(
int lower,
int upper,
) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
BetweenCondition(
property: 0,
lower: lower,
upper: upper,
),
);
});
}
}
extension CartQueryObject on QueryBuilder<Cart, Cart, QFilterCondition> {}
extension CartQuerySortBy on QueryBuilder<Cart, Cart, QSortBy> {
QueryBuilder<Cart, Cart, QAfterSortBy> sortByName(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(
1,
caseSensitive: caseSensitive,
);
});
}
QueryBuilder<Cart, Cart, QAfterSortBy> sortByNameDesc(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(
1,
sort: Sort.desc,
caseSensitive: caseSensitive,
);
});
}
QueryBuilder<Cart, Cart, QAfterSortBy> sortByPrice() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(3);
});
}
QueryBuilder<Cart, Cart, QAfterSortBy> sortByPriceDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(3, sort: Sort.desc);
});
}
QueryBuilder<Cart, Cart, QAfterSortBy> sortById() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(0);
});
}
QueryBuilder<Cart, Cart, QAfterSortBy> sortByIdDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(0, sort: Sort.desc);
});
}
}
extension CartQuerySortThenBy on QueryBuilder<Cart, Cart, QSortThenBy> {
QueryBuilder<Cart, Cart, QAfterSortBy> thenByName(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(1, caseSensitive: caseSensitive);
});
}
QueryBuilder<Cart, Cart, QAfterSortBy> thenByNameDesc(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(1, sort: Sort.desc, caseSensitive: caseSensitive);
});
}
QueryBuilder<Cart, Cart, QAfterSortBy> thenByPrice() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(3);
});
}
QueryBuilder<Cart, Cart, QAfterSortBy> thenByPriceDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(3, sort: Sort.desc);
});
}
QueryBuilder<Cart, Cart, QAfterSortBy> thenById() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(0);
});
}
QueryBuilder<Cart, Cart, QAfterSortBy> thenByIdDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(0, sort: Sort.desc);
});
}
}
extension CartQueryWhereDistinct on QueryBuilder<Cart, Cart, QDistinct> {
QueryBuilder<Cart, Cart, QAfterDistinct> distinctByName(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(1, caseSensitive: caseSensitive);
});
}
QueryBuilder<Cart, Cart, QAfterDistinct> distinctByPrice() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(3);
});
}
}
extension CartQueryProperty1 on QueryBuilder<Cart, Cart, QProperty> {
QueryBuilder<Cart, String?, QAfterProperty> nameProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(1);
});
}
QueryBuilder<Cart, List<IdValue>?, QAfterProperty> businessProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(2);
});
}
QueryBuilder<Cart, double?, QAfterProperty> priceProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(3);
});
}
QueryBuilder<Cart, int, QAfterProperty> idProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(0);
});
}
}
extension CartQueryProperty2<R> on QueryBuilder<Cart, R, QAfterProperty> {
QueryBuilder<Cart, (R, String?), QAfterProperty> nameProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(1);
});
}
QueryBuilder<Cart, (R, List<IdValue>?), QAfterProperty> businessProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(2);
});
}
QueryBuilder<Cart, (R, double?), QAfterProperty> priceProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(3);
});
}
QueryBuilder<Cart, (R, int), QAfterProperty> idProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(0);
});
}
}
extension CartQueryProperty3<R1, R2>
on QueryBuilder<Cart, (R1, R2), QAfterProperty> {
QueryBuilder<Cart, (R1, R2, String?), QOperations> nameProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(1);
});
}
QueryBuilder<Cart, (R1, R2, List<IdValue>?), QOperations> businessProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(2);
});
}
QueryBuilder<Cart, (R1, R2, double?), QOperations> priceProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(3);
});
}
QueryBuilder<Cart, (R1, R2, int), QOperations> idProperty() {
return QueryBuilder.apply(this, (query) {
return query.addProperty(0);
});
}
}
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Cart _$CartFromJson(Map<String, dynamic> json) => Cart()
..id = (json['id'] as num).toInt()
..name = json['field_3106992'] as String?
..business = (json['field_3106997'] as List<dynamic>?)
?.map((e) => IdValue.fromJson(e as Map<String, dynamic>))
.toList();
Map<String, dynamic> _$CartToJson(Cart instance) => <String, dynamic>{
'id': instance.id,
'field_3106992': instance.name,
'field_3106997': instance.business?.map((e) => e.toJson()).toList(),
};

View file

@ -0,0 +1,157 @@
import 'package:ambito/src/entity/cart/cart_element.dart';
import 'package:ambito/src/entity/entities.dart';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import '../../packages/ambito_theme/ambito_theme.dart';
class CartDataSource extends DataGridSource {
CartDataSource(
{required List<CartElement> cartElements, required this.context}) {
dataGridRows = cartElements
.map<DataGridRow>(
(dataGridRow) => DataGridRow(
cells: [
DataGridCell<String>(
columnName: 'name',
value: dataGridRow.name,
),
DataGridCell<String>(
columnName: 'amount',
value: dataGridRow.amount,
),
DataGridCell<List<IdValue>>(
columnName: 'provider',
value: dataGridRow.provider,
),
DataGridCell<String>(
columnName: 'price',
value: dataGridRow.price.toString(),
),
],
),
)
.toList();
}
final BuildContext context;
List<DataGridRow> dataGridRows = [];
@override
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
final AmbitoTheme theme = getTheme(context);
double completePrice = double.tryParse(row
.getCells()
.where((cell) => cell.columnName == 'price')
.first
.value
.toString() ??
'0.0') ??
0;
int amount = int.tryParse(row
.getCells()
.where((cell) => cell.columnName == 'amount')
.first
.value
.toString() ??
'0') ??
0;
if (amount > 1) {
completePrice = completePrice * amount;
}
return DataGridRowAdapter(
cells: row.getCells().map<Widget>(
(dataGridCell) {
if (dataGridCell.columnName == 'provider') {
final providerString =
dataGridCell.value.map((ele) => ele.value).toList().join(', ');
return Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Text(
providerString,
overflow: TextOverflow.ellipsis,
style: theme.bodyMedium.copyWith(
color: theme.currentColorScheme.primary,
),
),
);
}
if (dataGridCell.columnName == 'price') {
final priceString = amount == 1
? '${dataGridCell.value ?? '0'}'
: '${completePrice.toStringAsFixed(2)}€ (${dataGridCell.value ?? '0'}€ pro Stk.)';
return Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Text(
priceString,
overflow: TextOverflow.ellipsis,
style: theme.bodyMedium.copyWith(
color: theme.currentColorScheme.primary,
),
),
);
}
if (dataGridCell.columnName == 'amount') {
return Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
icon: Icon(
Icons.remove,
color: Theme.of(context).colorScheme.secondary,
),
padding:
EdgeInsets.symmetric(vertical: 4.0, horizontal: 18.0),
iconSize: 16.0,
color: Theme.of(context).primaryColor,
onPressed: () {},
),
Text(
dataGridCell.value,
textAlign: TextAlign.center,
style: theme.bodyMedium,
),
IconButton(
icon: Icon(
Icons.add,
color: Theme.of(context).colorScheme.secondary,
),
padding:
EdgeInsets.symmetric(vertical: 4.0, horizontal: 18.0),
iconSize: 16.0,
color: Theme.of(context).primaryColor,
onPressed: () {},
),
],
),
);
}
return Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
style: theme.bodyMedium.copyWith(
color: theme.currentColorScheme.primary,
),
),
);
},
).toList());
}
}

View file

@ -0,0 +1,30 @@
import 'package:ambito/src/entity/_general/id_value/id_value.dart';
import 'package:ambito/src/entity/base_entity.dart';
import 'package:isar/isar.dart';
import 'package:json_annotation/json_annotation.dart';
part 'cart_element.g.dart';
@collection
@JsonSerializable(explicitToJson: true)
class CartElement extends BaseEntity with EntityWithId {
CartElement();
@JsonKey(name: 'field_3110710')
String? name;
@JsonKey(name: 'field_3110713')
List<IdValue>? cart;
@JsonKey(name: 'field_3110714')
String? amount;
@JsonKey(name: 'field_3110715')
List<IdValue>? provider;
@JsonKey(name: 'field_3110716')
String? priceType;
@JsonKey(name: 'field_3110717')
String? price;
factory CartElement.fromJson(Map<String, dynamic> json) =>
_$CartElementFromJson(json);
Map<String, dynamic> toJson() => _$CartElementToJson(this);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,52 @@
import 'package:ambito/src/entity/cart/cart.dart';
import 'package:ambito/src/entity/cart/cart_element.dart';
import 'package:ambito/src/packages/ambito_notifier/notifier/cart_notifier.dart';
import 'package:isar/isar.dart';
import '../../consts/consts.dart';
import '../../packages/ambito_db/base_db.dart';
class CartRepository extends BaseDB {
@override
IsarCollection collection = isar.carts;
void upsert(Cart cart) {
Cart? existing = isar.carts.where().nameEqualTo(cart.name!).findFirst();
if (existing == null) {
ambitoCartNotifier.addCart();
existing = cart;
}
isar.write((isar) {
isar.carts.put(existing!);
});
}
void putElement(CartElement cartElement) {
isar.write((isar) {
isar.cartElements.put(cartElement);
});
}
List<Cart> getMyCarts() {
List<Cart> myCarts = [];
final all = isar.carts.where().findAll();
for (final cart in all) {
if (cart.business?.first.id == (prefs.getInt('currentUser') ?? 100)) {
myCarts.add(cart);
}
}
return myCarts;
}
List<CartElement> getElementsByCartId(int cartId) {
List<CartElement> myElements = [];
final all = isar.cartElements.where().findAll();
for (final element in all) {
if (element.cart!.first.id == cartId) {
myElements.add(element);
}
}
return myElements;
}
}

View file

@ -12,9 +12,15 @@ part 'list_measure.g.dart';
@collection
@JsonSerializable()
class ListMeasure extends BaseEntity with EntityWithId {
class ListMeasure extends BaseEntity {
ListMeasure();
@JsonKey(includeToJson: false, includeFromJson: false)
@Id()
late int isarId;
@Index()
int? id;
@Index()
String? name;
String? description;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,239 @@
import 'package:ambito/src/entity/_general/file/file_part.dart';
import 'package:ambito/src/entity/_general/id_value_color/id_value_color.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:isar/isar.dart';
import 'package:json_annotation/json_annotation.dart';
import '../../_general/file/thumbnail.dart';
import '../../_general/file/thumbnails.dart';
import '../../_general/id_value/id_value.dart';
part 'measure_complete.g.dart';
@JsonSerializable()
@collection
class MeasureComplete {
MeasureComplete({required this.id, required this.name});
final int id;
final String name;
FilePart? image;
String? description;
String? target;
List<String>? fundingPrograms;
List<String>? sizeOrArea;
String? growth;
String? climate;
String? soilWater;
String? riskOfSpottedWingDrosophila;
String? thermophilic;
String? frostHardy;
String? lateFrost;
String? drought;
List<String>? soilMoisture;
String? numberLight;
String? numberTemperature;
String? numberMoisture;
String? numberReaction;
String? numberNitrogen;
List<String>? region;
String? location;
String? applyCosts;
String? applyDuration;
List<String>? applyMonths;
List<String>? applyTools;
String? applyAdditionalInfos;
String? applySteps;
List<String>? applyMaterials;
List<FilePart>? gallery;
List<String>? maintenanceMonths;
String? maintenanceAdditionalInfos;
String? maintenanceFrequency;
String? maintenanceSteps;
String? maintenanceSpecialFeatures;
List<String>? maintenanceTools;
String? sources;
String? costs;
String? costsUnit;
String? measureType;
List<String>? measureGroups;
List<String>? measureCategories;
factory MeasureComplete.fromJson(Map<String, dynamic> json) {
List<String> helper = [];
List<FilePart> helperFiles = [];
MeasureComplete mc =
MeasureComplete(id: json['id'], name: json['field_3021886']);
if (json['field_2402548'] != null && json['field_2402548'].isNotEmpty) {
mc.image = FilePart.fromJson(json['field_2402548'][0]);
} else {
//mc.image =
}
mc.description = json['field_2402431'];
mc.target = json['field_2402433'];
if (json['field_2402540'] != null) {
json['field_2402540'].forEach((element) {
final IdValue idv = IdValue.fromJson(element);
helper.add(idv.value!);
});
}
mc.fundingPrograms = helper;
helper = [];
if (json['field_2402427'] != null) {
json['field_2402427'].forEach((element) {
final IdValueColor idv = IdValueColor.fromJson(element);
helper.add(idv.value!);
});
}
mc.measureCategories = helper;
mc.measureGroups = [IdValueColor.fromJson(json['field_2402473']).value!];
mc.measureType = json['field_2402426'];
helper = [];
mc.sizeOrArea = [
json['field_2402445'],
'Höhe: ${json['field_2532843']} - ${json['field_2532844']}mm'
];
if (json['field_2532846'] != null) {
json['field_2532846'].forEach((element) {
mc.growth = IdValueColor.fromJson(element).value;
});
}
if (json['field_2532849'] != null) {
mc.climate = IdValueColor.fromJson(json['field_2532849']).value;
}
if (json['field_2532853'] != null) {
mc.soilWater = json['field_2532853'];
}
if (json['field_2532848'] != null) {
mc.riskOfSpottedWingDrosophila =
IdValueColor.fromJson(json['field_2532848']).value;
}
if (json['field_2532860'] != null) {
json['field_2532860'].forEach((element) {
final IdValueColor idv = IdValueColor.fromJson(element);
helper.add(idv.value!);
});
}
mc.region = helper;
helper = [];
mc.location = json['field_2402444'];
mc.applyCosts = json['field_2402448'];
mc.applyDuration = json['field_2429064'];
if (json['field_2402440'] != null) {
json['field_2402440'].forEach((element) {
final IdValueColor idv = IdValueColor.fromJson(element);
helper.add(idv.value!);
});
}
mc.applyMonths = helper;
helper = [];
mc.applyAdditionalInfos = json['field_2429782'];
mc.applySteps = json['field_2402443'];
if (json['field_2498056'] != null) {
json['field_2498056'].forEach((element) {
final IdValueColor idv = IdValueColor.fromJson(element);
helper.add(idv.value!);
});
}
mc.maintenanceMonths = helper;
helper = [];
if (json['field_2429460'] != null) {
json['field_2429460'].forEach((element) {
final IdValueColor idv = IdValueColor.fromJson(element);
helper.add(idv.value!);
});
}
mc.applyTools = helper;
helper = [];
if (json['field_2428593'] != null) {
json['field_2428593'].forEach((element) {
final IdValueColor idv = IdValueColor.fromJson(element);
helper.add(idv.value!);
});
}
mc.applyMaterials = helper;
helper = [];
if (json['field_2402454'] != null) {
json['field_2402454'].forEach((element) {
final IdValueColor idv = IdValueColor.fromJson(element);
helper.add(idv.value!);
});
}
mc.maintenanceFrequency = helper.join(', ');
helper = [];
mc.maintenanceAdditionalInfos = json['field_2463465'];
mc.maintenanceSteps = json['field_2402452'];
mc.maintenanceSpecialFeatures = json['field_2402455'];
if (json['field_2429972'] != null) {
json['field_2429972'].forEach((element) {
final IdValueColor idv = IdValueColor.fromJson(element);
helper.add(idv.value!);
});
}
mc.maintenanceTools = helper;
helper = [];
mc.sources = json['field_2402437'];
if (json['field_3021896'] != null) {
json['field_3021896'].forEach((element) {
final FilePart fp = FilePart.fromJson(element);
helperFiles.add(fp);
});
}
mc.gallery = helperFiles;
helperFiles = [];
if (json['field_3021904'] != null) {
mc.costsUnit = IdValueColor.fromJson(json['field_3021904']).value;
}
mc.costs = json['field_3021892'];
return mc;
}
Map<String, dynamic> toJson() => _$MeasureCompleteToJson(this);
}
extension MeasureCompleteExtension on MeasureComplete {
CachedNetworkImage? getFullImage() {
CachedNetworkImage? cachedImage;
if (image != null) {
if (image!.url != null) {
cachedImage = CachedNetworkImage(
imageUrl: image!.url!,
placeholder: (context, url) => const CircularProgressIndicator(),
errorWidget: (context, url, error) => const Icon(Icons.error),
fit: BoxFit.cover,
);
}
}
return cachedImage;
}
List<Widget>? getGalleryThumbnails() {
List<Widget>? images = [];
if (gallery != null && gallery!.isNotEmpty) {
for (final FilePart image in gallery!) {
if (image.thumbnails?.cardCover?.url != null) {
images.add(
Padding(
padding: const EdgeInsets.all(10),
child: CachedNetworkImage(
imageUrl: image.thumbnails!.cardCover!.url!,
placeholder: (context, url) =>
const CircularProgressIndicator(),
errorWidget: (context, url, error) => const Icon(Icons.error),
),
),
);
}
}
}
return (images.isNotEmpty) ? images : null;
}
}

File diff suppressed because it is too large Load diff

View file

@ -7,4 +7,12 @@ import '../../../packages/ambito_db/base_db.dart';
class MeasureDetailsRepository extends BaseDB {
@override
IsarCollection collection = isar.measureDetails;
MeasureDetails getDetailsForMeasure(String measure) {
List<MeasureDetails> all = isar.measureDetails.where().findAll();
return all
.where(
(el) => el.measure!.map((m) => m.value).toList().contains(measure))
.first;
}
}

View file

@ -56,7 +56,8 @@ class MeasureGeneral extends BaseEntity with EntityWithId {
extension MeasureGeneralExtension on MeasureGeneral {
ListMeasure toListMeasure() {
final listMeasure = ListMeasure()
..id = isar.listMeasures.autoIncrement()
..isarId = isar.listMeasures.autoIncrement()
..id = this.id
..name = name
..measureGroups = measureGroup
?.map((group) =>

View file

@ -14,6 +14,10 @@ class MeasureGeneralRepository extends BaseDB {
return isar.measureGenerals.where().sortByName().findAll();
}
MeasureGeneral? getByName(String name) {
return isar.measureGenerals.where().nameEqualTo(name).findFirst();
}
List<MeasureGeneral> getAllOrderedByGroupAndType(
String group,
String type,

View file

@ -2,6 +2,7 @@ import 'package:ambito/src/entity/entities.dart';
import 'package:ambito/src/entity/lists/list_display.dart';
import 'package:ambito/src/entity/lists/list_repository.dart';
import 'package:ambito/src/entity/measure/category/measure_category.dart';
import 'package:ambito/src/entity/measure/complete/measure_complete.dart';
import 'package:ambito/src/entity/measure/measure_grouping.dart';
import 'package:ambito/src/extensions/extensions.dart';
import 'package:ambito/src/packages/ambito_db/base_db.dart';
@ -22,6 +23,10 @@ class MeasureRepository extends BaseDB {
});
}
MeasureTypes? getTypeByName(String name) {
return isar.measureTypes.where().measureTypeEqualTo(name).findFirst();
}
Map<String, int> getTypesCounterByCategory(String category) {
final counter = <String, int>{};
@ -116,119 +121,10 @@ class MeasureRepository extends BaseDB {
}
Future<bool> buildLists() async {
var measures = getAll();
Map<String, List<Map<String, IdValueColor>>> lists = {};
/*List<IsarPropertySchema> props = MeasureSchema.schema.properties;
for (var prop in props) {
if (prop.type == IsarType.objectList) {
lists[prop.name] = [];
}
}
logger.d(lists);
int counter = 0;
for (Measure measure in measures) {
var json = measure.toJson();
if (counter == 0) {
logger.d(json);
}
lists.forEach((key, value) {
if (counter == 0) {
logger.d(key);
}
if (json[key] != null) {
logger.d(json[key]);
}
});
counter++;
}*/
return true;
}
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
..url = entry.key.toLowerCase().replaceUmlauts()
..type = 'areaType'
..description =
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy.'
..image =
'images/measure/category/${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
..url = entry.key.toLowerCase().replaceUmlauts()
..type = 'group'
..description = 'Lorem ipsum dolor sit amet, consetetur sadipscing.'
..image =
'images/measure/category/${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
..url = entry.key.toLowerCase().replaceUmlauts()
..type = 'month'
..ids = entry.value)
.toList());
itemFilterRepo.putAll(filterFundingPrograms.entries
.map((entry) => ItemFilter()
..id = autoIncrement()
..name = entry.key
..url = entry.key.toLowerCase().replaceUmlauts()
..type = 'fundingProgram'
..ids = entry.value)
.toList());
*/
return true;
}
@ -360,4 +256,8 @@ class MeasureRepository extends BaseDB {
entries: filterItems.map((item) => item.title!).toList(),
);
}
MeasureComplete? getMeasureCompleteByName(String name) {
return isar.measureCompletes.where().nameEqualTo(name).findFirst();
}
}

View file

@ -154,7 +154,8 @@ class MeasureTypes extends BaseEntity with EntityWithId {
extension MeasureExtension on MeasureTypes {
ListMeasure toListMeasure() {
final listMeasure = ListMeasure()
..id = isar.listMeasures.autoIncrement()
..isarId = isar.listMeasures.autoIncrement()
..id = this.id
..name = measureType
..measureCategories = measureCategory
?.map(

View file

@ -7,4 +7,11 @@ import '../../../packages/ambito_db/base_db.dart';
class MeasureTypesDetailsRepository extends BaseDB {
@override
IsarCollection collection = isar.measureTypesDetails;
MeasureTypesDetails? getTypeDetailsForType(String type) {
return isar.measureTypesDetails
.where()
.measureTypeEqualTo(type)
.findFirst();
}
}

View file

@ -59,7 +59,8 @@ class BaseApi {
return true;
}
Future<bool> postContent(String table, dynamic body) async {
Future<dynamic> postContent(String table, dynamic body,
[bool autosave = true]) async {
init();
int tableId = tables[table] ?? 0;
@ -70,17 +71,17 @@ class BaseApi {
var response = await RestClient().post('$tableId/', body);
if (response.statusCode != 200) Get.toNamed('/error');
var model = _createModelFromJson(table, jsonDecode(response.body));
if (autosave == true) {
var model = _createModelFromJson(table, jsonDecode(response.body));
var repositoryFunction = repositoryMap[table];
if (repositoryFunction == null) return false;
repositoryFunction(model);
}
var repositoryFunction = repositoryMap[table];
if (repositoryFunction == null) return false;
repositoryFunction(model);
return true;
return response.body;
}
Future<bool> getContent(String table) async {
Future<dynamic> getContent(String table, [bool autosave = true]) async {
init();
int tableId = tables[table] ?? 0;
@ -93,39 +94,26 @@ class BaseApi {
var results = json['results'];
final repositoryMap = {
'area': AreaRepository().put,
'business': BusinessRepository().put,
'funding_program': FundingProgramRepository().put,
'measure_types': MeasureRepository().put,
'measure_general': MeasureGeneralRepository().put,
'measure_details': MeasureDetailsRepository().put,
'measure_types_details': MeasureTypesDetailsRepository().put,
//'measure_combination': MeasureCombinationRepository().put,
//'organism': OrganismRepository().put,
//'location_requirements': LocationRequirementsRepository().put,
//'reference_implementation': ReferenceImplementationRepository().put,
//'tree_type': TreeTypeRepository().put,
//'measure': MeasureRepository().putMeasureGroups,
if (autosave == true) {
final repositoryMap = {
'area': AreaRepository().put,
'business': BusinessRepository().put,
'funding_program': FundingProgramRepository().put,
'measure_types': MeasureRepository().put,
'measure_general': MeasureGeneralRepository().put,
'measure_details': MeasureDetailsRepository().put,
'measure_types_details': MeasureTypesDetailsRepository().put,
};
//'service_provider': ServiceProviderRepository().put,
//'service_provider_contact_person':
// ServiceProviderContactPersonRepository().put,
//'material': MaterialRepository().put,
//'source': SourceRepository().put,
//'experience_report': ExperienceReportRepository().put,
//'approval_requirement': ApprovalRequirementRepository().put
};
var repositoryFunction = repositoryMap[table];
if (repositoryFunction == null) return false;
var repositoryFunction = repositoryMap[table];
if (repositoryFunction == null) return false;
for (var item in results) {
var model = _createModelFromJson(table, item);
repositoryFunction(model);
for (var item in results) {
var model = _createModelFromJson(table, item);
repositoryFunction(model);
}
}
return true;
return results;
}
dynamic _createModelFromJson(String table, Map<String, dynamic> json) {

View file

@ -1,4 +1,5 @@
import 'package:ambito/src/entity/area/area.dart';
import 'package:ambito/src/entity/cart/cart.dart';
import 'package:ambito/src/entity/entities.dart';
import 'package:ambito/src/entity/lists/list_measure.dart';
import 'package:ambito/src/entity/lists/list_measure_single.dart';
@ -13,6 +14,7 @@ import 'package:isar/isar.dart';
import 'package:path_provider/path_provider.dart';
import '../../consts/consts.dart';
import '../../entity/cart/cart_element.dart';
import '../../entity/measure/type/measure_type.dart';
export 'repositories/_repositories.dart';
@ -29,13 +31,14 @@ class AmbitoIsarDB {
AreaSchema,
ApprovalRequirementSchema,
BusinessSchema,
CartSchema,
CartElementSchema,
ExperienceReportSchema,
FundingProgramSchema,
ItemFilterSchema,
ListMeasureSchema,
ListMeasureSingleSchema,
ListMeasureTypeGroupCategorySchema,
LocationRequirementsSchema,
MaterialSchema,
MeasureTypesSchema,
MeasureTypesDetailsSchema,
@ -45,13 +48,6 @@ class AmbitoIsarDB {
MeasureCategorySchema,
MeasureTypeSchema,
MeasureGroupingSchema,
NumberFactsheetSchema,
OrganismSchema,
ReferenceImplementationSchema,
ServiceProviderSchema,
ServiceProviderContactPersonSchema,
SourceSchema,
TreeTypeSchema,
],
directory: dir,
engine: engine,

View file

@ -0,0 +1,30 @@
import 'package:flutter/cupertino.dart';
AmbitoCartNotifier ambitoCartNotifier = AmbitoCartNotifier();
class AmbitoCartNotifier extends ChangeNotifier {
AmbitoCartNotifier();
AmbitoCartNotifier.create(BuildContext context);
int carts = 0;
void addCart() {
carts++;
notifyListeners();
}
void resetCarts() {
carts = 0;
notifyListeners();
}
void removeCart() {
if (carts > 1) {
carts--;
notifyListeners();
} else {
resetCarts();
}
}
}

View file

@ -63,7 +63,7 @@ class CalendarPageYearState extends State<CalendarPageYear> {
? month.substring(0, 3)
: month,
style: theme.titleMedium
?.copyWith(fontWeight: FontWeight.bold, color: Colors.white),
.copyWith(fontWeight: FontWeight.bold, color: Colors.white),
),
),
);

View file

@ -1,166 +1,282 @@
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_repository.dart';
import 'package:ambito/src/entity/measure/types/measure_types.dart';
import 'package:ambito/src/extensions/extensions.dart';
import 'dart:typed_data';
import 'package:ambito/src/entity/cart/cart_datasource.dart';
import 'package:ambito/src/entity/cart/cart_element.dart';
import 'package:ambito/src/entity/cart/cart_repository.dart';
import 'package:ambito/src/entity/measure/complete/measure_complete.dart';
import 'package:ambito/src/entity/measure/general/measure_general.dart';
import 'package:ambito/src/packages/ambito_theme/ambito_theme.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_to_pdf/export_delegate.dart';
import 'package:flutter_to_pdf/export_frame.dart';
import 'package:screen_breakpoints/screen_breakpoints.dart';
import 'package:syncfusion_flutter_calendar/calendar.dart';
import 'package:screenshot/screenshot.dart';
import 'package:syncfusion_flutter_core/theme.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import '../../consts/consts.dart';
import '../../widgets/appbar/ambito_appbar.dart';
import '../../entity/cart/cart.dart';
import '../../entity/measure/general/measure_general_repository.dart';
import '../../widgets/buttons/print_all_button.dart';
import '../../widgets/buttons/print_button.dart';
import '../../widgets/page/base_page.dart';
class CalendarPage extends StatefulWidget {
const CalendarPage({super.key});
class CartPage extends StatefulWidget {
const CartPage({super.key, required this.measure});
final MeasureComplete? measure;
@override
State<StatefulWidget> createState() => CalendarPageState();
State<StatefulWidget> createState() => CartPageState();
}
class CalendarPageState extends State<CalendarPage> {
List<Appointment> appointments = <Appointment>[];
class CartPageState extends State<CartPage> {
List<Cart>? carts;
Widget cartCards = const SizedBox();
final ExportDelegate exportDelegate = ExportDelegate(
ttfFonts: {
'OpenSans': 'fonts/OpenSans-Regular.ttf',
'OpenSans_regular': 'fonts/OpenSans-Regular.ttf',
'OpenSans_500': 'fonts/OpenSans-Bold.ttf',
},
);
List<ItemFilter>? monthFilter = [];
final ScreenshotController screenshotController = ScreenshotController();
Uint8List? _imageFile;
@override
void initState() {
initDataSource();
super.initState();
}
initDataSource() {
monthFilter = ItemFilterRepository().getByType('month')?.toList();
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<MeasureTypes?> currentMeasures =
MeasureRepository().getByIds(itemFilter.ids!);
for (var measure in currentMeasures) {
appointments.add(
Appointment(
startTime: startDate,
endTime: endDate,
isAllDay: true,
subject: measure!.measureType ?? '',
color: actionGroupColors[measure.measureGroup!.value!]!,
),
);
}
}
}
}
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
return Scaffold(
appBar: AmbitoAppbar(
links: const ['dashboard', 'massnahmen'],
breakpoint: Breakpoint.fromContext(context),
theme: theme,
),
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,
carts = CartRepository().getMyCarts();
return BasePage().getPage(
context,
BreakpointBuilder(
builder: (
context,
breakpoint,
configuration,
) {
return SingleChildScrollView(
child: Center(
child: Screenshot(
controller: screenshotController,
child: SizedBox(
width: Breakpoint.fromContext(context).width,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
theme.verticalSpacer,
Text(
'Warenkorb',
style: theme.headlineLarge,
textAlign: TextAlign.start,
),
theme.verticalSpacerSmall,
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: [
const Spacer(),
PrintAllButton(
onPressed: () async {
screenshotController.capture();
},
),
],
),
theme.verticalSpacerSmall,
buildCards(theme, carts),
],
),
),
),
),
),
),
);
},
),
);
}
_AppointmentDataSource _getCalendarDataSource() {
List<Appointment> appointments = <Appointment>[];
appointments.add(Appointment(
startTime: DateTime.now(),
endTime: DateTime.now().add(const Duration(minutes: 10)),
subject: 'Meeting',
isAllDay: true,
color: Colors.blue,
startTimeZone: '',
endTimeZone: '',
));
Future<void> saveFile(document, String name) async {}
return _AppointmentDataSource(appointments);
Widget buildCards(AmbitoTheme theme, List<Cart>? carts) {
List<Widget> children = [];
if (carts != null) {
int counter = 0;
for (final cart in carts) {
final measure = MeasureGeneralRepository().getByName(cart.name!);
final elements = CartRepository().getElementsByCartId(cart.id);
double sum = 0;
for (final element in elements) {
sum = sum +
((int.tryParse(element.amount ?? '1') ?? 1) *
(double.tryParse(element.price ?? '0') ?? 0));
}
final card = ExportFrame(
exportDelegate: exportDelegate,
frameId: 'cart${cart.id}',
child: SizedBox(
width: 1152,
child: Card(
elevation: 0,
color: theme.currentColorScheme.tertiary,
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
cart.name!,
style: theme.labelLarge.copyWith(
color: theme.currentColorScheme.primary),
),
const Spacer(),
SizedBox(
height: 40,
width: 200,
child: ClipRRect(
borderRadius: const BorderRadius.all(
Radius.circular(10),
),
child: measure?.getFullImage() ??
Image.asset('assets/images/logo_trans.png'),
),
),
],
),
theme.verticalSpacerSmall,
gridWidget(elements ?? []),
theme.verticalSpacer,
Row(
children: [
Text(
'Richtpreis ca. ${sum.toStringAsFixed(2)}',
style: theme.labelMedium
.copyWith(fontWeight: FontWeight.bold),
),
Spacer(),
PrintButton(
onPressed: () async {
final pdf = await exportDelegate
.exportToPdfDocument('cart${cart.id}');
await saveFile(pdf, '${cart.id}.pdf');
},
),
],
)
],
),
),
),
),
);
children.add(card);
children.add(theme.verticalSpacerMax);
counter++;
}
}
return ExportFrame(
frameId: 'completeCart',
exportDelegate: exportDelegate,
child: Column(
children: children,
),
);
}
Widget gridWidget(List<CartElement> cartElements) {
final AmbitoTheme theme = getTheme(context);
return SfDataGridTheme(
data: SfDataGridThemeData(
headerColor: theme.currentColorScheme.primaryContainer,
sortIcon: Icon(
Icons.keyboard_arrow_down,
color: theme.currentColorScheme.primary,
),
),
child: SfDataGrid(
allowSorting: true,
source: CartDataSource(cartElements: cartElements, context: context),
columnWidthMode: ColumnWidthMode.fill,
columns: [
GridColumn(
columnName: 'name',
label: Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.centerLeft,
child: Text(
'Material',
overflow: TextOverflow.ellipsis,
style: theme.bodyMedium.copyWith(
color: theme.currentColorScheme.primary,
),
),
),
),
GridColumn(
columnName: 'amount',
maximumWidth: 150,
label: Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.centerLeft,
child: Text(
'Menge',
overflow: TextOverflow.ellipsis,
style: theme.bodyMedium.copyWith(
color: theme.currentColorScheme.primary,
),
),
),
),
GridColumn(
columnName: 'provider',
maximumWidth: 200,
allowSorting: false,
label: Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.centerLeft,
child: Text(
'Anbieter',
overflow: TextOverflow.ellipsis,
style: theme.bodyMedium.copyWith(
color: theme.currentColorScheme.primary,
),
),
),
),
GridColumn(
columnName: 'price',
allowSorting: true,
maximumWidth: 250,
label: Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.centerLeft,
child: Text(
'Richtpreis',
overflow: TextOverflow.ellipsis,
style: theme.bodyMedium.copyWith(
color: theme.currentColorScheme.primary,
),
),
),
),
],
),
);
}
}
class _AppointmentDataSource extends CalendarDataSource {
_AppointmentDataSource(List<Appointment> source) {
appointments = source;
}
}
/*class ActionDataSource extends CalendarDataSource {
ActionDataSource(List<Action> source) {
appointments = source;
}
@override
DateTime getStartTime(int index) {
return appointments![index].from;
}
@override
DateTime getEndTime(int index) {
return appointments![index].to;
}
@override
bool isAllDay(int index) {
return appointments![index].isAllDay;
}
@override
String getSubject(int index) {
return appointments![index].eventName;
}
@override
String getStartTimeZone(int index) {
return appointments![index].startTimeZone;
}
@override
String getEndTimeZone(int index) {
return appointments![index].endTimeZone;
}
@override
Color getColor(int index) {
return appointments![index].background;
}
}
class Action {
Action(
{this.eventName = '',
required this.from,
required this.to,
required this.background,
this.isAllDay = false});
String eventName;
DateTime from;
DateTime to;
Color background;
bool isAllDay;
}*/

View file

@ -37,6 +37,7 @@ class DashboardAreasPageState extends State<DashboardAreasPage> {
final api = GoogleGeocodingApi(googleApiKey, isLogged: false);
Set<Marker> markers = {};
Set<Polygon> polygons = {};
Set<Polyline> polylines = {};
List<Area> areas = [];
Business? business;
@ -87,6 +88,7 @@ class DashboardAreasPageState extends State<DashboardAreasPage> {
mapWidget = MapWidget(
markers: markers,
polygons: polygons,
polylines: polylines,
);
});
});
@ -112,6 +114,7 @@ class DashboardAreasPageState extends State<DashboardAreasPage> {
padding: context.breakpoint.padding,
child: SizedBox(
width: 1152,
height: 1152,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -521,7 +524,9 @@ class DashboardAreasPageState extends State<DashboardAreasPage> {
],
),
theme.verticalSpacer,
(display == 0) ? mapWidget : gridWidget(areas),
Expanded(
child: (display == 0) ? mapWidget : gridWidget(areas),
),
theme.verticalSpacer,
],
),

View file

@ -70,6 +70,7 @@ class DashboardPageState extends State<DashboardPage> {
mapWidget = MapWidget(
markers: markers,
polygons: {},
polylines: {},
);
});
});

View file

@ -1,16 +1,4 @@
export 'advisor_card.dart';
export 'background_card.dart';
export 'biodiverisity_card.dart';
export 'creation_card.dart';
export 'description_card.dart';
export 'factsheet_card.dart';
export 'funding_card.dart';
export 'implementation_card.dart';
export 'location_card.dart';
export 'maintenance_card.dart';
export 'material_card.dart';
export 'presets_card.dart';
export 'review_card.dart';
export 'size_card.dart';
export 'sources_card.dart';
export 'toc_card.dart';

View file

@ -1,8 +1,8 @@
import 'package:ambito/src/entity/measure/complete/measure_complete.dart';
import 'package:ambito/src/extensions/extensions.dart';
import 'package:expansion_tile_card/expansion_tile_card.dart';
import 'package:flutter/material.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '../measure_detail_page.dart';
@ -13,7 +13,7 @@ class MainCard extends StatelessWidget {
required this.title,
required this.content});
final MeasureTypes massnahme;
final MeasureComplete massnahme;
final String title;
final Widget content;

View file

@ -1,7 +1,7 @@
import 'package:ambito/src/entity/measure/complete/measure_complete.dart';
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
class SideBarCard extends StatelessWidget {
@ -11,7 +11,7 @@ class SideBarCard extends StatelessWidget {
required this.title,
required this.content});
final MeasureTypes massnahme;
final MeasureComplete massnahme;
final String title;
final List<Widget> content;

View file

@ -1,15 +1,13 @@
import 'package:ambito/src/entity/measure/complete/measure_complete.dart';
import 'package:flutter/material.dart';
import 'package:flutter_linkify/flutter_linkify.dart';
import 'package:linkify/linkify.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '_sidebar_card.dart';
class AdvisorCard extends StatelessWidget {
const AdvisorCard({super.key, required this.massnahme});
final MeasureTypes massnahme;
final MeasureComplete massnahme;
@override
Widget build(BuildContext context) {
@ -20,24 +18,10 @@ class AdvisorCard extends StatelessWidget {
title: 'page.actionDetailPage.advisor.title',
content: [
Text(
'Max Mustermann',
'-',
style: theme.currentThemeData.textTheme.bodyLarge
?.copyWith(fontWeight: FontWeight.bold),
),
Linkify(
text: 'EMail: max@mustermann.de',
style: theme.currentThemeData.textTheme.bodyLarge,
linkifiers: const [
EmailLinkifier(),
],
),
Linkify(
text: 'Tel: +4917666554433',
style: theme.currentThemeData.textTheme.bodyLarge,
linkifiers: const [
PhoneNumberLinkifier(),
],
),
],
);
}

View file

@ -1,30 +0,0 @@
import 'package:flutter/material.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '_main_card.dart';
class BackgroundCard extends StatelessWidget {
const BackgroundCard({super.key, required this.massnahme});
final MeasureTypes massnahme;
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
return MainCard(
massnahme: massnahme,
title: 'page.actionDetailPage.background.target',
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
massnahme.applyLocation.toString(),
style: theme.currentThemeData.textTheme.bodyLarge,
),
],
),
);
}
}

View file

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

View file

@ -1,133 +0,0 @@
import 'package:ambito/src/consts/consts.dart';
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '_main_card.dart';
class CreationCard extends StatelessWidget {
const CreationCard({super.key, required this.massnahme});
final MeasureTypes massnahme;
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
Chip buildChip(String label, [active = false]) {
return Chip(
labelPadding: EdgeInsets.zero,
backgroundColor: active
? theme.currentColorScheme.secondary
: theme.currentColorScheme.outline.withOpacity(.1),
label: Text(
label,
style: theme.currentThemeData.textTheme.bodyLarge?.copyWith(
color: active
? theme.currentColorScheme.onSecondary
: theme.currentColorScheme.onSurface,
),
),
);
}
List<Chip> buildChips(List<String?>? items) =>
months.map((item) => buildChip(item, items?.contains(item))).toList();
List<Widget> buildTools(List<String?>? tools) =>
tools?.where((item) => item?.isNotEmpty ?? false).map((item) {
return Row(
children: [
const Icon(Icons.fiber_manual_record, size: 8),
theme.horizontalSpacerSmall,
Expanded(
child: Text(
item!,
style: theme.currentThemeData.textTheme.bodyLarge,
),
),
],
);
}).toList() ??
[];
Widget buildSection({
required String titleKey,
required List<Widget> children,
}) {
if (children.isEmpty) return const SizedBox.shrink();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Divider(),
Text(
context.translate(titleKey),
style: theme.currentThemeData.textTheme.labelMedium,
),
...children,
],
);
}
Widget buildTextSection(String? text, String titleKey) {
if (text == null || text.isEmpty) return const SizedBox.shrink();
return buildSection(
titleKey: titleKey,
children: [
Text(
text,
style: theme.currentThemeData.textTheme.bodyLarge,
),
],
);
}
final tfChips =
buildChips(massnahme.applyTimeFrame?.map((e) => e.value).toList());
final creationTools =
buildTools(massnahme.applyTools?.map((e) => e.value).toList());
return MainCard(
massnahme: massnahme,
title: 'page.actionDetailPage.creation.title',
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (tfChips.isNotEmpty)
buildSection(
titleKey: 'page.actionDetailPage.creation.timeFrame',
children: [
Wrap(
runSpacing: 8,
spacing: 8,
children: tfChips,
),
],
),
buildTextSection(
massnahme.applyTimeFrameAdditional,
'page.actionDetailPage.creation.additional',
),
buildTextSection(
massnahme.applyReminder,
'page.actionDetailPage.creation.reminders',
),
if (creationTools.isNotEmpty)
buildSection(
titleKey: 'page.actionDetailPage.creation.tools',
children: creationTools,
),
buildTextSection(
massnahme.applyWorkSteps,
'page.actionDetailPage.creation.steps',
),
buildTextSection(
massnahme.applyTips,
'page.actionDetailPage.creation.tips',
),
],
),
);
}
}

View file

@ -1,26 +0,0 @@
import 'package:flutter/material.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '_main_card.dart';
class DescriptionCard extends StatelessWidget {
const DescriptionCard({super.key, required this.massnahme});
final MeasureTypes massnahme;
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
return MainCard(
massnahme: massnahme,
title: 'page.actionDetailPage.description.title',
content: Text(
massnahme.description ?? '',
style: theme.currentThemeData.textTheme.bodyLarge,
textAlign: TextAlign.left,
),
);
}
}

View file

@ -1,14 +1,14 @@
import 'package:ambito/src/widgets/buttons/text_button.dart';
import 'package:flutter/material.dart';
import '../../../../entity/entities.dart';
import '../../../../entity/measure/complete/measure_complete.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '_sidebar_card.dart';
class FactsheetCard extends StatelessWidget {
const FactsheetCard({super.key, required this.massnahme});
final MeasureTypes massnahme;
final MeasureComplete massnahme;
@override
Widget build(BuildContext context) {

View file

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

View file

@ -1,52 +0,0 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '_main_card.dart';
class ImplementationCard extends StatelessWidget {
const ImplementationCard({super.key, required this.massnahme});
final MeasureTypes massnahme;
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
return MainCard(
massnahme: massnahme,
title: 'page.actionDetailPage.implementation.title',
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (massnahme.applyCosts != null && massnahme.applyCosts != '')
Text(
context.translate('page.actionDetailPage.implementation.costs'),
style: theme.currentThemeData.textTheme.labelMedium,
),
if (massnahme.applyCosts != null && massnahme.applyCosts != '')
Text(
massnahme.applyCosts.toString(),
style: theme.currentThemeData.textTheme.bodyLarge,
),
if (massnahme.applyCosts != null &&
massnahme.applyCosts != '' &&
massnahme.applyTime != null &&
massnahme.applyTime != '')
const Divider(),
if (massnahme.applyTime != null && massnahme.applyTime != '')
Text(
context.translate('page.actionDetailPage.implementation.time'),
style: theme.currentThemeData.textTheme.labelMedium,
),
if (massnahme.applyTime != null && massnahme.applyTime != '')
Text(
massnahme.applyTime.toString(),
style: theme.currentThemeData.textTheme.bodyLarge,
),
],
),
);
}
}

View file

@ -1,25 +0,0 @@
import 'package:flutter/material.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '_main_card.dart';
class LocationCard extends StatelessWidget {
const LocationCard({super.key, required this.massnahme});
final MeasureTypes massnahme;
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
return MainCard(
massnahme: massnahme,
title: 'page.actionDetailPage.location.title',
content: Text(
massnahme.applyLocation.toString(),
style: theme.currentThemeData.textTheme.bodyLarge,
),
);
}
}

View file

@ -0,0 +1,53 @@
import 'package:expansion_tile_card/expansion_tile_card.dart';
import 'package:flutter/cupertino.dart';
import '../../../../../packages/ambito_theme/ambito_theme.dart';
import '../../measure_detail_page.dart';
class CombinedCard extends StatelessWidget {
const CombinedCard({
super.key,
required this.title,
required this.elements,
});
final String title;
final List<Widget>? elements;
@override
Widget build(BuildContext context) {
if (elements == null) {
return const SizedBox();
}
final AmbitoTheme theme = getTheme(context);
globalKeys.putIfAbsent(title, () => GlobalKey<ExpansionTileCardState>());
return ExpansionTileCard(
key: globalKeys[title],
initiallyExpanded: true,
contentPadding: const EdgeInsets.only(left: 16),
elevation: 0,
expandedTextColor: theme.currentColorScheme.outline,
baseColor: theme.currentColorScheme.outline.withOpacity(.1),
expandedColor: theme.currentColorScheme.outline.withOpacity(.1),
title: Text(
title,
style: theme.currentThemeData.textTheme.labelMedium
?.copyWith(fontWeight: FontWeight.bold),
),
children: [
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20),
child: Column(
children: elements!,
),
),
),
],
);
}
}

View file

@ -0,0 +1,67 @@
import 'package:expansion_tile_card/expansion_tile_card.dart';
import 'package:flutter/material.dart';
import 'package:horizontal_list/horizontal_list.dart';
import '../../../../../packages/ambito_theme/ambito_theme.dart';
import '../../measure_detail_page.dart';
class GalleryCard extends StatelessWidget {
const GalleryCard({
super.key,
required this.title,
required this.widgets,
});
final String title;
final List<Widget>? widgets;
@override
Widget build(BuildContext context) {
if (widgets == null) {
return const SizedBox();
}
final AmbitoTheme theme = getTheme(context);
globalKeys.putIfAbsent(title, () => GlobalKey<ExpansionTileCardState>());
return ExpansionTileCard(
key: globalKeys[title],
initiallyExpanded: true,
contentPadding: const EdgeInsets.only(left: 16),
elevation: 0,
expandedTextColor: theme.currentColorScheme.outline,
baseColor: theme.currentColorScheme.outline.withOpacity(.1),
expandedColor: theme.currentColorScheme.outline.withOpacity(.1),
title: Text(
title,
style: theme.currentThemeData.textTheme.labelMedium
?.copyWith(fontWeight: FontWeight.bold),
),
children: [
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20),
child: HorizontalListView(
width: double.maxFinite, //Width of widget
height: 150, //Height of widget
list: widgets!, //List of widget
iconNext:
const Icon(Icons.arrow_forward_ios), // Icon for button next
iconPrevious:
const Icon(Icons.arrow_back_ios), // Icon for button previous
curveAnimation:
Curves.fastLinearToSlowEaseIn, //Curve for animation
durationAnimation:
const Duration(milliseconds: 300), //Duration of animation
enableManualScroll: true, //Enable manual scroll
onNextPressed: () {},
onPreviousPressed: () {},
),
),
),
],
);
}
}

View file

@ -0,0 +1,54 @@
import 'package:expansion_tile_card/expansion_tile_card.dart';
import 'package:flutter/cupertino.dart';
import '../../../../../packages/ambito_theme/ambito_theme.dart';
import '../../measure_detail_page.dart';
class SimpleTextCard extends StatelessWidget {
const SimpleTextCard({
super.key,
required this.title,
required this.text,
});
final String title;
final String? text;
@override
Widget build(BuildContext context) {
if (text == null) {
return const SizedBox();
}
final AmbitoTheme theme = getTheme(context);
globalKeys.putIfAbsent(title, () => GlobalKey<ExpansionTileCardState>());
return ExpansionTileCard(
key: globalKeys[title],
initiallyExpanded: true,
contentPadding: const EdgeInsets.only(left: 16),
elevation: 0,
expandedTextColor: theme.currentColorScheme.outline,
baseColor: theme.currentColorScheme.outline.withOpacity(.1),
expandedColor: theme.currentColorScheme.outline.withOpacity(.1),
title: Text(
title,
style: theme.currentThemeData.textTheme.labelMedium
?.copyWith(fontWeight: FontWeight.bold),
),
children: [
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20),
child: Text(
text!,
style: theme.bodyMedium,
),
),
),
],
);
}
}

View file

@ -0,0 +1,68 @@
import 'package:flutter/material.dart';
import '../../../../../consts/consts.dart';
import '../../../../../packages/ambito_theme/ambito_theme.dart';
class SublevelMonthsCard extends StatelessWidget {
const SublevelMonthsCard({
super.key,
required this.title,
required this.items,
});
final String title;
final List<String>? items;
@override
Widget build(BuildContext context) {
if (items == null) {
return const SizedBox();
}
final AmbitoTheme theme = getTheme(context);
Chip buildChip(String label, [active = false]) {
return Chip(
labelPadding: EdgeInsets.zero,
backgroundColor: active
? theme.currentColorScheme.secondary
: theme.currentColorScheme.outline.withOpacity(.1),
label: Text(
label,
style: theme.currentThemeData.textTheme.bodyLarge?.copyWith(
color: active
? theme.currentColorScheme.onSecondary
: theme.currentColorScheme.onSurface,
),
),
);
}
List<Chip> buildChips(List<String?>? items) =>
months.map((item) => buildChip(item, items?.contains(item))).toList();
final chips = buildChips(items);
return Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(right: 20, bottom: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: theme.currentThemeData.textTheme.labelMedium,
),
theme.verticalSpacerSmall,
Wrap(
runSpacing: 8,
spacing: 8,
children: chips,
),
],
),
),
);
}
}

View file

@ -0,0 +1,48 @@
import 'package:expansion_tile_card/expansion_tile_card.dart';
import 'package:flutter/cupertino.dart';
import '../../../../../packages/ambito_theme/ambito_theme.dart';
import '../../measure_detail_page.dart';
class SublevelTextCard extends StatelessWidget {
const SublevelTextCard({
super.key,
required this.title,
required this.text,
});
final String title;
final String? text;
@override
Widget build(BuildContext context) {
if (text == null) {
return const SizedBox();
}
final AmbitoTheme theme = getTheme(context);
globalKeys.putIfAbsent(title, () => GlobalKey<ExpansionTileCardState>());
return Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(right: 20, bottom: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: theme.currentThemeData.textTheme.labelMedium,
),
theme.verticalSpacerSmall,
Text(
text!,
style: theme.bodyMedium,
),
],
),
),
);
}
}

View file

@ -0,0 +1,66 @@
import 'package:expansion_tile_card/expansion_tile_card.dart';
import 'package:flutter/material.dart';
import '../../../../../packages/ambito_theme/ambito_theme.dart';
import '../../measure_detail_page.dart';
class SublevelUnorderedListCard extends StatelessWidget {
const SublevelUnorderedListCard({
super.key,
required this.title,
required this.text,
});
final String title;
final List<String>? text;
@override
Widget build(BuildContext context) {
if (text == null) {
return const SizedBox();
}
final AmbitoTheme theme = getTheme(context);
globalKeys.putIfAbsent(title, () => GlobalKey<ExpansionTileCardState>());
return Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(right: 20, bottom: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
title,
style: theme.currentThemeData.textTheme.labelMedium,
),
...text!
.map(
(item) => Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Align(
alignment: Alignment.center,
child: Icon(Icons.circle, size: 4),
),
theme.horizontalSpacerSmall,
Expanded(
child: Text(
item,
softWrap: true,
maxLines: 2,
style: theme.bodyMedium,
),
),
],
),
)
.toList(),
],
),
),
);
}
}

View file

@ -0,0 +1,70 @@
import 'package:expansion_tile_card/expansion_tile_card.dart';
import 'package:flutter/material.dart';
import '../../../../../packages/ambito_theme/ambito_theme.dart';
import '../../measure_detail_page.dart';
class UnorderedListCard extends StatelessWidget {
const UnorderedListCard({
super.key,
required this.title,
required this.text,
});
final String title;
final List<String>? text;
@override
Widget build(BuildContext context) {
if (text == null) {
return const SizedBox();
}
final AmbitoTheme theme = getTheme(context);
globalKeys.putIfAbsent(title, () => GlobalKey<ExpansionTileCardState>());
return ExpansionTileCard(
key: globalKeys[title],
initiallyExpanded: true,
contentPadding: const EdgeInsets.only(left: 16),
elevation: 0,
expandedTextColor: theme.currentColorScheme.outline,
baseColor: theme.currentColorScheme.outline.withOpacity(.1),
expandedColor: theme.currentColorScheme.outline.withOpacity(.1),
title: Text(
title,
style: theme.currentThemeData.textTheme.labelMedium
?.copyWith(fontWeight: FontWeight.bold),
),
children: [
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20),
child: Column(
children: text!
.map(
(item) => Row(
children: [
const Icon(Icons.circle, size: 4),
theme.horizontalSpacerSmall,
Expanded(
child: Text(
item,
softWrap: true,
maxLines: 2,
style: theme.bodyMedium,
),
),
],
),
)
.toList(),
),
),
),
],
);
}
}

View file

@ -1,144 +0,0 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '_main_card.dart';
class MaintenanceCard extends StatelessWidget {
const MaintenanceCard({super.key, required this.massnahme});
final MeasureTypes massnahme;
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
Chip buildChip(String label) {
return Chip(
labelPadding: EdgeInsets.zero,
backgroundColor: theme.currentColorScheme.secondary,
label: Text(
label,
style: theme.currentThemeData.textTheme.bodyLarge
?.copyWith(color: theme.currentColorScheme.onSecondary),
),
);
}
List<Chip> buildChips(List<String?>? items) =>
items
?.where((item) => item?.isNotEmpty ?? false)
.map((item) => buildChip(item!))
.toList() ??
[];
List<Widget> buildTools(List<String?>? tools) =>
tools?.where((item) => item?.isNotEmpty ?? false).map((item) {
return Row(
children: [
const Icon(Icons.fiber_manual_record, size: 8),
theme.horizontalSpacerSmall,
Expanded(
child: Text(
item!,
style: theme.currentThemeData.textTheme.bodyLarge,
),
),
],
);
}).toList() ??
[];
Widget buildSection({
required String titleKey,
required List<Widget> children,
}) {
if (children.isEmpty) return const SizedBox.shrink();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Divider(),
Text(
context.translate(titleKey),
style: theme.currentThemeData.textTheme.labelMedium,
),
...children,
],
);
}
Widget buildTextSection(String? text, String titleKey) {
if (text == null || text.isEmpty) return const SizedBox.shrink();
return buildSection(
titleKey: titleKey,
children: [
Text(
text,
style: theme.currentThemeData.textTheme.bodyLarge,
),
],
);
}
final tfChips = buildChips(
massnahme.maintenanceTimeFrame?.map((e) => e.value).toList());
final tfMaintenance = buildChips(
massnahme.maintenanceFrequency?.map((e) => e.value).toList());
final creationTools =
buildTools(massnahme.maintenanceMaterial?.map((e) => e.value).toList());
return MainCard(
massnahme: massnahme,
title: 'page.actionDetailPage.maintenance.title',
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (tfChips.isNotEmpty)
buildSection(
titleKey: 'page.actionDetailPage.maintenance.time',
children: [
Wrap(
runSpacing: 8,
spacing: 8,
children: tfChips,
),
],
),
buildTextSection(
massnahme.maintenanceTimeFrameAdditional,
'page.actionDetailPage.maintenance.additional_time',
),
if (tfMaintenance.isNotEmpty)
buildSection(
titleKey: 'page.actionDetailPage.maintenance.frequency',
children: [
Wrap(
runSpacing: 8,
spacing: 8,
children: tfMaintenance,
),
],
),
buildTextSection(
massnahme.maintenanceFrequencyAdditional,
'page.actionDetailPage.maintenance.additional_frequency',
),
if (creationTools.isNotEmpty)
buildSection(
titleKey: 'page.actionDetailPage.maintenance.tools',
children: creationTools,
),
buildTextSection(
massnahme.maintenanceWorkSteps,
'page.actionDetailPage.maintenance.steps',
),
buildTextSection(
massnahme.maintenanceTips,
'page.actionDetailPage.maintenance.tips',
),
],
),
);
}
}

View file

@ -1,15 +1,26 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:ambito/src/widgets/buttons/text_button.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
import '../../../../entity/entities.dart';
import 'package:ambito/src/entity/_general/id_value/id_value.dart';
import 'package:ambito/src/entity/cart/cart.dart';
import 'package:ambito/src/entity/cart/cart_element.dart';
import 'package:ambito/src/extensions/extensions.dart';
import 'package:ambito/src/packages/ambito_api/base_api.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../../consts/consts.dart';
import '../../../../entity/measure/complete/measure_complete.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '../../../../widgets/buttons/text_button.dart';
import '../../../cart/cart_page.dart';
import '_sidebar_card.dart';
class MaterialCard extends StatelessWidget {
const MaterialCard({super.key, required this.massnahme});
MaterialCard({super.key, required this.massnahme});
final MeasureTypes massnahme;
final MeasureComplete massnahme;
final List<CartElement> elements = [];
@override
Widget build(BuildContext context) {
@ -21,17 +32,62 @@ class MaterialCard extends StatelessWidget {
content: [
_getSortedMaterials(context),
theme.verticalSpacer,
if (massnahme.applyMaterialCosts != null)
Text(context
.translate('page.actionDetailPage.material.suggested_price') +
massnahme.applyMaterialCosts +
''),
theme.verticalSpacerSmall,
if (massnahme.costs != null)
Text(
context.translate(
'page.actionDetailPage.material.suggested_price') +
massnahme.costs +
'',
style: theme.bodyMedium.copyWith(fontWeight: FontWeight.bold),
),
theme.verticalSpacer,
Align(
alignment: Alignment.center,
child: TextButtonElement(
title: 'page.actionDetailPage.material.add_to_basket',
onPressed: () {},
onPressed: () async {
prefs.setBool('extended_json', false).then((_) async {
var cartId = isar.carts.autoIncrement();
Cart newCart = Cart()
..id = cartId
..name = massnahme.name
..business = [
(IdValue()..id = (prefs.getInt('currrentUser') ?? 100))
];
final cart = await BaseApi()
.postContent('cart', newCart.toJson(), false);
newCart = Cart.fromJson(jsonDecode(cart));
IdValue cartIdv = (IdValue()..id = newCart.id);
List<CartElement> elements = [];
final cartElement = CartElement()
..id = isar.cartElements.autoIncrement()
..cart = [cartIdv]
..name = massnahme.name
..amount = '1'
..priceType = massnahme.costsUnit
..provider = <IdValue>[]
..price = massnahme.costs ?? '0.0';
await BaseApi()
.postContent('cart_elements', cartElement.toJson(), false);
elements.add(cartElement);
for (var item in massnahme.applyMaterials ?? []) {
final addtionalElement = CartElement()
..id = isar.cartElements.autoIncrement()
..cart = [cartIdv]
..name = item
..amount = '1'
..priceType = 'Stk'
..provider = <IdValue>[]
..price = '0.0';
await BaseApi().postContent(
'cart_elements', addtionalElement.toJson(), false);
elements.add(addtionalElement);
}
Get.to(() => CartPage(measure: massnahme));
});
},
),
)
],
@ -41,15 +97,16 @@ class MaterialCard extends StatelessWidget {
_getSortedMaterials(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
List<String> items = [];
if (massnahme.applyMaterial != null) {
for (IdValueColor ivc in massnahme.applyMaterial!) {
items.add(ivc.value!);
}
}
List<String> items = massnahme.applyMaterials ?? [];
items.sort((a, b) => a.toString().compareTo(b.toString()));
List<Widget> tiles = [];
for (String item in items) {
elements.add(
CartElement()
..name = item
..amount = '1'
..price = massnahme.costs ?? '0.0',
);
tiles.add(
Row(
children: [

View file

@ -1,25 +0,0 @@
import 'package:flutter/material.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '_main_card.dart';
class PresetsCard extends StatelessWidget {
const PresetsCard({super.key, required this.massnahme});
final MeasureTypes massnahme;
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
return MainCard(
massnahme: massnahme,
title: 'page.actionDetailPage.presets.title',
content: Text(
massnahme.requirementTips.toString(),
style: theme.currentThemeData.textTheme.bodyLarge,
),
);
}
}

View file

@ -1,60 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_rating/flutter_rating.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '_sidebar_card.dart';
class ReviewCard extends StatelessWidget {
const ReviewCard({super.key, required this.massnahme});
final MeasureTypes massnahme;
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
return SideBarCard(
massnahme: massnahme,
title: 'page.actionDetailPage.review.title',
content: [
StarRating(
mainAxisAlignment: MainAxisAlignment.start,
size: 24,
allowHalfRating: true,
rating: 3.5,
filledIcon: Icons.star,
halfFilledIcon: Icons.star_half,
emptyIcon: Icons.star_border_outlined,
color:
Colors.yellow.shade800, // Color for filled and half-filled icons
borderColor: Colors.yellow.shade800, // Color for empty icons
onRatingChanged: null,
),
theme.verticalSpacerSmall,
Text(
'21 Bewertungen',
style: theme.bodySmall,
),
theme.verticalSpacer,
Text(
'"Sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam"',
style: theme.bodyLarge.copyWith(fontWeight: FontWeight.bold),
),
Text(
'Maxi Mustermann',
style: theme.bodyLarge.copyWith(fontWeight: FontWeight.bold),
),
theme.verticalSpacer,
Text(
'"Lorem ipsum dolor sit amet, consetetur sadipscing elitr"',
style: theme.bodyLarge.copyWith(fontWeight: FontWeight.bold),
),
Text(
'Peter Parker',
style: theme.bodyLarge.copyWith(fontWeight: FontWeight.bold),
),
],
);
}
}

View file

@ -1,25 +0,0 @@
import 'package:flutter/material.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '_main_card.dart';
class SizeCard extends StatelessWidget {
const SizeCard({super.key, required this.massnahme});
final MeasureTypes massnahme;
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
return MainCard(
massnahme: massnahme,
title: 'page.actionDetailPage.size.title',
content: Text(
massnahme.applySize.toString(),
style: theme.currentThemeData.textTheme.bodyLarge,
),
);
}
}

View file

@ -1,26 +0,0 @@
import 'package:flutter/material.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '_main_card.dart';
class SourcesCard extends StatelessWidget {
const SourcesCard({super.key, required this.massnahme});
final MeasureTypes massnahme;
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
return MainCard(
massnahme: massnahme,
title: 'page.actionDetailPage.sources.title',
content: Text(
massnahme.sources ?? '',
style: theme.currentThemeData.textTheme.bodyLarge,
textAlign: TextAlign.left,
),
);
}
}

View file

@ -1,15 +1,20 @@
import 'package:ambito/src/entity/measure/complete/measure_complete.dart';
import 'package:flutter/material.dart';
import 'package:super_bullet_list/bullet_list.dart';
import '../../../../entity/entities.dart';
import '../../../../packages/ambito_theme/ambito_theme.dart';
import '_sidebar_card.dart';
class TocCard extends StatelessWidget {
const TocCard({super.key, required this.massnahme, required this.items});
const TocCard({
super.key,
required this.massnahme,
required this.items,
required this.scrollController,
});
final MeasureTypes massnahme;
final MeasureComplete massnahme;
final List<String> items;
final ScrollController scrollController;
@override
Widget build(BuildContext context) {
@ -18,20 +23,25 @@ class TocCard extends StatelessWidget {
return SideBarCard(
massnahme: massnahme,
title: 'page.actionDetailPage.toc.title',
content: [
SuperBulletList(
gap: 2,
crossAxisMargin: 2,
iconSize: 24,
isOrdered: true,
items: items
.map((item) => Text(
item,
style: theme.bodyLarge,
))
.toList(),
),
],
content: items
.map((item) => Row(
children: [
SizedBox(width: 30, child:
Text(
'${items.indexOf(item) + 1}. ',
style: theme.bodyMedium,
),),
Expanded(
child: InkWell(
child: Text(
item,
style: theme.bodyMedium,
),
),
)
],
))
.toList(),
);
}
}

View file

@ -1,6 +1,16 @@
import 'package:ambito/src/entity/entities.dart';
import 'package:ambito/src/entity/enums/enum_details_type.dart';
import 'package:ambito/src/entity/measure/details/measure_details.dart';
import 'package:ambito/src/entity/measure/details/measure_details_repository.dart';
import 'package:ambito/src/entity/measure/measure_repository.dart';
import 'package:ambito/src/entity/measure/types_details/measure_types_details.dart';
import 'package:ambito/src/entity/measure/types_details/measure_types_details_repository.dart';
import 'package:ambito/src/extensions/extensions.dart';
import 'package:ambito/src/pages/measure/detail/cards/main/combined_card.dart';
import 'package:ambito/src/pages/measure/detail/cards/main/gallery_card.dart';
import 'package:ambito/src/pages/measure/detail/cards/main/simple_text_card.dart';
import 'package:ambito/src/pages/measure/detail/cards/main/sublevel_months_card.dart';
import 'package:ambito/src/pages/measure/detail/cards/main/sublevel_text_card.dart';
import 'package:ambito/src/pages/measure/detail/cards/main/unordered_list_card.dart';
import 'package:animated_segmented_tab_control/animated_segmented_tab_control.dart';
import 'package:expansion_tile_card/expansion_tile_card.dart';
import 'package:flutter/material.dart';
@ -11,6 +21,7 @@ import 'package:screen_breakpoints/screen_breakpoints.dart';
import '../../../config/config.dart';
import '../../../consts/consts.dart';
import '../../../entity/measure/complete/measure_complete.dart';
import '../../../packages/ambito_theme/ambito_theme.dart';
import '../../../widgets/appbar/ambito_appbar.dart';
import '../../ambito_page.dart';
@ -19,10 +30,7 @@ import 'cards/_cards.dart';
final Map<String, GlobalKey<ExpansionTileCardState>> globalKeys = {};
class MeasureDetailPage extends AmbitoPage {
const MeasureDetailPage({required this.id, required this.type, super.key});
final EnumDetailsType type;
final int id;
const MeasureDetailPage({super.key});
@override
final String path = 'massnahme';
@ -35,33 +43,73 @@ class MeasureDetailPage extends AmbitoPage {
class MeasureDetailPageState extends State<MeasureDetailPage> {
final ScrollController scrollController = ScrollController();
final ScrollController itemScrollController = ScrollController();
bool showBackToTopButton = false;
final Map<String, GlobalKey<ExpansionTileCardState>> expansionKeys = {};
MeasureGeneral? measureGeneral;
MeasureDetails? measureDetails;
MeasureTypes? measureType;
MeasureTypesDetails? measureTypesDetails;
List<Widget> contentItems = [];
final Set<String> visibleItems = {};
bool collapsed = false;
int? id;
MeasureComplete? measure;
@override
void initState() {
super.initState();
//massnahme = MeasureRepository().get(int.parse(id)) as MeasureTypes;
//}
// Parse ID from parameters
id = int.tryParse(Get.parameters['id'] ?? '0') ?? 0;
List<MeasureGeneral> generals = isar.measureGenerals.where().findAll();
// Initialize combined map with ID
Map<String, dynamic> combined = {'id': id};
logger.d(generals.map((el) => el.id));
// Retrieve measureGeneral data
measureGeneral = isar.measureGenerals.where().idEqualTo(id!).findFirst();
measureGeneral =
isar.measureGenerals.where().idEqualTo(widget.id).findFirst();
if (measureGeneral != null) {
// Fetch related details and types
measureDetails = MeasureDetailsRepository()
.getDetailsForMeasure(measureGeneral!.name!);
measureType = MeasureRepository().getTypeByName(
measureGeneral!.measureType!.map((el) => el.value).first!);
measureTypesDetails = MeasureTypesDetailsRepository()
.getTypeDetailsForType(measureType!.measureType!);
}
logger.d(measureGeneral);
// Save preferences and populate combined map
prefs.setBool('extended_json', true).then((_) {
_mergeToCombinedMap(combined, measureGeneral?.toJson());
_mergeToCombinedMap(combined, measureDetails?.toJson());
_mergeToCombinedMap(combined, measureType?.toJson());
_mergeToCombinedMap(combined, measureTypesDetails?.toJson());
setState(() {
measure = MeasureComplete.fromJson(combined);
});
logger.d(measure!.toJson());
});
// Add scroll listener for the back-to-top button
scrollController.addListener(() {
const showOffset = 10.0;
setState(
() => showBackToTopButton = scrollController.offset > showOffset);
setState(() {
showBackToTopButton = scrollController.offset > showOffset;
});
});
}
// Utility function to merge data into combined map, excluding 'id'
void _mergeToCombinedMap(
Map<String, dynamic> combined, Map<String, dynamic>? data) {
data?.forEach((key, value) {
if (key != 'id') {
combined[key] = value;
}
});
}
@ -74,9 +122,9 @@ class MeasureDetailPageState extends State<MeasureDetailPage> {
breakpoint: Breakpoint.fromContext(context),
theme: theme,
),
/*body: (context.breakpoint != myBreakpoints.sm)
? _buildInfoPage(context, massnahme)
: _tabbedInfoPage(context, massnahme),
body: (context.breakpoint != myBreakpoints.sm)
? _buildInfoPage(context, measure)
: _tabbedInfoPage(context, measure),
floatingActionButton: (context.breakpoint != myBreakpoints.sm)
? AnimatedOpacity(
duration: const Duration(milliseconds: 1000),
@ -94,11 +142,11 @@ class MeasureDetailPageState extends State<MeasureDetailPage> {
color: theme.currentColorScheme.onPrimary),
),
)
: null,*/
: null,
);
}
Widget _tabbedInfoPage(BuildContext context, MeasureTypes? massnahme) {
Widget _tabbedInfoPage(BuildContext context, MeasureComplete? massnahme) {
final AmbitoTheme theme = getTheme(context);
if (massnahme == null) {
@ -152,11 +200,11 @@ class MeasureDetailPageState extends State<MeasureDetailPage> {
SingleChildScrollView(
child: Column(children: _buildContentItems(massnahme)),
),
SingleChildScrollView(
/*SingleChildScrollView(
child: Column(
children: _buildSidebarItems(context, theme, massnahme),
),
),
),*/
],
),
),
@ -166,22 +214,20 @@ class MeasureDetailPageState extends State<MeasureDetailPage> {
);
}
Widget _buildInfoPage(BuildContext context, MeasureTypes? massnahme) {
Widget _buildInfoPage(BuildContext context, MeasureComplete? measure) {
final AmbitoTheme theme = getTheme(context);
if (massnahme == null) {
if (measure == null) {
return const Center(child: CircularProgressIndicator());
}
contentItems = _buildContentItems(massnahme);
contentItems = _buildContentItems(measure);
return Column(
children: [
_buildBreadcrumb(context, theme, massnahme),
//_buildBreadcrumb(context, theme, massnahme),
SizedBox(
width: double.infinity,
height: 300,
child: massnahme.getFullImage()),
width: double.infinity, height: 300, child: measure.getFullImage()),
Expanded(
child: SingleChildScrollView(
controller: scrollController,
@ -193,7 +239,7 @@ class MeasureDetailPageState extends State<MeasureDetailPage> {
Align(
alignment: Alignment.centerLeft,
child: Text(
massnahme.measureType!,
measure.name,
style: theme.currentThemeData.textTheme.headlineMedium,
),
),
@ -202,14 +248,22 @@ class MeasureDetailPageState extends State<MeasureDetailPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(children: contentItems),
child: Column(children: [
ListView.builder(
controller: itemScrollController,
itemCount: contentItems.length,
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemBuilder: (context, index) {
return contentItems[index];
}),
]),
),
theme.horizontalSpacer,
SizedBox(
width: 300,
child: Column(
children:
_buildSidebarItems(context, theme, massnahme),
children: _buildSidebarItems(context, theme, measure),
),
),
],
@ -257,68 +311,182 @@ class MeasureDetailPageState extends State<MeasureDetailPage> {
);
}
List<Widget> _buildContentItems(MeasureTypes massnahme) {
List<Widget> _buildContentItems(MeasureComplete measure) {
final AmbitoTheme theme = getTheme(context);
List<Widget> elements = [];
void addCard(
{required Widget card,
required String titleKey,
required bool condition}) {
if (condition) {
visibleItems.add(context.translate(titleKey));
elements.addAll([card, theme.verticalSpacer]);
void addCard({
required String title,
required Widget widget,
}) {
if (widget != const SizedBox()) {
visibleItems.add(title);
elements.add(widget);
elements.add(theme.verticalSpacer);
}
}
addCard(
card: DescriptionCard(massnahme: massnahme),
titleKey: 'page.actionDetailPage.description.title',
condition: massnahme.description?.isNotEmpty ?? false,
title: 'Beschreibung',
widget: SimpleTextCard(
title: 'Beschreibung',
text: measure.description,
),
);
addCard(
card: PresetsCard(massnahme: massnahme),
titleKey: 'page.actionDetailPage.presets.title',
condition: massnahme.objective?.isNotEmpty ?? false,
title: 'Zielsetzung',
widget: SimpleTextCard(
title: 'Zielsetzung',
text: measure.target,
),
);
addCard(
card: SizeCard(massnahme: massnahme),
titleKey: 'page.actionDetailPage.size.title',
condition: massnahme.applySize?.isNotEmpty ?? false,
title: 'Förderprogramme',
widget: UnorderedListCard(
title: 'Förderprogramme',
text: measure.fundingPrograms,
),
);
addCard(
card: LocationCard(massnahme: massnahme),
titleKey: 'page.actionDetailPage.location.title',
condition: massnahme.applyLocation?.isNotEmpty ?? false,
title: 'Größe / Fläche',
widget: UnorderedListCard(
title: 'Größe / Fläche',
text: measure.sizeOrArea,
),
);
addCard(
card: ImplementationCard(massnahme: massnahme),
titleKey: 'page.actionDetailPage.implementation.title',
condition: (massnahme.applyCosts?.isNotEmpty ?? false) &&
(massnahme.applyTime?.isNotEmpty ?? false),
title: 'Wuchs / Krone',
widget: SimpleTextCard(
title: 'Wuchs / Krone',
text: measure.growth,
),
);
addCard(
card: CreationCard(massnahme: massnahme),
titleKey: 'page.actionDetailPage.creation.title',
condition: massnahme.applyTimeFrame?.isNotEmpty ?? false,
title: 'Klima',
widget: SimpleTextCard(
title: 'Klima',
text: measure.climate,
),
);
addCard(
card: MaintenanceCard(massnahme: massnahme),
titleKey: 'page.actionDetailPage.maintenance.title',
condition: massnahme.maintenanceTimeFrame?.isNotEmpty ?? false,
title: 'Bodenwasser',
widget: SimpleTextCard(
title: 'Bodenwasser',
text: measure.soilWater,
),
);
addCard(
card: SourcesCard(massnahme: massnahme),
titleKey: 'page.actionDetailPage.sources.title',
condition: massnahme.sources?.isNotEmpty ?? false,
title: 'Region',
widget: SimpleTextCard(
title: 'Region',
text: measure.region?.join(', '),
),
);
addCard(
title: 'Standort',
widget: SimpleTextCard(
title: 'Standort',
text: measure.location,
),
);
addCard(
title: 'Fachgerechte Umsetzung',
widget: CombinedCard(
title: 'Fachgerechte Umsetzung',
elements: [
SublevelTextCard(
title: 'Kosten',
text: measure.applyCosts,
),
const Divider(),
SublevelTextCard(
title: 'Zeit',
text: measure.applyDuration,
),
],
),
);
addCard(
title: 'Anlage',
widget: CombinedCard(
title: 'Anlage',
elements: [
SublevelMonthsCard(
title: 'Zeitrahmen',
items: measure.applyMonths,
),
const Divider(),
SublevelTextCard(
title: 'Zusatzinformationen',
text: measure.applyAdditionalInfos,
),
const Divider(),
SublevelTextCard(
title: 'Arbeitsschritte',
text: measure.applySteps,
),
],
),
);
addCard(
title: 'Galerie',
widget: GalleryCard(
title: 'Galerie',
widgets: measure.getGalleryThumbnails(),
),
);
addCard(
title: 'Pflege',
widget: CombinedCard(
title: 'Pflege',
elements: [
SublevelMonthsCard(
title: 'Zeitrahmen',
items: measure.maintenanceMonths,
),
const Divider(),
SublevelTextCard(
title: 'Zusatzinformationen',
text: measure.maintenanceAdditionalInfos,
),
const Divider(),
SublevelTextCard(
title: 'Frequenz',
text: measure.maintenanceFrequency,
),
const Divider(),
SublevelTextCard(
title: 'Arbeitsschritte',
text: measure.maintenanceSteps,
),
const Divider(),
SublevelTextCard(
title: 'Besonderheiten',
text: measure.maintenanceSpecialFeatures,
),
],
),
);
addCard(
title: 'Quellen',
widget: SimpleTextCard(
title: 'Quellen',
text: measure.sources,
),
);
return [
@ -354,10 +522,14 @@ class MeasureDetailPageState extends State<MeasureDetailPage> {
}
List<Widget> _buildSidebarItems(
BuildContext context, AmbitoTheme theme, MeasureTypes massnahme) {
BuildContext context, AmbitoTheme theme, MeasureComplete massnahme) {
return [
if (visibleItems.isNotEmpty && context.breakpoint != myBreakpoints.sm)
TocCard(massnahme: massnahme, items: visibleItems.toList()),
TocCard(
massnahme: massnahme,
items: visibleItems.toList(),
scrollController: itemScrollController,
),
if (visibleItems.isNotEmpty && context.breakpoint != myBreakpoints.sm)
theme.verticalSpacer,
AdvisorCard(massnahme: massnahme),
@ -366,7 +538,6 @@ class MeasureDetailPageState extends State<MeasureDetailPage> {
theme.verticalSpacer,
FactsheetCard(massnahme: massnahme),
theme.verticalSpacer,
ReviewCard(massnahme: massnahme),
];
}
}

View file

@ -40,8 +40,6 @@ class MeasureGroupsPageState extends State<MeasureGroupsPage> {
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
//counter = MeasureRepository().getTypesCounterByCategory(currentCategory);
setState(() {
cards = {};
});

View file

@ -1,11 +1,9 @@
import 'package:ambito/src/config/config.dart';
import 'package:ambito/src/entity/enums/enum_details_type.dart';
import 'package:ambito/src/entity/funding_program/funding_program_repository.dart';
import 'package:ambito/src/entity/lists/list_display.dart';
import 'package:ambito/src/entity/lists/list_repository.dart';
import 'package:ambito/src/extensions/extensions.dart';
import 'package:ambito/src/pages/ambito_page.dart';
import 'package:ambito/src/pages/measure/detail/measure_detail_page.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';
@ -52,8 +50,6 @@ class MeasuresPageState extends State<MeasuresPage> {
void initState() {
ambitoFilterNotifier.addListener(_changeListener);
_initializeData();
preselectCategory = Get.parameters['kategorie'] ?? '';
if (preselectCategory != '') {
setState(() {
@ -102,30 +98,23 @@ class MeasuresPageState extends State<MeasuresPage> {
filterCategory = ambitoFilterNotifier.getFilter('category') ?? '';
filterGroup = ambitoFilterNotifier.getFilter('group') ?? '';
filterType = ambitoFilterNotifier.getFilter('type') ?? '';
/*filterSupport = ambitoFilterNotifier.getFilter('fundingProgram');
filterMonths = ambitoFilterNotifier.getFilter('month');*/
if (filterGroup == '' && filterType == '') {
setState(() {
itemsToDisplay = ListRepository().getGroupsToDisplay(filterCategory);
});
} else if (filterGroup != '' && filterType == '') {
setState(() {
itemsToDisplay =
ListRepository().getTypesToDisplay(filterCategory, filterGroup);
});
} else if (filterCategory != '' &&
filterGroup != '' &&
filterType != '') {
setState(() {
itemsToDisplay = ListRepository()
.getMeasuresToDisplay(filterCategory, filterGroup, filterType);
});
}
});
//html.window.history.pushState(null, 'Maßnahmen',
// '#/massnahmendatenbank/$filterCategory${filterGroup != '' ? '/$filterGroup' : ''}${filterType != '' ? '/$filterType' : ''}');
if (filterGroup == '' && filterType == '') {
setState(() {
itemsToDisplay = ListRepository().getGroupsToDisplay(filterCategory);
});
} else if (filterGroup != '' && filterType == '') {
setState(() {
itemsToDisplay =
ListRepository().getTypesToDisplay(filterCategory, filterGroup);
});
} else if (filterCategory != '' && filterGroup != '' && filterType != '') {
setState(() {
itemsToDisplay = ListRepository()
.getMeasuresToDisplay(filterCategory, filterGroup, filterType);
});
}
}
@override
@ -133,8 +122,6 @@ class MeasuresPageState extends State<MeasuresPage> {
super.dispose();
}
void _initializeData() {}
void _onSearchTextChanged(String value) {
setState(() {
searchText = value;
@ -270,17 +257,12 @@ class MeasuresPageState extends State<MeasuresPage> {
'/massnahmendatenbank/$filterCategory/$filterGroup/${measure.title!.toLowerCase().replaceUmlauts()}');
} else if (measure.isMeasure == true) {
logger.d(measure.id);
Get.to(
() => MeasureDetailPage(
id: measure.id!,
type: measure.isMeasure!
? EnumDetailsType.measure
: EnumDetailsType.type,
),
);
Get.toNamed('/massnahme/${measure.id}');
}
},
onHover: (hovered) {},
onHover: (measure.isMeasure == true || measure.hasChildren == true)
? (hovered) {}
: null,
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
focusColor: Colors.transparent,

View file

@ -1,4 +1,5 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:ambito/src/packages/ambito_notifier/notifier/cart_notifier.dart';
import 'package:ambito/src/packages/ambito_theme/ambito_theme.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
@ -55,6 +56,24 @@ class AmbitoAppbar extends AppBar {
color: theme.currentColorScheme.primary,
),
),
if (breakpoint >= myBreakpoints.md)
IconButton(
onPressed: () {
Get.toNamed('/warenkorb');
},
icon: ambitoCartNotifier.carts == 0
? Icon(
Icons.shopping_cart_outlined,
color: theme.currentColorScheme.primary,
)
: Badge.count(
count: ambitoCartNotifier.carts,
child: Icon(
Icons.shopping_cart_outlined,
color: theme.currentColorScheme.primary,
),
),
),
if (breakpoint >= myBreakpoints.md)
IconButton(
onPressed: () {

View file

@ -0,0 +1,23 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../packages/ambito_theme/ambito_theme.dart';
import 'outline_button.dart';
class PrintAllButton extends StatelessWidget {
final VoidCallback onPressed;
const PrintAllButton({super.key, required this.onPressed});
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
return WidgetOutlineButton(
onPressed: onPressed,
title: context.translate('page.general.buttons.print_all'),
backgroundColor: theme.currentColorScheme.secondary,
foregroundColor: theme.currentColorScheme.onPrimary,
borderColor: theme.currentColorScheme.secondary,
);
}
}

View file

@ -0,0 +1,23 @@
import 'package:ambito/src/extensions/extensions.dart';
import 'package:flutter/material.dart';
import '../../packages/ambito_theme/ambito_theme.dart';
import 'outline_button.dart';
class PrintButton extends StatelessWidget {
final VoidCallback onPressed;
const PrintButton({super.key, required this.onPressed});
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
return WidgetOutlineButton(
onPressed: onPressed,
title: context.translate('page.general.buttons.print'),
backgroundColor: theme.currentColorScheme.secondary,
foregroundColor: theme.currentColorScheme.onPrimary,
borderColor: theme.currentColorScheme.secondary,
);
}
}

View file

@ -12,7 +12,7 @@ import '../../entity/measure/group/measure_group.dart';
import '../../packages/ambito_theme/ambito_theme.dart';
class CardMeasure extends StatelessWidget {
const CardMeasure({Key? key, this.category, this.group}) : super(key: key);
const CardMeasure({super.key, this.category, this.group});
final MeasureCategory? category;
final MeasureGroup? group;

View file

@ -3,13 +3,19 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import '../../consts/consts.dart';
import '../../packages/ambito_theme/ambito_theme.dart';
class MapWidget extends StatefulWidget {
const MapWidget({super.key, required this.markers, required this.polygons});
const MapWidget(
{super.key,
required this.markers,
required this.polygons,
required this.polylines});
final Set<Marker>? markers;
final Set<Polygon>? polygons;
final Set<Marker> markers;
final Set<Polygon> polygons;
final Set<Polyline> polylines;
@override
State<StatefulWidget> createState() => MapWidgetState();
@ -29,12 +35,11 @@ class MapWidgetState extends State<MapWidget> {
@override
void initState() {
if (widget.markers != null) {
setState(() {
_initialPos =
CameraPosition(target: widget.markers!.first.position, zoom: 14);
});
}
setState(() {
_initialPos =
CameraPosition(target: widget.markers.first.position, zoom: 14);
});
super.initState();
}
@ -45,12 +50,11 @@ class MapWidgetState extends State<MapWidget> {
borderRadius: BorderRadius.circular(10.0),
child: SizedBox(
width: double.infinity,
height: 600,
child: Column(
children: [
Row(
children: [
Spacer(),
const Spacer(),
IconButton(
onPressed: () {
setState(() {
@ -70,17 +74,40 @@ class MapWidgetState extends State<MapWidget> {
onTap: (position) {
if (_drawPolygon == true) {
setState(() {
widget.markers?.add(Marker(
widget.markers.add(
Marker(
onTap: onTapMarker('polygon_$_counter'),
markerId: MarkerId('polygon_$_counter'),
position: position));
position: position,
),
);
if (_counter > 0) {
logger.i('add polyline');
widget.polylines.add(
Polyline(
polylineId: PolylineId('polyline_$_counter'),
color: theme.currentColorScheme.primary,
width: 2,
points: [
widget.markers
.where((el) =>
el.markerId ==
MarkerId('polygon_${_counter - 1}'))
.first
.position,
position
]),
);
}
_counter++;
});
}
},
mapToolbarEnabled: true,
mapType: MapType.hybrid,
markers: widget.markers ?? {},
polygons: widget.polygons ?? {},
markers: widget.markers,
polygons: widget.polygons,
polylines: widget.polylines,
initialCameraPosition: _initialPos,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
@ -91,4 +118,11 @@ class MapWidgetState extends State<MapWidget> {
)),
);
}
onTapMarker(String counter) {
logger.d(counter);
if (counter == 'polygon_0') {
logger.d('first pressed');
}
}
}

Some files were not shown because too many files have changed in this diff Show more