mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2026-10-23 09:47:54 +00:00
water leak
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="7.5" cy="7.5" r="5" stroke="#FF4756" stroke-width="5"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 171 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="7.5" cy="7.5" r="5" stroke="#023DFE" stroke-opacity="0.6" stroke-width="5"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 192 B |
@@ -28,7 +28,7 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
|
|||||||
bool closingReminder = false;
|
bool closingReminder = false;
|
||||||
bool waterAlarm = false;
|
bool waterAlarm = false;
|
||||||
WaterLeakModel deviceStatus =
|
WaterLeakModel deviceStatus =
|
||||||
WaterLeakModel(waterContactState: false, batteryPercentage: 0);
|
WaterLeakModel(waterContactState: 'normal', batteryPercentage: 0);
|
||||||
|
|
||||||
void _fetchStatus(
|
void _fetchStatus(
|
||||||
WaterLeakInitial event, Emitter<WaterLeakState> emit) async {
|
WaterLeakInitial event, Emitter<WaterLeakState> emit) async {
|
||||||
@@ -43,6 +43,7 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
|
|||||||
statusModelList,
|
statusModelList,
|
||||||
);
|
);
|
||||||
emit(UpdateState(waterSensor: deviceStatus));
|
emit(UpdateState(waterSensor: deviceStatus));
|
||||||
|
|
||||||
Future.delayed(const Duration(milliseconds: 500));
|
Future.delayed(const Duration(milliseconds: 500));
|
||||||
_listenToChanges();
|
_listenToChanges();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -115,39 +116,32 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceReport recordGroups = DeviceReport(
|
DeviceReport recordGroups =
|
||||||
startTime: '0',
|
DeviceReport(startTime: '0', endTime: '0', data: []);
|
||||||
endTime: '0',
|
|
||||||
data: [DeviceEvent(code: '111', eventTime: 23456789, value: 'tyuio')]);
|
|
||||||
|
|
||||||
Future<void> fetchLogsForLastMonth(
|
Future<void> fetchLogsForLastMonth(
|
||||||
ReportLogsInitial event, Emitter<WaterLeakState> emit) async {
|
ReportLogsInitial event, Emitter<WaterLeakState> emit) async {
|
||||||
// Get the current date and time
|
// Get the current date and time
|
||||||
DateTime now = DateTime.now();
|
DateTime now = DateTime.now();
|
||||||
|
|
||||||
// Calculate the date one month ago
|
|
||||||
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
|
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
|
||||||
|
|
||||||
// Convert the date to milliseconds since epoch (Unix timestamp in milliseconds)
|
|
||||||
int startTime = lastMonth.millisecondsSinceEpoch;
|
int startTime = lastMonth.millisecondsSinceEpoch;
|
||||||
int endTime = now.millisecondsSinceEpoch;
|
int endTime = now.millisecondsSinceEpoch;
|
||||||
try {
|
try {
|
||||||
emit(WaterLeakLoadingState());
|
emit(WaterLeakLoadingState());
|
||||||
// var response = await DevicesAPI.getReportLogs(
|
var response = await DevicesAPI.getReportLogs(
|
||||||
// startTime:
|
startTime: startTime.toString(),
|
||||||
// startTime.toString(), // Convert to String if the API expects it
|
endTime: endTime.toString(),
|
||||||
// endTime: endTime.toString(), // Convert to String if the API expects it
|
deviceUuid: WLId,
|
||||||
// deviceUuid: WLId,
|
code: 'watercontact_state',
|
||||||
// code: 'watercontact_state',
|
);
|
||||||
// );
|
recordGroups = response;
|
||||||
// print('response======${response}');
|
|
||||||
// recordGroups = response;
|
|
||||||
// Process response here
|
|
||||||
emit(UpdateState(waterSensor: deviceStatus));
|
emit(UpdateState(waterSensor: deviceStatus));
|
||||||
} on DioException catch (e) {
|
} on DioException catch (e) {
|
||||||
final errorData = e.response!.data;
|
final errorData = e.response!.data;
|
||||||
String errorMessage = errorData['message'];
|
String errorMessage = errorData['message'];
|
||||||
// Handle error
|
// Handle error
|
||||||
|
emit(WaterLeakFailedState(errorMessage: errorMessage));
|
||||||
|
|
||||||
print('Error fetching logs: ${errorMessage}');
|
print('Error fetching logs: ${errorMessage}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ abstract class WaterLeakEvent extends Equatable {
|
|||||||
class WaterLeakLoading extends WaterLeakEvent {}
|
class WaterLeakLoading extends WaterLeakEvent {}
|
||||||
|
|
||||||
class WaterLeakSwitch extends WaterLeakEvent {
|
class WaterLeakSwitch extends WaterLeakEvent {
|
||||||
final bool switchD;
|
final String switchD;
|
||||||
final String deviceId;
|
final String deviceId;
|
||||||
final String productId;
|
final String productId;
|
||||||
const WaterLeakSwitch({required this.switchD, this.deviceId = '', this.productId = ''});
|
const WaterLeakSwitch({required this.switchD, this.deviceId = '', this.productId = ''});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||||
|
|
||||||
class WaterLeakModel {
|
class WaterLeakModel {
|
||||||
bool waterContactState;
|
String waterContactState;
|
||||||
int batteryPercentage;
|
int batteryPercentage;
|
||||||
|
|
||||||
WaterLeakModel({
|
WaterLeakModel({
|
||||||
@@ -10,7 +10,7 @@ class WaterLeakModel {
|
|||||||
});
|
});
|
||||||
|
|
||||||
factory WaterLeakModel.fromJson(List<StatusModel> jsonList) {
|
factory WaterLeakModel.fromJson(List<StatusModel> jsonList) {
|
||||||
late bool _waterContactState;
|
late String _waterContactState;
|
||||||
late int _batteryPercentage;
|
late int _batteryPercentage;
|
||||||
|
|
||||||
for (int i = 0; i < jsonList.length; i++) {
|
for (int i = 0; i < jsonList.length; i++) {
|
||||||
|
|||||||
+52
-46
@@ -8,6 +8,7 @@ import 'package:syncrow_app/features/devices/bloc/water_leak_bloc/water_leak_sta
|
|||||||
import 'package:syncrow_app/features/shared_widgets/default_container.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/features/shared_widgets/default_scaffold.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.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/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
|
||||||
class NotificationSettingsPage extends StatelessWidget {
|
class NotificationSettingsPage extends StatelessWidget {
|
||||||
@@ -32,56 +33,61 @@ class NotificationSettingsPage extends StatelessWidget {
|
|||||||
: Column(
|
: Column(
|
||||||
children: [
|
children: [
|
||||||
DefaultContainer(
|
DefaultContainer(
|
||||||
child: Column(
|
child: Padding(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
padding: const EdgeInsets.only(left: 10, right: 10),
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
SizedBox(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
height: 50,
|
children: [
|
||||||
child: ListTile(
|
SizedBox(
|
||||||
contentPadding: EdgeInsets.zero,
|
height: 50,
|
||||||
leading: const BodyLarge(
|
child: ListTile(
|
||||||
text: 'Low Battery Alarm',
|
contentPadding: EdgeInsets.zero,
|
||||||
fontWeight: FontWeight.normal,
|
leading: const BodyMedium(
|
||||||
|
text: 'Low Battery Alarm',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 15,
|
||||||
|
),
|
||||||
|
trailing: Transform.scale(
|
||||||
|
scale: .8,
|
||||||
|
child: CupertinoSwitch(
|
||||||
|
value: waterLeakBloc.lowBattery,
|
||||||
|
onChanged: (value) {
|
||||||
|
context.read<WaterLeakBloc>().add(
|
||||||
|
ToggleLowBatteryEvent(value));
|
||||||
|
},
|
||||||
|
applyTheme: true,
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
trailing: Transform.scale(
|
|
||||||
scale: .8,
|
|
||||||
child: CupertinoSwitch(
|
|
||||||
value: waterLeakBloc.lowBattery,
|
|
||||||
onChanged: (value) {
|
|
||||||
context.read<WaterLeakBloc>().add(
|
|
||||||
ToggleLowBatteryEvent(value));
|
|
||||||
},
|
|
||||||
applyTheme: true,
|
|
||||||
)),
|
|
||||||
),
|
),
|
||||||
),
|
const Divider(
|
||||||
const Divider(
|
color: ColorsManager.graysColor,
|
||||||
color: ColorsManager.graysColor,
|
),
|
||||||
),
|
SizedBox(
|
||||||
SizedBox(
|
height: 50,
|
||||||
height: 50,
|
child: ListTile(
|
||||||
child: ListTile(
|
contentPadding: EdgeInsets.zero,
|
||||||
contentPadding: EdgeInsets.zero,
|
leading: const BodyLarge(
|
||||||
leading: const BodyLarge(
|
text: 'Water Leakage Alarm',
|
||||||
text: 'Water Leakage Alarm',
|
fontWeight: FontWeight.w400,
|
||||||
fontWeight: FontWeight.normal,
|
fontSize: 15,
|
||||||
|
),
|
||||||
|
trailing: Transform.scale(
|
||||||
|
scale: .8,
|
||||||
|
child: CupertinoSwitch(
|
||||||
|
value: waterLeakBloc.closingReminder,
|
||||||
|
onChanged: (value) {
|
||||||
|
context.read<WaterLeakBloc>().add(
|
||||||
|
ToggleClosingReminderEvent(
|
||||||
|
value));
|
||||||
|
},
|
||||||
|
applyTheme: true,
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
trailing: Transform.scale(
|
|
||||||
scale: .8,
|
|
||||||
child: CupertinoSwitch(
|
|
||||||
value: waterLeakBloc.closingReminder,
|
|
||||||
onChanged: (value) {
|
|
||||||
context.read<WaterLeakBloc>().add(
|
|
||||||
ToggleClosingReminderEvent(
|
|
||||||
value));
|
|
||||||
},
|
|
||||||
applyTheme: true,
|
|
||||||
)),
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/water_leak_bloc/water_leak_bloc.dart';
|
import 'package:syncrow_app/features/devices/bloc/water_leak_bloc/water_leak_bloc.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/water_leak_bloc/water_leak_event.dart';
|
import 'package:syncrow_app/features/devices/bloc/water_leak_bloc/water_leak_event.dart';
|
||||||
@@ -8,212 +9,214 @@ import 'package:syncrow_app/features/devices/model/device_report_model.dart';
|
|||||||
import 'package:syncrow_app/features/shared_widgets/default_container.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/features/shared_widgets/default_scaffold.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.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/context_extension.dart';
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
|
||||||
class WaterLeakRecordsScreen extends StatelessWidget {
|
class WaterLeakRecordsScreen extends StatefulWidget {
|
||||||
final String WLId;
|
final String WLId;
|
||||||
const WaterLeakRecordsScreen({super.key, required this.WLId});
|
const WaterLeakRecordsScreen({super.key, required this.WLId});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<WaterLeakRecordsScreen> createState() => _WaterLeakRecordsScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WaterLeakRecordsScreenState extends State<WaterLeakRecordsScreen> {
|
||||||
|
int _selectedIndex = 0; // Track the selected tab index
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DefaultScaffold(
|
return DefaultScaffold(
|
||||||
title: 'Records',
|
title: 'Records',
|
||||||
child: BlocProvider(
|
child: BlocProvider(
|
||||||
create: (context) =>
|
create: (context) =>
|
||||||
WaterLeakBloc(WLId: WLId ?? '')..add(const ReportLogsInitial()),
|
WaterLeakBloc(WLId: widget.WLId)..add(const ReportLogsInitial()),
|
||||||
child: BlocBuilder<WaterLeakBloc, WaterLeakState>(
|
child: BlocBuilder<WaterLeakBloc, WaterLeakState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final waterSensorBloc = BlocProvider.of<WaterLeakBloc>(context);
|
final waterSensorBloc = BlocProvider.of<WaterLeakBloc>(context);
|
||||||
final Map<String, List<DeviceEvent>> groupedRecords = {};
|
final Map<String, List<DeviceEvent>> groupedRecords = {};
|
||||||
|
|
||||||
if (state is WaterLeakLoadingState) {
|
if (state is WaterLeakLoadingState) {
|
||||||
return const Center(
|
return const Center(
|
||||||
child: DefaultContainer(
|
child: DefaultContainer(
|
||||||
width: 50, height: 50, child: CircularProgressIndicator()),
|
width: 50, height: 50, child: CircularProgressIndicator()),
|
||||||
);
|
);
|
||||||
} else if (state is UpdateState) {
|
} else if (state is UpdateState) {
|
||||||
// Group records by formatted date
|
for (var record in waterSensorBloc.recordGroups.data!) {
|
||||||
|
final DateTime eventDateTime =
|
||||||
|
DateTime.fromMillisecondsSinceEpoch(record.eventTime!);
|
||||||
|
final String formattedDate =
|
||||||
|
DateFormat('EEEE, dd/MM/yyyy').format(eventDateTime);
|
||||||
|
|
||||||
// Iterate over the data list in DeviceReport
|
if (groupedRecords.containsKey(formattedDate)) {
|
||||||
for (var record in waterSensorBloc.recordGroups.data!) {
|
groupedRecords[formattedDate]!.add(record);
|
||||||
final DateTime eventDateTime =
|
} else {
|
||||||
DateTime.fromMillisecondsSinceEpoch(record.eventTime!);
|
groupedRecords[formattedDate] = [record];
|
||||||
final String formattedDate =
|
}
|
||||||
DateFormat('EEEE, dd/MM/yyyy').format(eventDateTime);
|
|
||||||
|
|
||||||
// Group by formatted date
|
|
||||||
if (groupedRecords.containsKey(formattedDate)) {
|
|
||||||
groupedRecords[formattedDate]!.add(record);
|
|
||||||
} else {
|
|
||||||
groupedRecords[formattedDate] = [record];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return DefaultTabController(
|
return DefaultTabController(
|
||||||
// Wrap with DefaultTabController
|
length: 2,
|
||||||
length: 2,
|
child: Column(
|
||||||
child: Column(
|
children: [
|
||||||
children: [
|
Container(
|
||||||
Container(
|
width: MediaQuery.of(context).size.width,
|
||||||
width: MediaQuery.of(context).size.width,
|
decoration: const ShapeDecoration(
|
||||||
decoration: const ShapeDecoration(
|
color: ColorsManager.onPrimaryColor,
|
||||||
color: ColorsManager.onPrimaryColor,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(30)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: TabBar(
|
|
||||||
onTap: (value) {
|
|
||||||
// if (value == 0) {
|
|
||||||
// if (oneTouchBloc.createSchedule == true) {
|
|
||||||
// // oneTouchBloc.toggleCreateSchedule();
|
|
||||||
// oneTouchBloc
|
|
||||||
// .add(const ToggleCreateScheduleEvent(index: 0));
|
|
||||||
// }
|
|
||||||
// oneTouchBloc.add(const ToggleSelectedEvent(index: 0));
|
|
||||||
// } else {
|
|
||||||
// oneTouchBloc.add(const ToggleSelectedEvent(index: 1));
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
indicatorColor: Colors.white, // Customize the indicator
|
|
||||||
dividerHeight: 0,
|
|
||||||
indicatorSize: TabBarIndicatorSize.tab,
|
|
||||||
indicator: const ShapeDecoration(
|
|
||||||
color: ColorsManager.slidingBlueColor,
|
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
tabs: [
|
child: TabBar(
|
||||||
Tab(
|
onTap: (value) {
|
||||||
child: Container(
|
setState(() {
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
_selectedIndex = value; // Update selected index
|
||||||
child: BodySmall(
|
});
|
||||||
text: 'Record',
|
},
|
||||||
style: context.bodySmall.copyWith(
|
indicatorColor: Colors.white,
|
||||||
color: ColorsManager.blackColor,
|
dividerHeight: 0,
|
||||||
fontSize: 12,
|
indicatorSize: TabBarIndicatorSize.tab,
|
||||||
fontWeight: FontWeight.w400,
|
indicator: const ShapeDecoration(
|
||||||
|
color: ColorsManager.slidingBlueColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
tabs: [
|
||||||
|
Tab(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||||
|
child: BodySmall(
|
||||||
|
text: 'Record',
|
||||||
|
style: context.bodySmall.copyWith(
|
||||||
|
color: _selectedIndex == 0
|
||||||
|
? Colors.white
|
||||||
|
: ColorsManager.blackColor,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Tab(
|
||||||
Tab(
|
child: Container(
|
||||||
child: Container(
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
child: Text(
|
||||||
child: Text(
|
'Automation Record',
|
||||||
'Automation Record',
|
style: context.bodySmall.copyWith(
|
||||||
style: context.bodySmall.copyWith(
|
color: _selectedIndex == 1
|
||||||
color: ColorsManager.blackColor,
|
? Colors.white
|
||||||
fontSize: 12,
|
: ColorsManager.blackColor,
|
||||||
fontWeight: FontWeight.w400,
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
Expanded(
|
||||||
Expanded(
|
|
||||||
child: TabBarView(
|
child: TabBarView(
|
||||||
physics:
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
const NeverScrollableScrollPhysics(), // Disable swiping
|
children: [
|
||||||
|
groupedRecords.isEmpty
|
||||||
|
? const Center(child: Text('No data available.'))
|
||||||
|
: ListView.builder(
|
||||||
|
itemCount: groupedRecords.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final String date =
|
||||||
|
groupedRecords.keys.elementAt(index);
|
||||||
|
final List<DeviceEvent> recordsForDate =
|
||||||
|
groupedRecords[date]!;
|
||||||
|
|
||||||
children: [
|
return Column(
|
||||||
// Build the ListView with grouped data
|
crossAxisAlignment:
|
||||||
ListView.builder(
|
CrossAxisAlignment.start,
|
||||||
itemCount: groupedRecords.length,
|
children: [
|
||||||
itemBuilder: (context, index) {
|
Padding(
|
||||||
final String date =
|
padding: const EdgeInsets.all(16.0),
|
||||||
groupedRecords.keys.elementAt(index);
|
child: Text(
|
||||||
final List<DeviceEvent> recordsForDate =
|
date,
|
||||||
groupedRecords[date]!;
|
style: const TextStyle(
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
return Column(
|
fontSize: 13,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
fontWeight: FontWeight.w700,
|
||||||
children: [
|
|
||||||
// Date header
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: Text(
|
|
||||||
date,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: ColorsManager.grayColor,
|
|
||||||
fontSize: 13,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// List of records for the specific date
|
|
||||||
DefaultContainer(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
...recordsForDate
|
|
||||||
.asMap()
|
|
||||||
.entries
|
|
||||||
.map((entry) {
|
|
||||||
final int idx = entry.key;
|
|
||||||
final DeviceEvent record = entry.value;
|
|
||||||
final DateTime eventDateTime =
|
|
||||||
DateTime.fromMillisecondsSinceEpoch(
|
|
||||||
record.eventTime!);
|
|
||||||
final String formattedTime =
|
|
||||||
DateFormat('HH:mm:ss')
|
|
||||||
.format(eventDateTime);
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
child: ListTile(
|
|
||||||
leading: Icon(
|
|
||||||
record.value == 'true'
|
|
||||||
? Icons.radio_button_checked
|
|
||||||
: Icons
|
|
||||||
.radio_button_unchecked,
|
|
||||||
color: record.value == 'true'
|
|
||||||
? Colors.blue
|
|
||||||
: Colors.grey,
|
|
||||||
),
|
|
||||||
title: Text(
|
|
||||||
record.value == 'true'
|
|
||||||
? "Opened"
|
|
||||||
: "Closed",
|
|
||||||
style: const TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
subtitle: Text('$formattedTime'),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
// Only add Divider if it's not the last item
|
),
|
||||||
if (idx != recordsForDate.length - 1)
|
),
|
||||||
const Divider(
|
DefaultContainer(
|
||||||
color: ColorsManager.graysColor,
|
child: Column(
|
||||||
),
|
children: [
|
||||||
],
|
...recordsForDate
|
||||||
);
|
.asMap()
|
||||||
}).toList(),
|
.entries
|
||||||
],
|
.map((entry) {
|
||||||
),
|
final int idx = entry.key;
|
||||||
|
final DeviceEvent record =
|
||||||
|
entry.value;
|
||||||
|
final DateTime eventDateTime =
|
||||||
|
DateTime
|
||||||
|
.fromMillisecondsSinceEpoch(
|
||||||
|
record.eventTime!);
|
||||||
|
final String formattedTime =
|
||||||
|
DateFormat('HH:mm:ss')
|
||||||
|
.format(eventDateTime);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
leading: SvgPicture.asset(
|
||||||
|
record.value == 'true'
|
||||||
|
? Assets
|
||||||
|
.leakDetectedIcon
|
||||||
|
: Assets
|
||||||
|
.leakNormalIcon,
|
||||||
|
height: 25,
|
||||||
|
width: 25,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
record.value == 'true'
|
||||||
|
? "Normal"
|
||||||
|
: "Leak Detected",
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight:
|
||||||
|
FontWeight.bold,
|
||||||
|
fontSize: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle:
|
||||||
|
Text('$formattedTime'),
|
||||||
|
),
|
||||||
|
if (idx !=
|
||||||
|
recordsForDate.length - 1)
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager
|
||||||
|
.graysColor,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
Container(
|
||||||
);
|
height: 10,
|
||||||
},
|
width: 20,
|
||||||
),
|
),
|
||||||
Container(
|
],
|
||||||
height: 10,
|
),
|
||||||
width: 20,
|
),
|
||||||
)
|
],
|
||||||
]))
|
),
|
||||||
],
|
);
|
||||||
),
|
},
|
||||||
);
|
),
|
||||||
}
|
|
||||||
// return const Center(child: Text('No data available.'));
|
|
||||||
// },
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,13 +29,14 @@ class WaterLeakScreen extends StatelessWidget {
|
|||||||
child: BlocBuilder<WaterLeakBloc, WaterLeakState>(
|
child: BlocBuilder<WaterLeakBloc, WaterLeakState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final waterLeakBloc = BlocProvider.of<WaterLeakBloc>(context);
|
final waterLeakBloc = BlocProvider.of<WaterLeakBloc>(context);
|
||||||
WaterLeakModel model =
|
WaterLeakModel model = WaterLeakModel(
|
||||||
WaterLeakModel(batteryPercentage: 0, waterContactState: false);
|
batteryPercentage: 0, waterContactState: 'normal');
|
||||||
if (state is LoadingNewSate) {
|
if (state is LoadingNewSate) {
|
||||||
model = state.waterSensor;
|
model = state.waterSensor;
|
||||||
} else if (state is UpdateState) {
|
} else if (state is UpdateState) {
|
||||||
model = state.waterSensor;
|
model = state.waterSensor;
|
||||||
}
|
}
|
||||||
|
print(model.batteryPercentage);
|
||||||
return state is WaterLeakLoadingState
|
return state is WaterLeakLoadingState
|
||||||
? const Center(
|
? const Center(
|
||||||
child: DefaultContainer(
|
child: DefaultContainer(
|
||||||
@@ -97,7 +98,7 @@ class WaterLeakScreen extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
model.waterContactState
|
model.waterContactState == 'normal'
|
||||||
? Assets.normalWaterLeak
|
? Assets.normalWaterLeak
|
||||||
: Assets.detectedWaterLeak,
|
: Assets.detectedWaterLeak,
|
||||||
fit: BoxFit.fill,
|
fit: BoxFit.fill,
|
||||||
@@ -116,7 +117,8 @@ class WaterLeakScreen extends StatelessWidget {
|
|||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
WaterLeakRecordsScreen(WLId: device!.uuid!)),
|
WaterLeakRecordsScreen(
|
||||||
|
WLId: device!.uuid!)),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -138,7 +140,6 @@ class WaterLeakScreen extends StatelessWidget {
|
|||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
child: BodySmall(
|
child: BodySmall(
|
||||||
text: 'Records',
|
text: 'Records',
|
||||||
// doorLockButtons.keys.elementAt(index),
|
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -155,7 +156,8 @@ class WaterLeakScreen extends StatelessWidget {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => NotificationSettingsPage()),
|
builder: (context) =>
|
||||||
|
NotificationSettingsPage()),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|||||||
@@ -1076,4 +1076,7 @@ class Assets {
|
|||||||
"assets/icons/detected_water_leak.svg";
|
"assets/icons/detected_water_leak.svg";
|
||||||
|
|
||||||
static const String waterLeakIcon = "assets/icons/waterleak_icon.svg";
|
static const String waterLeakIcon = "assets/icons/waterleak_icon.svg";
|
||||||
|
static const String leakDetectedIcon = "assets/icons/leak_detected.svg";
|
||||||
|
static const String leakNormalIcon = "assets/icons/leak_normal_icon.svg";
|
||||||
|
//leakNormalIcon
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ class DevicesAPI {
|
|||||||
.replaceAll('{deviceUuid}', deviceId),
|
.replaceAll('{deviceUuid}', deviceId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
|
print(json);
|
||||||
return json;
|
return json;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user