import 'package:flutter/material.dart'; import 'package:flutter_box_transform/flutter_box_transform.dart'; import 'package:oc_front/core/services/specialized_services/abstract_service.dart'; import 'package:oc_front/core/services/specialized_services/booking_service.dart'; import 'package:oc_front/main.dart'; import 'package:oc_front/models/workflow.dart'; import 'package:oc_front/widgets/logs.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:oc_front/widgets/lib/tranformablebox.dart' as fork; import 'package:oc_front/widgets/sheduler_items/scheduler_calendar.dart'; import 'package:oc_front/widgets/sheduler_items/scheduler_item.dart'; double menuSize = 300; // ignore: must_be_immutable class ScheduleWidget extends StatefulWidget { DateTime start; DateTime end; bool isDayPlanner = true; bool loading = true; bool isList = true; bool isBox = true; AbstractService service; ScheduleWidget ({ super.key, required this.start, required this.end, required this.service, this.isBox =true, this.isList = true, this.loading = false}); @override ScheduleWidgetState createState() => ScheduleWidgetState(); } String? selected; String? selectedReal; class ScheduleWidgetState extends State { String search = ""; String? level; List colors = [Colors.blue, Colors.orange, redColor, Colors.green, redColor]; DateTime getFocusedDay() { if (selected != null) { return DateTime.parse(selected!); } return DateTime.now(); } @override Widget build(BuildContext context) { return FutureBuilder( future: widget.service.search(context, [ "${widget.start.year}-${widget.start.month > 9 ? widget.start.month : "0${widget.start.month}"}-${widget.start.day > 9 ? widget.start.day : "0${widget.start.day}"}", "${widget.end.year}-${widget.end.month > 9 ? widget.end.month : "0${widget.end.month}"}-${widget.end.day > 9 ? widget.end.day : "0${widget.end.day}"}"], {}), builder: (ctx, as) { Future.delayed(const Duration(minutes: 1), () { setState(() {}); }); Map> data = {}; if (as.hasData && as.data!.data != null) { for (var element in as.data!.data!.executions) { if (element.executionData == null) { continue; } DateTime dateTime = DateTime.parse(element.executionData!); DateTime date = DateTime(dateTime.year, dateTime.month, dateTime.day); var str = "${date.toIso8601String()}Z"; if (data[str] == null) { data[str] = []; } data[str]!.add(element); data[str]!.sort((a, b) => DateTime.parse(a.executionData!).compareTo(DateTime.parse(b.executionData!))); } } bool isInfo = getMainWidth(context) <= 600 && selected != null && widget.isBox; double w = selected != null && widget.isBox ? getMainWidth(context) - menuSize : getMainWidth(context); List children = []; if (selected != null) { for (var wf in data[selected!] ?? ([])) { DateTime d2 = DateTime.parse(wf.executionData!).toLocal(); children.add( InkWell( onTap: () => setState(() { selectedReal = wf.executionData; }), child: Container( margin: const EdgeInsets.all(10), decoration: BoxDecoration( border: Border.all(color: selectedReal != null && selectedReal == wf.executionData ? lightColor : Colors.transparent, width: 2), borderRadius: BorderRadius.circular(4), color: Colors.white ), child: Container( padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), child: Row(children: [ Container( width: 10, height: 10, decoration: BoxDecoration( color: colors[(wf.status ?? 1) - 1], borderRadius: BorderRadius.circular(4), ), ), SizedBox( width: (menuSize - 160), child: Padding( padding: const EdgeInsets.only(left: 20), child: Text(wf.name?.toUpperCase() ?? "", overflow: TextOverflow.ellipsis, style: const TextStyle(color: Colors.black, fontSize: 12, fontWeight: FontWeight.w500)), )), SizedBox( child: Padding( padding: const EdgeInsets.only(left: 20), child: Text("${d2.hour > 9 ? d2.hour : "0${d2.hour}"}:${d2.minute > 9 ? d2.minute : "0${d2.minute}"}:${d2.second > 9 ? d2.second : "0${d2.second}"}", overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 15, color: Colors.grey, fontWeight: FontWeight.w500)))) ]) )) )); } } String? selectedID; WorkflowExecution? sel; if (selectedReal != null) { try { sel = data[selected!]!.firstWhere((element) => element.executionData == selectedReal); selectedID = sel.id; } catch(e) { /* */ } } menuSize = isInfo ? getMainWidth(context) : (menuSize > getMainWidth(context) / 2 ? getMainWidth(context) / 2 : menuSize); Rect rect = Rect.fromCenter( center: MediaQuery.of(context).size.center(Offset.zero), width: selected != null ? menuSize : 0, height: (getMainHeight(context) - 50) > 0 ? (getMainHeight(context) - 50) : 0); return Row( children: [ isInfo ? Container() : SizedBox( width: w, child: widget.isList ? SchedulerItemWidget(data: data, parent: this, focusedDay: getFocusedDay(), width: w) : SchedulerCalendarWidget(data: data, start: widget.start, end: widget.end, parent: this, focusedDay: getFocusedDay(),) ), !widget.isBox ? Container() : fork.TransformableBox( rect: rect, constraints: BoxConstraints( maxWidth: isInfo ? getMainWidth(context) : (selected != null ? getMainWidth(context) / 2 : 0), minWidth: selected != null ? 300 : 0), handleTapSize: 1, handleTapLeftSize: 0, allowFlippingWhileResizing: false, draggable: false, flip: null, resizeModeResolver: () => ResizeMode.freeform, visibleHandles: const {HandlePosition.left}, enabledHandles: const {HandlePosition.left}, clampingRect: Offset.zero & MediaQuery.sizeOf(context), handleAlignment: HandleAlignment.inside, onChanged: (result, event) { setState(() { menuSize = result.rect.width; }); }, contentBuilder: (context, rect, flip) { return Container( height: getMainHeight(context) - 50, width: isInfo ? getMainWidth(context) : (selected != null ? menuSize : 0), color: midColor, child: Column( children: [ Row( children: [ InkWell( onTap: () => setState(() { widget.isDayPlanner = true; }), child: Tooltip( message: "day planning", child: Container( height: 50, width: (isInfo ? getMainWidth(context) : (selected != null ? menuSize : 0)) / (selectedReal != null ? 2 : 1 ), alignment: Alignment.center, decoration: BoxDecoration( color: widget.isDayPlanner ? Colors.grey : Colors.transparent, border: Border(bottom: BorderSide(color: Colors.grey.shade400), right: BorderSide(color: Colors.grey.shade400))), child: Icon(Icons.calendar_today_outlined, color: widget.isDayPlanner ? Colors.white : Colors.grey), ) )), InkWell( onTap: () => setState(() { widget.isDayPlanner = false; }), child: Tooltip( message: "monitor task", child: Container( height: 50, width: selectedReal == null ? 0 : ( (isInfo ? getMainWidth(context) : (selected != null ? menuSize : 0)) / 2), alignment: Alignment.center, decoration: BoxDecoration( color: !widget.isDayPlanner ? Colors.grey : Colors.transparent, border: Border(bottom: BorderSide(color: Colors.grey.shade400)) ), child: Icon(Icons.monitor_heart_outlined, size: 25, color: !widget.isDayPlanner ? Colors.white : Colors.grey), ) )) ]), SizedBox( width: isInfo ? getMainWidth(context) : (selected != null ? menuSize : 0), height: getMainHeight(context) - (!widget.isDayPlanner && !widget.loading ? 150 : 100 ), child: Stack( children: [ SingleChildScrollView( child: Column( mainAxisAlignment: children.isEmpty || widget.loading ? MainAxisAlignment.center : MainAxisAlignment.start, children: [ ...( widget.isDayPlanner ? children : ( selectedID != null ? [ widget.loading ? const SpinKitCircle(color: Colors.white,) : LogsWidget(exec: sel, search: search, level: level) ] : [])), children.isEmpty ? Container( height: 100, alignment: Alignment.center, child: const Text("No event found", style: TextStyle(color: Colors.grey, fontSize: 20))) : Container() ]), ) ]) ), !widget.isDayPlanner && !widget.loading ? Row( children: [ Container( width: 150, height: 50, decoration: BoxDecoration( border: Border(left: BorderSide(color: midColor)), ), child: DropdownButtonFormField( isExpanded: true, value: level, style: const TextStyle(fontSize: 12), hint: const Text("by level...", style: TextStyle(fontSize: 12)), decoration: InputDecoration( filled: true, focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.zero, borderSide: BorderSide(color: lightColor, width: 0), ), fillColor: Colors.white, contentPadding: const EdgeInsets.only(left: 30, right: 30, top: 10, bottom: 30), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.zero, borderSide: BorderSide(color: midColor, width: 0), ), border: OutlineInputBorder( borderRadius: BorderRadius.zero, borderSide: BorderSide(color: midColor, width: 0)), ), items: [ DropdownMenuItem(value: "debug,warning,error,info", child: Row( children: [ Container( width: 10, height: 15, color: Colors.grey), Text(" all", style: TextStyle(fontSize: 12, color: Colors.black)) ])), DropdownMenuItem(value: "debug", child: Row( children: [ Container( width: 10, height: 15, color: Colors.blue), Text(" debug", style: TextStyle(fontSize: 12, color: Colors.black)) ])), DropdownMenuItem(value: "warning", child: Row( children: [ Container( width: 10, height: 15, color: Colors.orange), Text(" warning", style: TextStyle(fontSize: 12, color: Colors.black)) ])), DropdownMenuItem(value: "error", child: Row( children: [ Container( width: 10, height: 15, color: redColor), Text(" error", style: TextStyle(fontSize: 12, color: Colors.black)) ])), DropdownMenuItem(value: "info", child: Row( children: [ Container( width: 10, height: 15, color: Colors.green), Text(" info", style: TextStyle(fontSize: 12, color: Colors.black)) ])), ], onChanged: (value) { setState(() { level = value; }); })), Container( width: menuSize - 150, height: 50, decoration: BoxDecoration( border: Border(left: BorderSide(color: midColor)), ), child: TextField( onChanged: (value) { setState(() { search = value; });}, style: const TextStyle(fontSize: 12), decoration: const InputDecoration( hintText: "by logs...", fillColor: Colors.white, filled: true, contentPadding: EdgeInsets.symmetric(horizontal: 30), hintStyle: TextStyle( color: Colors.black, fontSize: 12, fontWeight: FontWeight.w300 ), border: InputBorder.none ) )) ] ) : Container( ), ], ), ); }) ]); }); } }