Merge branch 'dev' of https://github.com/SyncrowIOT/syncrow-app into feat/refactor

This commit is contained in:
hannathkadher
2024-10-31 10:45:08 +04:00
66 changed files with 4004 additions and 1041 deletions
@@ -0,0 +1,177 @@
import 'package:flutter/material.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class EnergyConsumptionPage extends StatefulWidget {
final List<dynamic> chartData;
final double totalConsumption;
final String date;
EnergyConsumptionPage({
required this.chartData,
required this.totalConsumption,
required this.date,
});
@override
_EnergyConsumptionPageState createState() => _EnergyConsumptionPageState();
}
class _EnergyConsumptionPageState extends State<EnergyConsumptionPage> {
late List<dynamic> _chartData;
@override
void initState() {
_chartData = widget.chartData;
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 19),
child: LineChart(
LineChartData(
lineTouchData: LineTouchData(
handleBuiltInTouches: true,
touchSpotThreshold: 2,
getTouchLineEnd: (barData, spotIndex) {
return 10.0;
},
touchTooltipData: LineTouchTooltipData(
getTooltipColor: (touchTooltipItem) => Colors.white,
tooltipRoundedRadius: 10.0,
tooltipPadding: const EdgeInsets.all(8.0),
tooltipBorder: BorderSide(color: Colors.grey, width: 1),
getTooltipItems: (List<LineBarSpot> touchedSpots) {
return touchedSpots.map((spot) {
return LineTooltipItem(
'${spot.x},\n ${spot.y.toStringAsFixed(2)} kWh',
const TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
fontSize: 12,
),
);
}).toList();
},
)),
titlesData: FlTitlesData(
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: false,
),
),
leftTitles: const AxisTitles(
sideTitles: SideTitles(
showTitles: false,
),
),
rightTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: false,
),
),
topTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 70,
getTitlesWidget: (value, meta) {
int index = value.toInt();
if (index >= 0 && index < _chartData.length) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: RotatedBox(
quarterTurns: -1,
child: Text(_chartData[index].time,
style: TextStyle(fontSize: 10)),
),
);
}
return const SizedBox.shrink();
},
),
),
),
gridData: FlGridData(
show: true,
drawVerticalLine: true,
horizontalInterval: 1,
verticalInterval: 1,
getDrawingVerticalLine: (value) {
return FlLine(
color: Colors.grey.withOpacity(0.2),
dashArray: [8, 8],
strokeWidth: 1,
);
},
getDrawingHorizontalLine: (value) {
return FlLine(
color: Colors.grey.withOpacity(0.2),
dashArray: [5, 5],
strokeWidth: 1,
);
},
drawHorizontalLine: false,
),
lineBarsData: [
LineChartBarData(
preventCurveOvershootingThreshold: 0.1,
curveSmoothness: 0.5,
preventCurveOverShooting: true,
aboveBarData: BarAreaData(),
spots: _chartData
.asMap()
.entries
.map((entry) => FlSpot(
entry.key.toDouble(), entry.value.consumption))
.toList(),
isCurved: true,
color: ColorsManager.chart.withOpacity(0.6),
show: true,
shadow: Shadow(color: Colors.black12),
belowBarData: BarAreaData(
show: true,
gradient: LinearGradient(
colors: [
ColorsManager.chart.withOpacity(0.5),
Colors.blue.withOpacity(0.1),
],
begin: Alignment.center,
end: Alignment.bottomCenter,
),
),
dotData: FlDotData(
show: false,
),
isStrokeCapRound: true,
barWidth: 2,
),
],
borderData: FlBorderData(
show: false,
border: Border.all(
color: Color(0xff023DFE).withOpacity(0.7),
width: 10,
),
),
),
),
),
),
],
),
);
}
}
class EnergyData {
EnergyData(this.time, this.consumption);
final String time;
final double consumption;
}
//
@@ -0,0 +1,239 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/devices/view/widgets/power_clamp/power_info_card.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'power_chart.dart';
class PowerClampCard extends StatelessWidget {
final bool? isGeneral;
final String? title;
final String? totalCurrent;
final String? totalActiveGeneral;
final String? totalCurrentGeneral;
final String? totalFrequencyGeneral;
final String? totalVoltage;
final String? totalActive;
final String? totalFrequency;
final String? dateTimeSelected;
final String? totalFactor;
final Widget? dateSwitcher;
final String? formattedDate;
final String? phaseType;
final String? energyConsumption;
final Function()? selectDateEvent;
final List<EnergyData>? chartData;
final BuildContext? context;
const PowerClampCard({
Key? key,
this.isGeneral,
this.title,
this.totalCurrent,
this.totalActiveGeneral,
this.dateTimeSelected,
this.totalCurrentGeneral,
this.totalFrequencyGeneral,
this.totalVoltage,
this.phaseType,
this.totalActive,
this.totalFrequency,
this.totalFactor,
this.dateSwitcher,
this.formattedDate,
this.selectDateEvent,
this.chartData,
this.context,
this.energyConsumption,
//nConsumption
}) : super(key: key);
@override
Widget build(BuildContext context) {
return DefaultContainer(
child: Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 10, bottom: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Energy usage'),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodyLarge(
text: title!,
fontSize: 20,
fontWeight: FontWeight.w700,
),
Row(
children: [
BodyLarge(
text: energyConsumption!,
fontSize: 20,
fontWeight: FontWeight.w700,
),
const BodySmall(text: 'kWh')
],
),
],
),
const SizedBox(
height: 10,
),
isGeneral == true
? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
PowerClampInfoCard(
iconPath: Assets.powerActiveIcon,
title: 'Active',
value: '$totalActiveGeneral',
unit: ' w',
),
PowerClampInfoCard(
iconPath: Assets.voltMeterIcon,
title: 'Current',
value: '$totalCurrentGeneral',
unit: ' A',
),
PowerClampInfoCard(
iconPath: Assets.frequencyIcon,
title: 'Frequency',
value: '$totalFrequencyGeneral',
unit: ' Hz',
),
],
)
: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
PowerClampInfoCard(
iconPath: Assets.voltageIcon,
title: 'Voltage',
value: '${double.parse(totalVoltage!) / 10}',
unit: ' V',
),
PowerClampInfoCard(
iconPath: Assets.voltMeterIcon,
title: 'Current',
value: '$totalCurrent',
unit: ' A',
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
PowerClampInfoCard(
iconPath: Assets.powerActiveIcon,
title: 'Active Power',
value: '$totalActive',
unit: ' w',
),
PowerClampInfoCard(
iconPath: Assets.speedoMeter,
title: 'Power Factor',
value: '$totalFactor',
unit: '',
),
],
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
BodyMedium(
text: isGeneral == true
? 'Total consumption'
: phaseType!,
fontSize: 12,
fontWeight: FontWeight.w700,
),
Text(
dateTimeSelected!,
style: const TextStyle(
fontSize: 8, fontWeight: FontWeight.w400),
),
],
),
const Row(
children: [
BodyMedium(
text: '1000.00 ',
fontSize: 12,
fontWeight: FontWeight.w700),
BodyMedium(
text: 'kWh',
fontSize: 8,
fontWeight: FontWeight.w700),
],
),
],
),
Expanded(
child: SizedBox(
child: EnergyConsumptionPage(
chartData: chartData!.isNotEmpty
? chartData!
: [
EnergyData('12:00 AM', 4.0),
EnergyData('01:00 AM', 3.5),
EnergyData('02:00 AM', 3.8),
EnergyData('03:00 AM', 3.2),
EnergyData('04:00 AM', 4.0),
EnergyData('05:00 AM', 3.4),
EnergyData('06:00 AM', 3.2),
EnergyData('07:00 AM', 3.5),
EnergyData('08:00 AM', 3.8),
EnergyData('09:00 AM', 3.6),
EnergyData('10:00 AM', 3.9),
EnergyData('11:00 AM', 4.0),
],
totalConsumption: chartData!
.fold(0, (sum, data) => sum + data.consumption),
date: '10/08/2024',
),
),
),
const SizedBox(
height: 5,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
DefaultContainer(
padding: EdgeInsets.all(0),
color: ColorsManager.grayBox,
child: SizedBox(
child: dateSwitcher,
)),
InkWell(
onTap: selectDateEvent,
child: DefaultContainer(
color: ColorsManager.grayBox,
child: SizedBox(
child: Padding(
padding: const EdgeInsets.all(5),
child: Text(formattedDate!),
),
)),
),
],
)
]),
),
);
}
}
@@ -0,0 +1,252 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/power_clamp_bloc/power_clamp_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/power_clamp_bloc/power_clamp_event.dart';
import 'package:syncrow_app/features/devices/bloc/power_clamp_bloc/power_clamp_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/power_clamp_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/power_clamp/power_chart.dart';
import 'package:syncrow_app/features/devices/view/widgets/power_clamp/power_clamp_card.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class PowerClampPage extends StatefulWidget {
final DeviceModel? device;
const PowerClampPage({super.key, this.device});
@override
State<PowerClampPage> createState() => _PowerClampPageState();
}
class _PowerClampPageState extends State<PowerClampPage> {
final PageController _pageController = PageController();
int _currentPage = 0;
static const int _pageCount = 4;
late PowerClampModel model;
@override
void initState() {
super.initState();
_pageController.addListener(_handlePageChange);
model = _initialPowerClampModel();
}
void _handlePageChange() {
int nextPage = _pageController.page?.round() ?? 0;
if (_currentPage != nextPage) {
setState(() {
_currentPage = nextPage;
});
}
}
@override
void dispose() {
_pageController.removeListener(_handlePageChange);
_pageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Power Clamp',
child: BlocProvider(
create: (context) => PowerClampBloc(PCId: widget.device?.uuid ?? '')
..add(const PowerClampInitial()),
child: BlocBuilder<PowerClampBloc, PowerClampState>(
builder: (context, state) {
final blocProvider = context.read<PowerClampBloc>();
List<EnergyData> chartData = [];
if (state is UpdateState) {
model = state.powerClampModel;
} else if (state is EnergyDataState) {
chartData = state.energyData;
} else if (state is FilterRecordsState) {
chartData = state.filteredRecords;
}
if (state is PowerClampLoadingState) {
return const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator(),
),
);
}
return Column(
children: [
Flexible(
child: RefreshIndicator(
onRefresh: () async {
blocProvider.add(const PowerClampInitial());
},
child: PageView(controller: _pageController, children: [
_buildPowerClampCard(
phaseType: '',
title: 'Total Energy \nConsumption',
phase: model.status.general,
isGeneral: true,
chartData: chartData,
blocProvider: blocProvider,
),
_buildPowerClampCard(
title: 'Phase A Energy \nConsumption',
phaseType: 'Phase A consumption',
phase: model.status.phaseA,
chartData: chartData,
blocProvider: blocProvider,
),
_buildPowerClampCard(
title: 'Phase B Energy \nConsumption',
phaseType: 'Phase B consumption',
phase: model.status.phaseB,
chartData: chartData,
blocProvider: blocProvider,
),
_buildPowerClampCard(
title: 'Phase C Energy \nConsumption',
phaseType: 'Phase C consumption',
phase: model.status.phaseC,
chartData: chartData,
blocProvider: blocProvider,
),
]),
),
),
_buildPageIndicator(),
],
);
},
),
),
);
}
PowerClampModel _initialPowerClampModel() {
return PowerClampModel(
productType: '',
productUuid: '',
status: PowerStatus(
phaseA: Phase(dataPoints: _emptyDataPoints()),
phaseB: Phase(dataPoints: _emptyDataPoints()),
phaseC: Phase(dataPoints: _emptyDataPoints()),
general: Phase(dataPoints: _emptyDataPoints()),
),
);
}
List<DataPoint> _emptyDataPoints() {
return [
DataPoint(
code: '',
customName: '',
dpId: 0,
time: 0,
type: '',
value: 0,
),
];
}
List<Widget> _buildPowerClampCards(PowerClampModel model,
List<EnergyData> chartData, PowerClampBloc blocProvider) {
return [
_buildPowerClampCard(
phaseType: '',
title: 'Total Energy \nConsumption',
phase: model.status.general,
isGeneral: true,
chartData: chartData,
blocProvider: blocProvider,
),
_buildPowerClampCard(
phaseType: 'Phase A consumption',
title: 'Phase A Energy \nConsumption',
phase: model.status.phaseA,
chartData: chartData,
blocProvider: blocProvider,
),
_buildPowerClampCard(
phaseType: 'Phase B consumption',
title: 'Phase B Energy \nConsumption',
phase: model.status.phaseB,
chartData: chartData,
blocProvider: blocProvider,
),
_buildPowerClampCard(
phaseType: 'Phase C consumption',
title: 'Phase C Energy \nConsumption',
phase: model.status.phaseC,
chartData: chartData,
blocProvider: blocProvider,
),
];
}
Widget _buildPowerClampCard({
required String title,
required String phaseType,
required Phase phase,
bool isGeneral = false,
required List<EnergyData> chartData,
required PowerClampBloc blocProvider,
}) {
return PowerClampCard(
dateTimeSelected:
'${blocProvider.dateTime!.day}/${blocProvider.dateTime!.month}/${blocProvider.dateTime!.year} ${blocProvider.endChartDate}',
energyConsumption: _getValueOrNA(phase.dataPoints, isGeneral ? 0 : 5),
title: title,
phaseType: phaseType,
isGeneral: isGeneral,
dateSwitcher: blocProvider.dateSwitcher(),
formattedDate: blocProvider.formattedDate,
selectDateEvent: () {
blocProvider.add(SelectDateEvent(context: context));
},
totalActiveGeneral: isGeneral ? _getValueOrNA(phase.dataPoints, 2) : null,
totalCurrentGeneral:
isGeneral ? _getValueOrNA(phase.dataPoints, 1) : null,
totalFrequencyGeneral:
isGeneral ? _getValueOrNA(phase.dataPoints, 4) : null,
totalFactor: !isGeneral ? _getValueOrNA(phase.dataPoints, 3) : null,
totalActive: !isGeneral ? _getValueOrNA(phase.dataPoints, 2) : null,
totalCurrent: !isGeneral ? _getValueOrNA(phase.dataPoints, 1) : null,
totalVoltage: !isGeneral ? _getValueOrNA(phase.dataPoints, 0) : null,
chartData: chartData,
context: context,
);
}
String _getValueOrNA(List<DataPoint> dataPoints, int index) {
return dataPoints.length > index
? dataPoints[index].value.toString()
: 'N/A';
}
Widget _buildPageIndicator() {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(_pageCount, (index) {
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.symmetric(horizontal: 4.0),
height: 10.0,
width: _currentPage == index ? 10.0 : 10.0,
decoration: BoxDecoration(
color:
_currentPage == index ? Colors.grey : ColorsManager.greyColor,
borderRadius: BorderRadius.circular(5.0),
),
);
}),
),
);
}
}
@@ -0,0 +1,312 @@
// import 'package:flutter/material.dart';
// import 'package:flutter_bloc/flutter_bloc.dart';
// import 'package:syncrow_app/features/devices/bloc/power_clamp_bloc/power_clamp_bloc.dart';
// import 'package:syncrow_app/features/devices/bloc/power_clamp_bloc/power_clamp_event.dart';
// import 'package:syncrow_app/features/devices/bloc/power_clamp_bloc/power_clamp_state.dart';
// import 'package:syncrow_app/features/devices/model/device_model.dart';
// import 'package:syncrow_app/features/devices/model/power_clamp_model.dart';
// import 'package:syncrow_app/features/devices/view/widgets/power_clamp/power_chart.dart';
// import 'package:syncrow_app/features/devices/view/widgets/power_clamp/power_clamp_card.dart';
// import 'package:syncrow_app/features/shared_widgets/default_container.dart';
// import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
// import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
// class PowerClampTestPage extends StatefulWidget {
// late final DeviceModel? device;
// PowerClampTestPage({super.key, this.device});
// @override
// _PowerClampTestPageState createState() => _PowerClampTestPageState();
// }
// class _PowerClampTestPageState extends State<PowerClampTestPage> {
// final PageController _pageController = PageController();
// int _currentPage = 0;
// final int _pageCount = 4;
// @override
// void initState() {
// super.initState();
// _pageController.addListener(() {
// int nextPage = _pageController.page?.round() ?? 0;
// if (_currentPage != nextPage) {
// setState(() {
// _currentPage = nextPage;
// });
// }
// });
// }
// @override
// void dispose() {
// _pageController.dispose();
// super.dispose();
// }
// @override
// Widget build(BuildContext context) {
// return DefaultScaffold(
// title: 'Power Clamp',
// child: BlocProvider(
// create: (context) => PowerClampBloc(PCId: widget.device?.uuid ?? '')
// ..add(const PowerClampInitial()),
// child: BlocBuilder<PowerClampBloc, PowerClampState>(
// builder: (context, state) {
// final _blocProvider = BlocProvider.of<PowerClampBloc>(context);
// PowerClampModel model = PowerClampModel(
// productType: '',
// productUuid: '',
// status: PowerStatus(
// phaseA: Phase(
// dataPoints: [
// DataPoint(
// code: '',
// customName: '',
// dpId: 0,
// time: 0,
// type: '',
// value: 0),
// ],
// ),
// phaseB: Phase(
// dataPoints: [
// DataPoint(
// code: '',
// customName: '',
// dpId: 0,
// time: 0,
// type: '',
// value: 0),
// ],
// ),
// phaseC: Phase(
// dataPoints: [
// DataPoint(
// code: '',
// customName: '',
// dpId: 0,
// time: 0,
// type: '',
// value: 0),
// ],
// ),
// general: Phase(
// dataPoints: [
// DataPoint(
// code: '',
// customName: '',
// dpId: 0,
// time: 0,
// type: '',
// value: 0),
// ],
// ),
// ),
// );
// List<EnergyData> chartData = [];
// if (state is UpdateState) {
// model = state.powerClampModel;
// } else if (state is EnergyDataState) {
// chartData = state.energyData;
// }
// return state is PowerClampLoadingState
// ? const Center(
// child: DefaultContainer(
// width: 50,
// height: 50,
// child: CircularProgressIndicator()),
// )
// : Column(
// children: [
// Flexible(
// child: RefreshIndicator(
// onRefresh: () async {
// _blocProvider.add(const PowerClampInitial());
// },
// child: PageView(
// controller: _pageController,
// children: [
// PowerClampCard(
// energyConsumption:
// model.status.general.dataPoints.length > 0
// ? model.status.general.dataPoints[0].value
// .toString()
// : 'N/A',
// title: 'Total Energy \nConsumption',
// isGeneral: true,
// dateSwitcher: Container(),
// formattedDate: _blocProvider.formattedDate,
// selectDateEvent: () {
// _blocProvider.add(
// SelectDateEvent(context: context));
// },
// totalFrequencyGeneral:
// model.status.general.dataPoints.length > 4
// ? model.status.general.dataPoints[4].value
// .toString()
// : 'N/A',
// totalActiveGeneral:
// model.status.general.dataPoints.length > 2
// ? model.status.general.dataPoints[2].value
// .toString()
// : 'N/A',
// totalCurrentGeneral:
// model.status.general.dataPoints.length > 1
// ? model.status.general.dataPoints[1].value
// .toString()
// : 'N/A',
// totalVoltage:
// model.status.general.dataPoints.length > 0
// ? model.status.general.dataPoints[0].value.toString()
// : 'N/A',
// chartData: chartData,
// context: context),
// PowerClampCard(
// energyConsumption:
// model.status.phaseA.dataPoints.length > 5
// ? model.status.phaseA.dataPoints[5].value
// .toString()
// : 'N/A',
// title: 'Phase A Energy \nConsumption',
// dateSwitcher: _blocProvider.dateSwitcher(),
// formattedDate: _blocProvider.formattedDate,
// selectDateEvent: () {
// _blocProvider.add(
// SelectDateEvent(context: context));
// },
// totalFactor: model.status.phaseA.dataPoints.length > 3
// ? model.status.phaseA.dataPoints[3].value
// .toString()
// : 'N/A',
// totalActive: model.status.phaseA.dataPoints.length > 2
// ? model.status.phaseA.dataPoints[2].value
// .toString()
// : 'N/A',
// totalCurrent:
// model.status.phaseA.dataPoints.length > 1
// ? model.status.phaseA.dataPoints[1]
// .value
// .toString()
// : 'N/A',
// totalVoltage:
// model.status.phaseA.dataPoints.length > 0
// ? model.status.phaseA.dataPoints[0]
// .value
// .toString()
// : 'N/A',
// chartData: chartData,
// context: context),
// PowerClampCard(
// energyConsumption:
// model.status.phaseB.dataPoints.length > 5
// ? model.status.phaseB.dataPoints[5].value
// .toString()
// : 'N/A',
// title: 'Phase B Energy \nConsumption',
// dateSwitcher: _blocProvider.dateSwitcher(),
// formattedDate: _blocProvider.formattedDate,
// selectDateEvent: () {
// _blocProvider.add(
// SelectDateEvent(context: context));
// },
// totalFactor: model.status.phaseA.dataPoints.length > 3
// ? model.status.phaseB.dataPoints[3].value
// .toString()
// : 'N/A',
// totalActive: model.status.phaseB.dataPoints.length > 2
// ? model.status.phaseB.dataPoints[2].value
// .toString()
// : 'N/A',
// totalCurrent:
// model.status.phaseB.dataPoints.length > 1
// ? model.status.phaseB.dataPoints[1]
// .value
// .toString()
// : 'N/A',
// totalVoltage:
// model.status.phaseB.dataPoints.length > 0
// ? model.status.phaseB.dataPoints[0]
// .value
// .toString()
// : 'N/A',
// chartData: chartData,
// context: context),
// PowerClampCard(
// energyConsumption:
// model.status.phaseC.dataPoints.length > 5
// ? model.status.phaseC.dataPoints[5].value
// .toString()
// : 'N/A',
// title: 'Phase A Energy \nConsumption',
// dateSwitcher: _blocProvider.dateSwitcher(),
// formattedDate: _blocProvider.formattedDate,
// selectDateEvent: () {
// _blocProvider.add(
// SelectDateEvent(context: context));
// },
// totalFactor: model.status.phaseC.dataPoints.length > 3
// ? model.status.phaseC.dataPoints[3].value
// .toString()
// : 'N/A',
// totalActive: model.status.phaseC.dataPoints.length > 2
// ? model.status.phaseC.dataPoints[2].value
// .toString()
// : 'N/A',
// totalCurrent:
// model.status.phaseC.dataPoints.length > 1
// ? model.status.phaseC.dataPoints[1]
// .value
// .toString()
// : 'N/A',
// totalVoltage:
// model.status.phaseC.dataPoints.length > 0
// ? model.status.phaseC.dataPoints[0]
// .value
// .toString()
// : 'N/A',
// chartData: chartData,
// context: context),
// ]),
// ),
// ),
// Padding(
// padding: const EdgeInsets.symmetric(vertical: 10.0),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: List.generate(_pageCount, (index) {
// return AnimatedContainer(
// duration: const Duration(milliseconds: 300),
// margin:
// const EdgeInsets.symmetric(horizontal: 4.0),
// height: 10.0,
// width: _currentPage == index
// ? 10.0
// : 10.0, // Change width for current page
// decoration: BoxDecoration(
// color: _currentPage == index
// ? Colors
// .grey // Use a different color for the active indicator
// : ColorsManager.greyColor,
// borderRadius: BorderRadius.circular(5.0),
// ),
// );
// }),
// ),
// ),
// ],
// );
// },
// ),
// ),
// );
// }
// }
@@ -0,0 +1,72 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class PowerClampInfoCard extends StatelessWidget {
final String iconPath;
final String title;
final String value;
final String unit;
const PowerClampInfoCard({
Key? key,
required this.iconPath,
required this.title,
required this.value,
required this.unit,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Expanded(
child: DefaultContainer(
height: 55,
color: ColorsManager.grayBox,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: SvgPicture.asset(
iconPath,
fit: BoxFit.contain,
),
),
Expanded(
flex: 3,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BodyMedium(
fontWeight: FontWeight.w400,
fontSize: 8,
text: title,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BodyMedium(
fontWeight: FontWeight.w700,
fontSize: 15,
text: value,
),
BodyMedium(
fontWeight: FontWeight.w700,
fontSize: 8,
text: unit,
),
],
),
],
),
)
],
),
),
);
}
}
@@ -1,30 +1,108 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/model/room_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/room_page_switch.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class RoomPage extends StatelessWidget {
class RoomPage extends StatefulWidget {
const RoomPage({super.key, required this.room});
final SubSpaceModel room;
@override
_RoomPageState createState() => _RoomPageState();
}
class _RoomPageState extends State<RoomPage> {
final TextEditingController _searchController = TextEditingController();
List<dynamic> _filteredDevices = [];
@override
void initState() {
super.initState();
_filteredDevices = widget.room.devices ?? [];
_searchController.addListener(_filterDevices);
}
@override
void dispose() {
_searchController.removeListener(_filterDevices);
_searchController.dispose();
super.dispose();
}
void _filterDevices() {
final query = _searchController.text.toLowerCase();
setState(() {
_filteredDevices = widget.room.devices!
.where((device) => device.type!.toLowerCase().contains(query))
.toList();
});
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1.5,
),
padding: const EdgeInsets.only(top: 10),
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: room.devices!.length,
itemBuilder: (context, index) {
return RoomPageSwitch(device: room.devices![index]);
},
),
return Column(
children: [
if (widget.room.devices!.isNotEmpty)
TextFormField(
controller: _searchController,
decoration: InputDecoration(
hintText: 'Search',
hintStyle: const TextStyle(
color: ColorsManager.textGray,
fontSize: 16,
fontWeight: FontWeight.w400),
prefixIcon: Container(
padding: const EdgeInsets.all(5.0),
margin: const EdgeInsets.all(10.0),
child: SvgPicture.asset(
Assets.searchIcon,
fit: BoxFit.contain,
),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
),
_filteredDevices.isNotEmpty
? Expanded(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1.5,
),
padding: const EdgeInsets.only(top: 10),
itemCount: _filteredDevices.length,
itemBuilder: (context, index) {
return RoomPageSwitch(device: _filteredDevices[index]);
},
),
)
: widget.room.devices!.isNotEmpty
? const Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: Text(
'No Results Found',
style: TextStyle(
color: ColorsManager.grayColor,
fontSize: 14,
fontWeight: FontWeight.w400),
)),
],
),
)
: const SizedBox(),
],
);
}
}
@@ -15,6 +15,7 @@ import 'package:syncrow_app/features/devices/view/widgets/gateway/gateway_view.d
import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_Interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/one_touch/one_touch_screen.dart';
import 'package:syncrow_app/features/devices/view/widgets/power_clamp/power_clamp_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_touch/three_touch_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_Interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_touch_Interface.dart';
@@ -171,6 +172,13 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
pageBuilder: (context, animation1, animation2) =>
DoorSensorScreen(device: device)));
case DeviceType.PC:
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
PowerClampPage(device: device)));
case DeviceType.OneTouch:
Navigator.push(
context,
@@ -40,13 +40,10 @@ class SceneListview extends StatelessWidget {
sceneName: scene.name,
),
);
context
.read<SmartSceneSelectBloc>()
.add(const SmartSceneClearEvent());
context.read<SmartSceneSelectBloc>().add(const SmartSceneClearEvent());
BlocProvider.of<CreateSceneBloc>(context).add(
FetchSceneTasksEvent(
sceneId: scene.id, isAutomation: false));
BlocProvider.of<CreateSceneBloc>(context)
.add(FetchSceneTasksEvent(sceneId: scene.id, isAutomation: false));
/// the state to set the scene type must be after the fetch
BlocProvider.of<CreateSceneBloc>(context)
@@ -59,11 +56,13 @@ class SceneListview extends StatelessWidget {
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset(
child: Image.memory(
height: 32,
width: 32,
Assets.assetsIconsLogo,
scene.iconInBytes,
fit: BoxFit.fill,
errorBuilder: (context, error, stackTrace) => Image.asset(
height: 32, width: 32, fit: BoxFit.fill, Assets.assetsIconsLogo),
),
),
Expanded(
+201 -113
View File
@@ -13,7 +13,9 @@ import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_touch_wi
import 'package:syncrow_app/features/devices/view/widgets/water_heater/wh_wizard.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class WizardPage extends StatelessWidget {
final List<DevicesCategoryModel> groupsList;
@@ -21,126 +23,212 @@ class WizardPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1.5,
),
padding: const EdgeInsets.only(top: 10),
shrinkWrap: true,
itemCount: groupsList.length,
itemBuilder: (_, index) {
return GestureDetector(
onTap: () {
if (groupsList[index].name == 'AC') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
const ACsView()));
}
if (groupsList[index].name == '3G') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
const ThreeGangWizard()));
}
if (groupsList[index].name == '2G') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
const TwoGangWizard()));
}
if (groupsList[index].name == '1G') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
const OneGangWizard()));
}
if (groupsList[index].name == 'WH') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
const WHWizard()));
}
final TextEditingController _searchController = TextEditingController();
List<DevicesCategoryModel> _filteredGroups = groupsList;
if (groupsList[index].name == '1GT') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
const OneTouchWizard()));
}
void _filterGroups(String query) {
_filteredGroups = groupsList
.where((group) =>
group.name!.toLowerCase().contains(query.toLowerCase()))
.toList();
}
if (groupsList[index].name == '2GT') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
const TwoTouchWizard()));
}
if (groupsList[index].name == '3GT') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
const ThreeTouchWizard()));
}
if (groupsList[index].name == 'GD') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
const GarageWizard()));
}
if (groupsList[index].name == 'CUR') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
const CurtainsWizard()));
}
},
child: DefaultContainer(
padding: const EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SvgPicture.asset(
groupsList[index].icon!,
return StatefulBuilder(
builder: (context, setState) {
return Column(
children: [
if (groupsList.isNotEmpty)
TextFormField(
controller: _searchController,
onChanged: (value) {
setState(() {
_filterGroups(value);
});
},
decoration: InputDecoration(
hintText: 'Search',
hintStyle: const TextStyle(
color: ColorsManager.textGray,
fontSize: 16,
fontWeight: FontWeight.w400),
prefixIcon: Container(
padding: const EdgeInsets.all(5.0),
margin: const EdgeInsets.all(10.0),
child: SvgPicture.asset(
Assets.searchIcon,
fit: BoxFit.contain,
),
// CustomSwitch(
],
),
FittedBox(
fit: BoxFit.scaleDown,
child: BodyLarge(
text: groupsList[index].name!,
style: context.bodyLarge.copyWith(
fontWeight: FontWeight.bold,
height: 0,
fontSize: 20,
color: Colors.grey,
),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
],
),
const SizedBox(
height: 10,
),
),
_filteredGroups.isNotEmpty
? Expanded(
child: ListView(
shrinkWrap: true,
children: [
GridView.builder(
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1.5,
),
padding: const EdgeInsets.only(top: 10),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: _filteredGroups.length,
itemBuilder: (_, index) {
return GestureDetector(
onTap: () {
if (_filteredGroups[index].name == 'AC') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1,
animation2) =>
const ACsView()));
}
if (_filteredGroups[index].name == '3G') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1,
animation2) =>
const ThreeGangWizard()));
}
if (_filteredGroups[index].name == '2G') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1,
animation2) =>
const TwoGangWizard()));
}
if (_filteredGroups[index].name == '1G') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1,
animation2) =>
const OneGangWizard()));
}
if (_filteredGroups[index].name == 'WH') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1,
animation2) =>
const WHWizard()));
}
if (_filteredGroups[index].name == '1GT') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1,
animation2) =>
const OneTouchWizard()));
}
if (_filteredGroups[index].name == '2GT') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1,
animation2) =>
const TwoTouchWizard()));
}
if (_filteredGroups[index].name == '3GT') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1,
animation2) =>
const ThreeTouchWizard()));
}
if (_filteredGroups[index].name == 'GD') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1,
animation2) =>
const GarageWizard()));
}
if (_filteredGroups[index].name == 'CUR') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1,
animation2) =>
const CurtainsWizard()));
}
},
child: DefaultContainer(
padding: const EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
SvgPicture.asset(
_filteredGroups[index].icon!,
fit: BoxFit.contain,
),
],
),
FittedBox(
fit: BoxFit.scaleDown,
child: BodyLarge(
text: _filteredGroups[index].name!,
style: context.bodyLarge.copyWith(
fontWeight: FontWeight.bold,
height: 0,
fontSize: 20,
color: Colors.grey,
),
),
),
],
),
),
);
},
)
],
),
)
: const Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: Text(
'No Results Found',
style: TextStyle(
color: ColorsManager.grayColor,
fontSize: 14,
fontWeight: FontWeight.w400),
)),
],
),
),
],
);
},
);