From ab6d87f78bf7141b416ed547549c16597367b0c8 Mon Sep 17 00:00:00 2001 From: YujithIsura Date: Tue, 10 Sep 2024 15:34:06 +0530 Subject: [PATCH] vehicle fule consumption report WIP --- .../asset_admin/lib/screens/scaffold.dart | 90 +-- .../lib/screens/vehicle_fuel_consumption.dart | 20 +- .../lib/widgets/vehicle_fuel_consumption.dart | 508 +++++++++-------- .../vehicle_fuel_consumption_edit.dart | 333 +++++++++++ .../vehicle_fuel_consumption_table.dart | 526 ++++++++++++++++++ 5 files changed, 1170 insertions(+), 307 deletions(-) create mode 100644 campus/frontend/lib/avinya/asset_admin/lib/widgets/vehicle_fuel_consumption_edit.dart create mode 100644 campus/frontend/lib/avinya/asset_admin/lib/widgets/vehicle_fuel_consumption_table.dart diff --git a/campus/frontend/lib/avinya/asset_admin/lib/screens/scaffold.dart b/campus/frontend/lib/avinya/asset_admin/lib/screens/scaffold.dart index f26a546d..33056095 100644 --- a/campus/frontend/lib/avinya/asset_admin/lib/screens/scaffold.dart +++ b/campus/frontend/lib/avinya/asset_admin/lib/screens/scaffold.dart @@ -47,10 +47,10 @@ class _SMSScaffoldState extends State { tileName: "Consumable Monthly Report", route: "/consumable_monthly_report", icon: Icons.summarize_sharp), - // SideNavigationSectionTile( - // tileName: "Vehicle Fuel Consumption Monthly Report", - // route: "/vehicle_fuel_consumption_monthly_report", - // icon: Icons.local_gas_station_outlined), + SideNavigationSectionTile( + tileName: "Vehicle Fuel Consumption Monthly Report", + route: "/vehicle_fuel_consumption_monthly_report", + icon: Icons.local_gas_station_outlined), ]; return Scaffold( @@ -385,47 +385,47 @@ class _SMSScaffoldState extends State { ), ), ), - // MouseRegion( - // onEnter: (_) { - // setState(() { - // isVehicleFuelConsumptionSectionHovered = true; - // }); - // }, - // onExit: (_) { - // setState(() { - // isVehicleFuelConsumptionSectionHovered = false; - // }); - // }, - // child: Container( - // decoration: BoxDecoration( - // color: isVehicleFuelConsumptionSectionHovered - // ? Colors.white.withOpacity(0.3) - // : null, - // borderRadius: BorderRadius.circular(15.0), - // ), - // margin: EdgeInsets.all(8.0), - // child: ListTile( - // leading: Icon(Icons.local_gas_station_sharp, - // color: Colors.white, size: 20.0), - // title: Container( - // margin: EdgeInsets.only(left: 12.0), - // transform: - // Matrix4.translationValues(-25, 0.0, 0.0), - // child: Text( - // "Vehicle Fuel Consumption", - // style: TextStyle( - // color: Colors.white, - // fontSize: 12, - // ), - // ), - // ), - // onTap: () { - // Navigator.pop(context); // Close the drawer - // routeState.go('/vehicle_fuel_consumption'); - // }, - // ), - // ), - // ), + MouseRegion( + onEnter: (_) { + setState(() { + isVehicleFuelConsumptionSectionHovered = true; + }); + }, + onExit: (_) { + setState(() { + isVehicleFuelConsumptionSectionHovered = false; + }); + }, + child: Container( + decoration: BoxDecoration( + color: isVehicleFuelConsumptionSectionHovered + ? Colors.white.withOpacity(0.3) + : null, + borderRadius: BorderRadius.circular(15.0), + ), + margin: EdgeInsets.all(8.0), + child: ListTile( + leading: Icon(Icons.local_gas_station_sharp, + color: Colors.white, size: 20.0), + title: Container( + margin: EdgeInsets.only(left: 12.0), + transform: + Matrix4.translationValues(-25, 0.0, 0.0), + child: Text( + "Vehicle Fuel Consumption", + style: TextStyle( + color: Colors.white, + fontSize: 12, + ), + ), + ), + onTap: () { + Navigator.pop(context); // Close the drawer + routeState.go('/vehicle_fuel_consumption'); + }, + ), + ), + ), SideNavigationSection( initialSectionHoveredValue: isConsumableReportSectionHovered, diff --git a/campus/frontend/lib/avinya/asset_admin/lib/screens/vehicle_fuel_consumption.dart b/campus/frontend/lib/avinya/asset_admin/lib/screens/vehicle_fuel_consumption.dart index 90081a9a..cd94adbd 100644 --- a/campus/frontend/lib/avinya/asset_admin/lib/screens/vehicle_fuel_consumption.dart +++ b/campus/frontend/lib/avinya/asset_admin/lib/screens/vehicle_fuel_consumption.dart @@ -1,15 +1,17 @@ import 'package:flutter/material.dart'; -import 'package:gallery/avinya/asset_admin/lib/widgets/vehicle_fuel_consumption.dart'; +import 'package:gallery/avinya/asset_admin/lib/widgets/vehicle_fuel_consumption_table.dart'; class VehicleFuelConsumptionScreen extends StatefulWidget { const VehicleFuelConsumptionScreen({super.key}); @override - State createState() => _VehicleFuelConsumptionScreenState(); + State createState() => + _VehicleFuelConsumptionScreenState(); } -class _VehicleFuelConsumptionScreenState extends State { - @override +class _VehicleFuelConsumptionScreenState + extends State { + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( @@ -17,10 +19,14 @@ class _VehicleFuelConsumptionScreenState extends State { var screenWidth = MediaQuery.of(context).size.width; var screenHeight = MediaQuery.of(context).size.height; - return Flexible( - child: Padding( - padding: const EdgeInsets.only(left: 20.0, top: 30.0), - child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - Flexible( - flex: 1, - child: Text( - 'Select a Date :', - style: TextStyle( - fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), - ), - ), - SizedBox( - width: 20.0, + return Padding( + padding: const EdgeInsets.only(left: 20.0, top: 30.0), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Row( + children: [ + Flexible( + flex: 1, + child: Text( + 'Select a Date :', + style: TextStyle( + fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), ), - Flexible( - flex: 2, - child: Container( - margin: EdgeInsets.only(left: 30.0), - width: screenWidth * 0.05, - height: screenHeight * 0.06, - child: TextField( - readOnly: true, - decoration: InputDecoration( - prefixIcon: Icon(Icons.calendar_month), - border: InputBorder.none), - onTap: () => _selectDate(context), - ), + ), + SizedBox( + width: 20.0, + ), + Flexible( + flex: 2, + child: Container( + margin: EdgeInsets.only(left: 30.0), + width: screenWidth * 0.05, + height: screenHeight * 0.06, + child: TextField( + readOnly: true, + decoration: InputDecoration( + prefixIcon: Icon(Icons.calendar_month), + border: InputBorder.none), + onTap: () => _selectDate(context), ), ), - if (_selectedDate != null) - Flexible( - flex: 1, - child: Text('${_selectedDate!.toLocal()}'.split(' ')[0])) - else - Flexible( + ), + if (_selectedDate != null) + Flexible( flex: 1, - child: Container( - margin: EdgeInsets.only(left: 20.0), - child: const Text( - 'No date selected.', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - ), - ), - ), - ) - ], - ), - const SizedBox( - height: 10, - ), - Row( - children: [ + child: Text('${_selectedDate!.toLocal()}'.split(' ')[0])) + else Flexible( flex: 1, - child: Text( - 'Select a Reason :', - style: TextStyle( - fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), - ), - ), - SizedBox( - width: 20.0, - ), - Flexible( - flex: 2, child: Container( margin: EdgeInsets.only(left: 20.0), - width: screenWidth * 0.17, - height: screenHeight * 0.06, - decoration: BoxDecoration( - border: Border.all(color: Colors.grey, width: 1.0), - borderRadius: BorderRadius.circular(5.0)), - child: DropdownButton( - isExpanded: true, - underline: SizedBox.shrink(), - value: reasonValue, - items: reasonValues.map((String? reason) { - return DropdownMenuItem( - value: reason, child: Text(reason ?? '')); - }).toList(), - onChanged: (String? newValue) async { - if (newValue == null) { - return; - } - setState(() { - reasonValue = newValue; - }); - }), - ), - ), - ], - ), - const SizedBox( - height: 10, - ), - Row( - children: [ - Flexible( - flex: 1, - child: Text( - 'Vehicle No :', - style: TextStyle( - fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), + child: const Text( + 'No date selected.', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + ), + ), ), + ) + ], + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + Flexible( + flex: 1, + child: Text( + 'Select a Reason :', + style: TextStyle( + fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), ), - SizedBox( - width: 20.0, - ), - Flexible( - flex: 2, - child: Container( - margin: EdgeInsets.only(left: 50.0), - width: screenWidth * 0.08, - height: screenHeight * 0.06, - decoration: BoxDecoration( - border: Border.all(color: Colors.grey, width: 1.0), - borderRadius: BorderRadius.circular(5.0)), - child: DropdownButton( - isExpanded: true, - underline: SizedBox.shrink(), - value: vehicleNoValue, - items: vehicleNoValues.map((String? vehicleNo) { - return DropdownMenuItem( - value: vehicleNo, child: Text(vehicleNo ?? '')); - }).toList(), - onChanged: (String? newValue) async { - if (newValue == null) { - return; - } - setState(() { - vehicleNoValue = newValue; - }); - }), - ), + ), + SizedBox( + width: 20.0, + ), + Flexible( + flex: 2, + child: Container( + margin: EdgeInsets.only(left: 20.0), + width: screenWidth * 0.17, + height: screenHeight * 0.06, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 1.0), + borderRadius: BorderRadius.circular(5.0)), + child: DropdownButton( + isExpanded: true, + underline: SizedBox.shrink(), + value: reasonValue, + items: reasonValues.map((String? reason) { + return DropdownMenuItem( + value: reason, child: Text(reason ?? '')); + }).toList(), + onChanged: (String? newValue) async { + if (newValue == null) { + return; + } + setState(() { + reasonValue = newValue; + }); + }), ), - ], - ), - const SizedBox( - height: 10, - ), - Row( - children: [ - Flexible( - flex: 1, - child: Text( - 'Starting Meter :', - style: TextStyle( - fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), - ), + ), + ], + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + Flexible( + flex: 1, + child: Text( + 'Vehicle No :', + style: TextStyle( + fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), ), - SizedBox( - width: 20.0, + ), + SizedBox( + width: 20.0, + ), + Flexible( + flex: 2, + child: Container( + margin: EdgeInsets.only(left: 50.0), + width: screenWidth * 0.08, + height: screenHeight * 0.06, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 1.0), + borderRadius: BorderRadius.circular(5.0)), + child: DropdownButton( + isExpanded: true, + underline: SizedBox.shrink(), + value: vehicleNoValue, + items: vehicleNoValues.map((String? vehicleNo) { + return DropdownMenuItem( + value: vehicleNo, child: Text(vehicleNo ?? '')); + }).toList(), + onChanged: (String? newValue) async { + if (newValue == null) { + return; + } + setState(() { + vehicleNoValue = newValue; + }); + }), ), - Flexible( - flex: 2, - child: Container( - margin: EdgeInsets.only(left: 30.0), - width: screenWidth * 0.2, - height: screenHeight * 0.08, - child: TextField( - maxLength: 20, - keyboardType: TextInputType.number, - controller: _starting_meter_controller, - decoration: InputDecoration( - counterText: '', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(4.0))), - ), - ), + ), + ], + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + Flexible( + flex: 1, + child: Text( + 'Starting Meter :', + style: TextStyle( + fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), ), - ], - ), - const SizedBox( - height: 10, - ), - Row( - children: [ - Flexible( - flex: 1, - child: Text( - 'Ending Meter :', - style: TextStyle( - fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), + ), + SizedBox( + width: 20.0, + ), + Flexible( + flex: 2, + child: Container( + margin: EdgeInsets.only(left: 30.0), + width: screenWidth * 0.2, + height: screenHeight * 0.08, + child: TextField( + maxLength: 20, + keyboardType: TextInputType.number, + controller: _starting_meter_controller, + decoration: InputDecoration( + counterText: '', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(4.0))), ), ), - SizedBox( - width: 20.0, + ), + ], + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + Flexible( + flex: 1, + child: Text( + 'Ending Meter :', + style: TextStyle( + fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), ), - Flexible( - flex: 2, - child: Container( - margin: EdgeInsets.only(left: 35.0), - width: screenWidth * 0.2, - height: screenHeight * 0.08, - child: TextField( - maxLength: 20, - keyboardType: TextInputType.number, - controller: _ending_meter_controller, - decoration: InputDecoration( - counterText: '', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(4.0))), - ), + ), + SizedBox( + width: 20.0, + ), + Flexible( + flex: 2, + child: Container( + margin: EdgeInsets.only(left: 35.0), + width: screenWidth * 0.2, + height: screenHeight * 0.08, + child: TextField( + maxLength: 20, + keyboardType: TextInputType.number, + controller: _ending_meter_controller, + decoration: InputDecoration( + counterText: '', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(4.0))), ), ), - ], - ), - const SizedBox( - height: 10, - ), - Row( - children: [ - Flexible( - flex: 1, - child: Text( - 'Comment :', - style: TextStyle( - fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), - ), + ), + ], + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + Flexible( + flex: 1, + child: Text( + 'Comment :', + style: TextStyle( + fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), ), - SizedBox( - width: 20.0, - ), - Flexible( - flex: 2, - child: Container( - margin: EdgeInsets.only(left: 55.0), - width: screenWidth * 0.2, - height: screenHeight * 0.2, - child: TextField( - keyboardType: TextInputType.multiline, - maxLines: null, - minLines: 3, - controller: _comment_controller, - decoration: InputDecoration( - counterText: '', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(4.0))), - ), + ), + SizedBox( + width: 20.0, + ), + Flexible( + flex: 2, + child: Container( + margin: EdgeInsets.only(left: 55.0), + width: screenWidth * 0.2, + height: screenHeight * 0.2, + child: TextField( + keyboardType: TextInputType.multiline, + maxLines: null, + minLines: 3, + controller: _comment_controller, + decoration: InputDecoration( + counterText: '', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(4.0))), ), ), - ], - ), - Row( - children: [ - Flexible( - child: Container( - width: screenWidth * 0.2, - height: screenHeight * 0.1, - child: OutlinedButton( - style: OutlinedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5.0)), - backgroundColor: Colors.yellow[700], - side: BorderSide( - color: Colors.grey.shade500, - width: 0.5, - style: BorderStyle.solid, - ), + ), + ], + ), + Row( + children: [ + Flexible( + child: Container( + width: screenWidth * 0.2, + height: screenHeight * 0.1, + child: OutlinedButton( + style: OutlinedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0)), + backgroundColor: Colors.yellow[700], + side: BorderSide( + color: Colors.grey.shade500, + width: 0.5, + style: BorderStyle.solid, ), - onPressed: (() {}), - child: Text( - 'Save', - style: TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.w400), - )), - ), + ), + onPressed: (() {}), + child: Text( + 'Save', + style: TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.w400), + )), ), - ], - ) - ]), - ), + ), + ], + ) + ]), ); } } diff --git a/campus/frontend/lib/avinya/asset_admin/lib/widgets/vehicle_fuel_consumption_edit.dart b/campus/frontend/lib/avinya/asset_admin/lib/widgets/vehicle_fuel_consumption_edit.dart new file mode 100644 index 00000000..5a9ea7f3 --- /dev/null +++ b/campus/frontend/lib/avinya/asset_admin/lib/widgets/vehicle_fuel_consumption_edit.dart @@ -0,0 +1,333 @@ +import 'package:flutter/material.dart'; + +class VehicleFuelConsumptionEdit extends StatefulWidget { + const VehicleFuelConsumptionEdit({super.key}); + + @override + State createState() => + _VehicleFuelConsumptionEditState(); +} + +class _VehicleFuelConsumptionEditState + extends State { + DateTime? _selectedDate; + String reasonValue = 'Student Shuttle-Morning'; + final List reasonValues = [ + 'Student Shuttle-Morning', + 'Student Shuttle-Evening', + 'Other' + ]; + String vehicleNoValue = 'QL-9904'; + final List vehicleNoValues = ['QL-9904', 'PB-2010', 'KV-1892']; + final _starting_meter_controller = TextEditingController(); + final _ending_meter_controller = TextEditingController(); + final _comment_controller = TextEditingController(); + + Future _selectDate(BuildContext context) async { + final DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2020), + lastDate: DateTime(2101), + ); + + if (pickedDate != null && pickedDate != _selectedDate) { + setState(() { + _selectedDate = pickedDate; + }); + } + } + + @override + void dispose() { + _starting_meter_controller.dispose(); + _ending_meter_controller.dispose(); + _comment_controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var screenWidth = MediaQuery.of(context).size.width; + var screenHeight = MediaQuery.of(context).size.height; + + return Padding( + padding: const EdgeInsets.only(left: 20.0, top: 30.0), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Row( + children: [ + Flexible( + flex: 1, + child: Text( + 'Select a Date :', + style: TextStyle( + fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), + ), + ), + SizedBox( + width: 20.0, + ), + Flexible( + flex: 2, + child: Container( + margin: EdgeInsets.only(left: 30.0), + width: screenWidth * 0.05, + height: screenHeight * 0.06, + child: TextField( + readOnly: true, + decoration: InputDecoration( + prefixIcon: Icon(Icons.calendar_month), + border: InputBorder.none), + onTap: () => _selectDate(context), + ), + ), + ), + if (_selectedDate != null) + Flexible( + flex: 1, + child: Text('${_selectedDate!.toLocal()}'.split(' ')[0])) + else + Flexible( + flex: 1, + child: Container( + margin: EdgeInsets.only(left: 20.0), + child: const Text( + 'No date selected.', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + ), + ), + ), + ) + ], + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + Flexible( + flex: 1, + child: Text( + 'Select a Reason :', + style: TextStyle( + fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), + ), + ), + SizedBox( + width: 20.0, + ), + Flexible( + flex: 2, + child: Container( + margin: EdgeInsets.only(left: 20.0), + width: screenWidth * 0.17, + height: screenHeight * 0.06, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 1.0), + borderRadius: BorderRadius.circular(5.0)), + child: DropdownButton( + isExpanded: true, + underline: SizedBox.shrink(), + value: reasonValue, + items: reasonValues.map((String? reason) { + return DropdownMenuItem( + value: reason, child: Text(reason ?? '')); + }).toList(), + onChanged: (String? newValue) async { + if (newValue == null) { + return; + } + setState(() { + reasonValue = newValue; + }); + }), + ), + ), + ], + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + Flexible( + flex: 1, + child: Text( + 'Vehicle No :', + style: TextStyle( + fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), + ), + ), + SizedBox( + width: 20.0, + ), + Flexible( + flex: 2, + child: Container( + margin: EdgeInsets.only(left: 50.0), + width: screenWidth * 0.08, + height: screenHeight * 0.06, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 1.0), + borderRadius: BorderRadius.circular(5.0)), + child: DropdownButton( + isExpanded: true, + underline: SizedBox.shrink(), + value: vehicleNoValue, + items: vehicleNoValues.map((String? vehicleNo) { + return DropdownMenuItem( + value: vehicleNo, child: Text(vehicleNo ?? '')); + }).toList(), + onChanged: (String? newValue) async { + if (newValue == null) { + return; + } + setState(() { + vehicleNoValue = newValue; + }); + }), + ), + ), + ], + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + Flexible( + flex: 1, + child: Text( + 'Starting Meter :', + style: TextStyle( + fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), + ), + ), + SizedBox( + width: 20.0, + ), + Flexible( + flex: 2, + child: Container( + margin: EdgeInsets.only(left: 30.0), + width: screenWidth * 0.2, + height: screenHeight * 0.08, + child: TextField( + maxLength: 20, + keyboardType: TextInputType.number, + controller: _starting_meter_controller, + decoration: InputDecoration( + counterText: '', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(4.0))), + ), + ), + ), + ], + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + Flexible( + flex: 1, + child: Text( + 'Ending Meter :', + style: TextStyle( + fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), + ), + ), + SizedBox( + width: 20.0, + ), + Flexible( + flex: 2, + child: Container( + margin: EdgeInsets.only(left: 35.0), + width: screenWidth * 0.2, + height: screenHeight * 0.08, + child: TextField( + maxLength: 20, + keyboardType: TextInputType.number, + controller: _ending_meter_controller, + decoration: InputDecoration( + counterText: '', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(4.0))), + ), + ), + ), + ], + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + Flexible( + flex: 1, + child: Text( + 'Comment :', + style: TextStyle( + fontStyle: FontStyle.normal, fontWeight: FontWeight.bold), + ), + ), + SizedBox( + width: 20.0, + ), + Flexible( + flex: 2, + child: Container( + margin: EdgeInsets.only(left: 55.0), + width: screenWidth * 0.2, + height: screenHeight * 0.2, + child: TextField( + keyboardType: TextInputType.multiline, + maxLines: null, + minLines: 3, + controller: _comment_controller, + decoration: InputDecoration( + counterText: '', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(4.0))), + ), + ), + ), + ], + ), + Row( + children: [ + Flexible( + child: Container( + width: screenWidth * 0.2, + height: screenHeight * 0.1, + child: OutlinedButton( + style: OutlinedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0)), + backgroundColor: Colors.yellow[700], + side: BorderSide( + color: Colors.grey.shade500, + width: 0.5, + style: BorderStyle.solid, + ), + ), + onPressed: (() {}), + child: Text( + 'Save', + style: TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.w400), + )), + ), + ), + ], + ) + ]), + ); + } +} diff --git a/campus/frontend/lib/avinya/asset_admin/lib/widgets/vehicle_fuel_consumption_table.dart b/campus/frontend/lib/avinya/asset_admin/lib/widgets/vehicle_fuel_consumption_table.dart new file mode 100644 index 00000000..ad884130 --- /dev/null +++ b/campus/frontend/lib/avinya/asset_admin/lib/widgets/vehicle_fuel_consumption_table.dart @@ -0,0 +1,526 @@ +import 'dart:ui'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:gallery/avinya/asset_admin/lib/data/stock_repenishment.dart'; +import 'package:gallery/data/campus_apps_portal.dart'; +import 'package:gallery/data/person.dart'; +import 'package:intl/intl.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import '../routing.dart'; + +class VehicleFuelConsumptionTable extends StatefulWidget { + const VehicleFuelConsumptionTable({Key? key, required this.title}) + : super(key: key); + + final String title; + + @override + State createState() => + _VehicleFuelConsumptionTableState(); +} + +class _VehicleFuelConsumptionTableState + extends State { + List _fetchedStockList = []; + List _fetchedStockListAfterSchool = []; + List result = []; + Organization? _fetchedOrganization; + bool _isFetching = true; + bool _isAfter = false; + List _fetchedStudentList = []; + Person? _person; + String? formatted_date; + int? parent_org_id; + + bool _isSubmitting = false; + bool _isUpdate = false; + bool _showQtyIn = false; + bool _backDate = false; + double prevQtyIn = 0.00; + int prevIndex = 0; + //calendar specific variables + DateTime? _selectedDay; + + List _controllers = []; + DateTime _selectedDate = DateTime.now(); + DateTime _fetcheddDate = DateTime.now(); + + late DataTableSource _data; + List columnNames = []; + List> attendanceList = []; + var _selectedValue; + var activityId = 0; + bool _isDisplayErrorMessage = false; + + var today = DateTime.now(); + + // DateTime? _selectedDate; + late TextEditingController _controller; + Future _pickDate(BuildContext context) async { + final DateTime? picked = await showDatePicker( + context: context, + initialDate: _selectedDate ?? DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2101), + ); + if (picked != null && picked != _selectedDate) { + DateTime isToday = DateTime.now(); + _isAfter = picked.isAfter(isToday); + setState(() { + _selectedDate = picked; + _isAfter = _isAfter; + prevQtyIn = 0.00; + }); + } + + int? parentOrgId = + campusAppsPortalInstance.getUserPerson().organization!.id; + + if (parentOrgId != null) { + setState(() { + _isFetching = true; // Set _isFetching to true before starting the fetch + }); + try { + setState(() { + refreshState( + DateFormat('yyyy-MM-dd HH:mm:ss').format(_selectedDate!)); + }); + } catch (error) { + // Handle any errors that occur during the fetch + setState(() { + _isFetching = false; // Set _isFetching to false in case of error + }); + // Perform error handling, e.g., show an error message + } + } + } + + @override + void initState() { + super.initState(); + // var today = DateTime.now(); + activityId = campusAppsPortalInstance.activityIds['homeroom']!; + _selectedDate = DateTime.now(); + _fetchInitialData(); + // selectWeek(today, activityId); + } + + void _initializeControllers() { + _controllers = _fetchedStockList.map((item) { + DateTime isToday = DateTime.now(); + return TextEditingController( + text: _showQtyIn ? item.quantity_in?.toString() : '0', + // text: + // _selectedDate == isToday ? '' : item.quantity_in?.toString() ?? '', + ); + }).toList(); + } + + @override + void dispose() { + // Perform any cleanup tasks here + for (var controller in _controllers) { + controller.dispose(); + } + super.dispose(); + } + + Future _fetchInitialData() async { + int? parentOrgId = + campusAppsPortalInstance.getUserPerson().organization?.id; + if (parentOrgId != null) { + setState(() { + _isFetching = true; // Show loading indicator + }); + try { + await refreshState( + DateFormat('yyyy-MM-dd HH:mm:ss').format(_selectedDate!)); + } catch (error) { + // Handle any errors that occur during the fetch + // You can show an error message or take appropriate actions here + } finally { + setState(() { + _isFetching = false; // Hide loading indicator + }); + } + } + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + } + + void updateSelected(int index, bool value, List selected) { + setState(() { + selected[index] = value; + }); + } + + String formatDateTime(DateTime dateTime) { + return "${dateTime.year}-${dateTime.month.toString().padLeft(2, '0')}-${dateTime.day.toString().padLeft(2, '0')} " + "${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}:${dateTime.second.toString().padLeft(2, '0')}"; + } + + Future refreshState(String? newValue) async { + setState(() { + _isFetching = true; // Set _isFetching to true before starting the fetch + }); + int? parentOrgId = + campusAppsPortalInstance.getUserPerson().organization!.id; + _selectedValue = newValue ?? null; + + _fetchedStockList = + await getStockListforReplenishment(parentOrgId, newValue!); + Person person = campusAppsPortalInstance.getUserPerson(); + + var formattedDate = formatDateTime(_selectedDate); + + for (var item in _fetchedStockList) { + if (item.updated != null) { + DateTime itemDate = DateTime.parse(item.updated!).toLocal(); + DateTime itemDateOnly = + DateTime(itemDate.year, itemDate.month, itemDate.day); + DateTime currentDate = DateTime.now().toLocal(); + if (item.quantity_out != 0) { + if (_selectedDate.day == currentDate.day) { + _isSubmitting = false; + _showQtyIn = false; + _backDate = false; + _isUpdate = false; + } else { + _isUpdate = true; + _backDate = false; + _isSubmitting = true; + _showQtyIn = false; + // this is a depletion + } + } else { + if (_selectedDate.year == currentDate.year && + _selectedDate.month == currentDate.month && + _selectedDate.day == currentDate.day) { + if (_selectedDate.isAfter(itemDateOnly) && + item.quantity_in != 0 && + _selectedDate.day != itemDateOnly.day) { + _showQtyIn = false; + _backDate = false; + _isUpdate = false; + } else { + _isSubmitting = false; + _showQtyIn = false; + _backDate = false; + _isUpdate = false; + } + } else if (_selectedDate.isBefore(currentDate)) { + if (_selectedDate.isAfter(itemDateOnly) && item.quantity_in != 0) { + _isSubmitting = false; + _showQtyIn = false; + _backDate = false; + _isUpdate = false; + break; + } else if (_selectedDate.isBefore(itemDateOnly)) { + _isSubmitting = true; + _showQtyIn = true; + _backDate = true; + _isUpdate = true; + } else { + _isSubmitting = true; + _backDate = false; + _showQtyIn = true; + _isUpdate = true; + } + } else { + _isSubmitting = false; + _showQtyIn = false; + _backDate = false; + _isUpdate = false; + } + } + } else { + _isSubmitting = false; + _showQtyIn = false; + _backDate = false; + _isUpdate = false; + } + } + + _fetchedStockList.map((item) { + if (item.quantity_in != 0) { + if (item.updated != null) { + _fetcheddDate = DateTime.parse(item.updated!); + } + } + }).toList(); + + if (mounted) { + setState(() { + _fetchedStockList; + _person = person; + _isSubmitting = _isSubmitting; + _backDate = _backDate; + _showQtyIn = _showQtyIn; + _fetcheddDate = _fetcheddDate; + _isUpdate = _isUpdate; + formatted_date = formattedDate; + parent_org_id = parentOrgId; + _isFetching = + false; // Ensure _isFetching is set to false after fetching + }); + } + + _initializeControllers(); + } + + Future _handleSubmit() async { + setState(() { + _isSubmitting = true; + }); + + if (_showQtyIn || _isUpdate) { + result = await updateConsumableReplenishment( + _fetchedStockList, this.formatted_date); + } else { + result = await addConsumableReplenishment(_fetchedStockList, + this._person?.id, this.parent_org_id, this.formatted_date, _isUpdate); + } + + setState(() { + refreshState(DateFormat('yyyy-MM-dd HH:mm:ss').format(_selectedDate)); + _isSubmitting = false; + _isUpdate = true; + }); + } + + @override + Widget build(BuildContext context) { + final routeState = RouteStateScope.of(context); + + return SingleChildScrollView( + child: campusAppsPortalPersonMetaDataInstance + .getGroups() + .contains('Student') + ? Padding( + padding: const EdgeInsets.all(16.0), + child: Center( + child: Text( + "Please go to 'Mark Attendance' Page", + style: TextStyle(fontSize: 24.0, fontWeight: FontWeight.bold), + ), + ), + ) + : Padding( + padding: const EdgeInsets.all(30.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Align( + alignment: Alignment.centerLeft, + child: Container( + width: 200, + child: TextField( + readOnly: true, + onTap: () => _pickDate(context), + decoration: InputDecoration( + labelText: 'Select Date', + suffixIcon: Icon(Icons.calendar_today), + ), + controller: TextEditingController( + text: _selectedDate == null + ? '' + : '${_selectedDate!.toLocal()}'.split(' ')[0], + ), + ), + ), + ), + SizedBox(height: 16.0), + _isFetching + ? Center( + child: SpinKitCircle( + color: Colors.deepPurpleAccent, + size: 50, + ), + ) + : _backDate != true + ? _fetchedStockList.isNotEmpty + ? LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: ConstrainedBox( + constraints: BoxConstraints( + minWidth: constraints.maxWidth, + ), + child: DataTable( + columns: const [ + DataColumn( + label: Text( + "Product Name", + style: TextStyle( + fontWeight: + FontWeight.bold), + ), + ), + DataColumn( + label: Text( + "Quantity", + style: TextStyle( + fontWeight: + FontWeight.bold), + ), + ), + DataColumn( + label: Text( + "On Hand", + style: TextStyle( + fontWeight: + FontWeight.bold), + ), + ), + DataColumn( + label: Text( + "Total", + style: TextStyle( + fontWeight: + FontWeight.bold), + ), + ), + DataColumn( + label: Text( + "Unit", + style: TextStyle( + fontWeight: + FontWeight.bold), + ), + ), + DataColumn( + label: Text( + "Action", + style: TextStyle( + fontWeight: + FontWeight.bold), + ), + ), + ], + rows: _fetchedStockList + .asMap() + .entries + .map((entry) { + int index = entry.key; + StockReplenishment item = + entry.value; + _controller = TextEditingController( + text: _isAfter + ? '0' + : item.quantity_in + ?.toString() ?? + '', + ); + return DataRow( + cells: [ + DataCell(Text( + item.consumable!.name!)), + DataCell(Text( + item.consumable!.name!)), + DataCell(Text( + _showQtyIn + ? item.prev_quantity! + .toString() + : item.quantity! + .toString(), + )), + DataCell(Text(item + .total_quantity + .toString())), + DataCell(Text(item + .resource_property!.value! + .toString())), + DataCell( + TextButton( + onPressed: () { + // Handle redirection to the new screen + routeState.go( + '/edit_screen/${item.id}'); + }, + child: Text('Edit'), + ), + ), + ], + ); + }).toList(), + ), + ), + ); + }, + ) + : Center( + child: Text('No data found'), + ) + : Text("Please Select Valid Date"), + if (!_isFetching && _fetchedStockList.isNotEmpty) + _backDate != true + ? Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: Align( + alignment: Alignment.centerRight, + child: SizedBox( + width: 120, + child: ElevatedButton( + onPressed: + _isSubmitting ? null : _handleSubmit, + style: ButtonStyle( + padding: MaterialStateProperty.all( + EdgeInsets.all(16.0)), + textStyle: + MaterialStateProperty.resolveWith( + (states) { + if (states + .contains(MaterialState.disabled)) { + return TextStyle( + fontSize: 16, color: Colors.grey); + } + return TextStyle( + fontSize: 16, color: Colors.black); + }), + elevation: + MaterialStateProperty.resolveWith( + (states) { + if (states + .contains(MaterialState.disabled)) { + return 0.0; + } + return 20.0; + }), + backgroundColor: + MaterialStateProperty.resolveWith( + (states) { + if (states + .contains(MaterialState.disabled)) { + return Colors.grey.shade400; + } + return Colors.greenAccent; + }), + foregroundColor: + MaterialStateProperty.resolveWith( + (states) { + if (states + .contains(MaterialState.disabled)) { + return Colors.grey.shade700; + } + return Colors.black; + }), + ), + child: Text( + _isUpdate ? 'Update' : 'Save', + ), + ), + ), + ), + ) + : Text(""), + ], + ), + ), + ); + } +}