ambito/lib/src/pages/dashboard/areas/dashboard_areas_page.dart

635 lines
34 KiB
Dart
Raw Normal View History

2024-12-07 20:53:13 +01:00
import 'package:ambito/src/entity/_general/id_value/id_value.dart';
import 'package:ambito/src/entity/area/area_datasource.dart';
import 'package:ambito/src/entity/area/area_repository.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_geocoding_api/google_geocoding_api.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:screen_breakpoints/screen_breakpoints.dart';
import 'package:syncfusion_flutter_core/theme.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:toggle_switch/toggle_switch.dart';
import '../../../config/config.dart';
import '../../../consts/consts.dart';
import '../../../entity/area/area.dart';
import '../../../entity/business/business.dart';
import '../../../packages/ambito_api/base_api.dart';
import '../../../packages/ambito_theme/ambito_theme.dart';
import '../../../widgets/appbar/ambito_appbar.dart';
import '../../../widgets/map/map_widget.dart';
import '../../../widgets/map/marker_generator.dart';
import '../../../widgets/page/base_page.dart';
class DashboardAreasPage extends StatefulWidget {
const DashboardAreasPage(
{super.key, required this.businessId, required this.userId});
final int businessId;
final int userId;
@override
State<StatefulWidget> createState() => DashboardAreasPageState();
}
class DashboardAreasPageState extends State<DashboardAreasPage> {
Widget mapWidget = const SizedBox();
final api = GoogleGeocodingApi(googleApiKey, isLogged: false);
Set<Marker> markers = {};
Set<Polygon> polygons = {};
List<Area> areas = [];
Business? business;
int display = 0;
@override
void initState() {
BaseApi().getContent('business').then((_) {
business = isar.business.get(widget.businessId);
display = int.tryParse(Get.parameters['index'] ?? '0') ?? 0;
api
.search(business!.addressComplete!, language: 'de')
.then((GoogleGeocodingResponse response) {
MarkerGenerator(64)
.createBitmapDescriptorFromIconData(
Icons.home,
Colors.white,
const Color(0xFF60845E),
const Color(0xff87A34E),
)
.then((
BitmapDescriptor bitMapDescriptor,
) {
final prettyAddress = response.results.firstOrNull?.mapToPretty();
areas = AreaRepository().getAreasForBusiness(widget.businessId);
for (Area area in areas) {
final polygon = area.toPolygon();
if (polygon != null) {
setState(() {
polygons.add(polygon);
});
}
}
setState(() {
markers.add(
Marker(
markerId: MarkerId(business!.name!),
position: LatLng(
prettyAddress?.latitude ?? 0,
prettyAddress?.longitude ?? 0,
),
icon: bitMapDescriptor,
),
);
mapWidget = MapWidget(
markers: markers,
polygons: polygons,
);
});
});
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
final AmbitoTheme theme = getTheme(context);
setState(() {});
areas = AreaRepository().getAreasForBusiness(widget.businessId);
return BasePage().getPage(
context,
SingleChildScrollView(
child: Align(
alignment: Alignment.topCenter,
child: Padding(
padding: context.breakpoint.padding,
child: SizedBox(
width: 1152,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
theme.verticalSpacer,
Text(
'Flächen',
style: theme.titleMedium,
),
theme.verticalSpacer,
Row(
children: [
ToggleSwitch(
initialLabelIndex: display,
totalSwitches: 2,
minWidth: 200,
borderWidth: 1,
labels: const ['Karte', 'Liste'],
activeBgColor: [theme.currentColorScheme.secondary],
borderColor: [theme.currentColorScheme.secondary],
inactiveBgColor: Colors.white,
activeFgColor: theme.currentColorScheme.onSecondary,
customTextStyles: [theme.bodyMedium],
onToggle: (index) {
setState(() {
display = index ?? 0;
});
},
),
const Spacer(),
OutlinedButton(
style: OutlinedButton.styleFrom(
minimumSize: const Size(200, 50),
shape: RoundedRectangleBorder(
side: const BorderSide(
color: Colors.blue,
width: 1,
style: BorderStyle.solid),
borderRadius: BorderRadius.circular(
10,
),
),
backgroundColor: theme.currentColorScheme.secondary,
foregroundColor:
theme.currentColorScheme.onSecondary,
side: BorderSide(
width: 1,
color: theme.currentColorScheme.secondary),
),
onPressed: () async {
final TextEditingController _controllerName =
TextEditingController();
final TextEditingController _controllerSize =
TextEditingController();
final TextEditingController _controllerDescription =
TextEditingController();
await showDialog<String>(
context: context,
builder: (BuildContext context) =>
Dialog.fullscreen(
child: Scaffold(
appBar: AmbitoAppbar(
links: const ['dashboard', 'massnahmen'],
breakpoint:
Breakpoint.fromContext(context),
theme: theme),
body: BreakpointBuilder(
builder: (
context,
breakpoint,
configuration,
) {
return SingleChildScrollView(
child: Center(
child: SizedBox(
width:
Breakpoint.fromContext(context)
.width,
child: Padding(
padding:
const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
theme.verticalSpacer,
Text(
'Fläche bearbeiten',
style: theme.headlineMedium
.copyWith(
color: theme
.currentColorScheme
.onSurface,
),
),
theme.verticalSpacer,
Align(
alignment:
Alignment.centerRight,
child: Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
OutlinedButton(
style: OutlinedButton
.styleFrom(
minimumSize:
const Size(
200, 50),
shape:
RoundedRectangleBorder(
side: BorderSide(
color: redColors[
'primary']!,
width: 1,
style:
BorderStyle
.solid,
),
borderRadius:
BorderRadius
.circular(
10,
),
),
backgroundColor: theme
.currentColorScheme
.surface
.withOpacity(
.1),
foregroundColor: theme
.currentColorScheme
.primary,
side: BorderSide(
width: 1,
color: theme
.currentColorScheme
.primary,
),
),
onPressed: () {
Navigator.pop(
context);
},
child: Text(
'Abbrechen',
style: theme
.bodyMedium,
),
),
theme.horizontalSpacer,
OutlinedButton(
onHover: (hover) {},
style: OutlinedButton
.styleFrom(
minimumSize:
const Size(
200, 50),
shape:
RoundedRectangleBorder(
side: BorderSide(
color: redColors[
'primary']!,
width: 1,
style:
BorderStyle
.solid,
),
borderRadius:
BorderRadius
.circular(
10,
),
),
backgroundColor: theme
.currentColorScheme
.secondary,
foregroundColor: theme
.currentColorScheme
.onPrimary,
side: BorderSide(
width: 1,
color: theme
.currentColorScheme
.secondary,
),
),
onPressed: () async {
Area area = Area()
..id = isar.areas
.autoIncrement()
..description =
_controllerDescription
.value
.text
..business = [
IdValue()
..id = widget
.businessId
..value =
business!
.name!
]
..name =
_controllerName
.value
.text
..size =
_controllerSize
.value
.text;
await BaseApi()
.postContent(
'area',
area.toJson());
await BaseApi()
.getContent(
'business');
setState(() {
areas = AreaRepository()
.getAreasForBusiness(
widget
.businessId);
logger.d(
areas.length);
});
Navigator.pop(
context);
},
child: Text(
'Speichern',
style: theme
.bodyMedium,
),
),
],
),
),
theme.verticalSpacer,
Card(
elevation: 0,
color: theme
.currentColorScheme
.tertiary,
child: Padding(
padding:
EdgeInsets.all(20),
child: Column(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Text(
'Allgemein',
style: theme
.headlineSmall,
),
theme.verticalSpacer,
Row(
children: [
Expanded(
child:
TextField(
controller:
_controllerName,
maxLines: 1,
decoration:
InputDecoration(
labelText:
'Bezeichnung',
isDense:
true,
hintText:
'Bezeichnung',
filled:
true,
fillColor:
Colors
.white,
hoverColor:
Colors
.white,
border:
OutlineInputBorder(
borderSide:
BorderSide(
color: redColors[
'primary']!,
width:
1,
style: BorderStyle
.solid,
),
borderRadius:
BorderRadius.circular(
8),
),
),
),
),
theme
.horizontalSpacer,
Expanded(
child:
TextField(
controller:
_controllerSize,
maxLines: 1,
decoration:
InputDecoration(
suffixText:
'',
labelText:
'Größe',
isDense:
true,
hintText:
'Größe',
filled:
true,
fillColor:
Colors
.white,
hoverColor:
Colors
.white,
border:
OutlineInputBorder(
borderSide:
BorderSide(
color: redColors[
'primary']!,
width:
1,
style: BorderStyle
.solid,
),
borderRadius:
BorderRadius.circular(
8),
),
),
),
),
],
),
theme.verticalSpacer,
TextField(
controller:
_controllerDescription,
maxLines: 5,
decoration:
InputDecoration(
labelText:
'Notizen',
isDense: true,
hintText:
'Notizen',
filled: true,
fillColor:
Colors.white,
hoverColor:
Colors.white,
border:
OutlineInputBorder(
borderSide:
BorderSide(
color: redColors[
'primary']!,
width: 1,
style:
BorderStyle
.solid,
),
borderRadius:
BorderRadius
.circular(
8),
),
),
),
],
),
),
),
theme.verticalSpacer,
],
),
),
),
),
);
},
),
),
),
);
Get.offAndToNamed('/dashboard/flaechen/1');
},
child: Text(
'Neue Fläche',
style: theme.bodyMedium,
))
],
),
theme.verticalSpacer,
(display == 0) ? mapWidget : gridWidget(areas),
theme.verticalSpacer,
],
),
),
),
),
),
);
}
Widget gridWidget(List<Area> areas) {
final AmbitoTheme theme = getTheme(context);
return SizedBox(
width: 1152,
child: SfDataGridTheme(
data: SfDataGridThemeData(
headerColor: theme.currentColorScheme.primaryContainer,
sortIcon: Icon(
Icons.keyboard_arrow_down,
color: theme.currentColorScheme.primary,
),
),
child: SfDataGrid(
allowSorting: true,
source: AreaDataSource(areas: areas, context: context),
columnWidthMode: ColumnWidthMode.fill,
columns: [
GridColumn(
visible: false,
columnName: 'id',
label: Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
style: theme.bodyMedium.copyWith(
color: theme.currentColorScheme.primary,
),
),
),
),
GridColumn(
columnName: 'name',
label: Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.centerLeft,
child: Text(
'Bezeichnung',
overflow: TextOverflow.ellipsis,
style: theme.bodyMedium.copyWith(
color: theme.currentColorScheme.primary,
),
),
),
),
GridColumn(
columnName: 'size',
maximumWidth: 200,
label: Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.centerLeft,
child: Text(
'Größe',
overflow: TextOverflow.ellipsis,
style: theme.bodyMedium.copyWith(
color: theme.currentColorScheme.primary,
),
),
),
),
GridColumn(
columnName: 'description',
maximumWidth: 100,
allowSorting: false,
label: Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.centerLeft,
child: Text(
'Notiz',
overflow: TextOverflow.ellipsis,
style: theme.bodyMedium.copyWith(
color: theme.currentColorScheme.primary,
),
),
),
),
GridColumn(
columnName: 'action',
allowSorting: false,
maximumWidth: 150,
label: Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.centerLeft,
child: Text(
'Aktion',
overflow: TextOverflow.ellipsis,
style: theme.bodyMedium.copyWith(
color: theme.currentColorScheme.primary,
),
),
),
),
],
),
),
);
}
}