push garage partial garage door

This commit is contained in:
ashrafzarkanisala
2024-10-06 15:09:36 +03:00
parent b9bc2ec186
commit 1e2e2bf4e6
15 changed files with 1610 additions and 76 deletions

View File

@ -0,0 +1,212 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_bloc.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_event.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_state.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/helper/garage_door_helper.dart';
import 'package:syncrow_web/pages/device_managment/water_heater/models/schedule_model.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:syncrow_web/utils/format_date_time.dart';
class ScheduleGarageTableWidget extends StatelessWidget {
final GarageDoorLoadedState state;
const ScheduleGarageTableWidget({
super.key,
required this.state,
});
@override
Widget build(BuildContext context) {
return Column(
children: [
Table(
border: TableBorder.all(
color: ColorsManager.graysColor,
borderRadius: const BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)),
),
children: [
TableRow(
decoration: const BoxDecoration(
color: ColorsManager.boxColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
children: [
_buildTableHeader('Active'),
_buildTableHeader('Days'),
_buildTableHeader('Time'),
_buildTableHeader('Function'),
_buildTableHeader('Action'),
],
),
],
),
BlocBuilder<GarageDoorBloc, GarageDoorState>(
builder: (context, state) {
if (state is ScheduleGarageLoadingState) {
return const SizedBox(height: 200, child: Center(child: CircularProgressIndicator()));
}
if (state is GarageDoorLoadedState && state.schedules?.isEmpty == true) {
return _buildEmptyState(context);
} else if (state is GarageDoorLoadedState) {
return Container(
height: 200,
decoration: BoxDecoration(
border: Border.all(color: ColorsManager.graysColor),
borderRadius:
const BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)),
),
child: _buildTableBody(state, context));
}
return const SizedBox(
height: 200,
);
},
),
],
);
}
Widget _buildEmptyState(BuildContext context) {
return Container(
height: 200,
decoration: BoxDecoration(
border: Border.all(color: ColorsManager.graysColor),
borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)),
),
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SvgPicture.asset(Assets.emptyRecords, width: 40, height: 40),
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'No schedules added yet',
style: context.textTheme.bodySmall!.copyWith(
fontSize: 13,
color: ColorsManager.grayColor,
),
),
),
],
),
),
);
}
Widget _buildTableBody(GarageDoorLoadedState state, BuildContext context) {
return SizedBox(
height: 200,
child: SingleChildScrollView(
child: Table(
border: TableBorder.all(color: ColorsManager.graysColor),
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
children: [
if (state.schedules != null)
for (int i = 0; i < state.schedules!.length; i++)
_buildScheduleRow(state.schedules![i], i, context, state),
],
),
),
);
}
Widget _buildTableHeader(String label) {
return TableCell(
child: Padding(
padding: const EdgeInsets.all(12),
child: Text(
label,
style: const TextStyle(
fontSize: 13,
color: ColorsManager.grayColor,
),
),
),
);
}
TableRow _buildScheduleRow(ScheduleModel schedule, int index, BuildContext context, GarageDoorLoadedState state) {
return TableRow(
children: [
Center(
child: GestureDetector(
onTap: () {
context.read<GarageDoorBloc>().add(UpdateGarageDoorScheduleEvent(
index: index,
enable: !schedule.enable,
scheduleId: schedule.scheduleId,
deviceId: state.status.uuid,
functionOn: schedule.function.value,
));
},
child: SizedBox(
width: 24,
height: 24,
child: schedule.enable
? const Icon(Icons.radio_button_checked, color: ColorsManager.blueColor)
: const Icon(
Icons.radio_button_unchecked,
color: ColorsManager.grayColor,
),
),
),
),
Center(child: Text(_getSelectedDays(ScheduleModel.parseSelectedDays(schedule.days)))),
Center(child: Text(formatIsoStringToTime(schedule.time, context))),
Center(child: Text(schedule.function.value ? 'On' : 'Off')),
Center(
child: Wrap(
runAlignment: WrapAlignment.center,
children: [
TextButton(
style: TextButton.styleFrom(padding: EdgeInsets.zero),
onPressed: () {
ScheduleGarageDoorDialogHelper.showAddGarageDoorScheduleDialog(context,
schedule: schedule, index: index, isEdit: true);
},
child: Text(
'Edit',
style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.blueColor),
),
),
TextButton(
style: TextButton.styleFrom(padding: EdgeInsets.zero),
onPressed: () {
context.read<GarageDoorBloc>().add(DeleteGarageDoorScheduleEvent(
index: index,
scheduleId: schedule.scheduleId,
deviceId: state.status.uuid,
));
},
child: Text(
'Delete',
style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.blueColor),
),
),
],
),
),
],
);
}
String _getSelectedDays(List<bool> selectedDays) {
final days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
List<String> selectedDaysStr = [];
for (int i = 0; i < selectedDays.length; i++) {
if (selectedDays[i]) {
selectedDaysStr.add(days[i]);
}
}
return selectedDaysStr.join(', ');
}
}

View File

@ -0,0 +1,46 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class ScheduleGarageHeader extends StatelessWidget {
const ScheduleGarageHeader({super.key});
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const SizedBox(),
Text(
'Scheduling',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22,
color: ColorsManager.dialogBlueTitle,
),
),
Container(
width: 25,
decoration: BoxDecoration(
color: Colors.transparent,
shape: BoxShape.circle,
border: Border.all(
color: Colors.grey,
width: 1.0,
),
),
child: IconButton(
padding: const EdgeInsets.all(1),
icon: const Icon(
Icons.close,
color: Colors.grey,
size: 18,
),
onPressed: () {
Navigator.of(context).pop();
},
),
),
],
);
}
}

View File

@ -0,0 +1,50 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_state.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/widgets/schedule__garage_table.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
class ScheduleGarageManagementUI extends StatelessWidget {
final GarageDoorLoadedState state;
final Function onAddSchedule;
const ScheduleGarageManagementUI({
super.key,
required this.state,
required this.onAddSchedule,
});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 170,
height: 40,
child: DefaultButton(
borderColor: ColorsManager.boxColor,
padding: 2,
backgroundColor: ColorsManager.graysColor,
borderRadius: 15,
onPressed: () => onAddSchedule(),
child: Row(
children: [
const Icon(Icons.add, color: ColorsManager.primaryColor),
Text(
' Add new schedule',
style: context.textTheme.bodySmall!.copyWith(
color: ColorsManager.blackColor,
),
),
],
),
),
),
const SizedBox(height: 20),
ScheduleGarageTableWidget(state: state),
],
);
}
}

View File

@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
class ScheduleModeButtons extends StatelessWidget {
final VoidCallback onSave;
const ScheduleModeButtons({
super.key,
required this.onSave,
});
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: DefaultButton(
height: 40,
onPressed: () {
Navigator.pop(context);
},
backgroundColor: ColorsManager.boxColor,
child: Text(
'Cancel',
style: context.textTheme.bodyMedium,
),
),
),
const SizedBox(width: 20),
Expanded(
child: DefaultButton(
height: 40,
onPressed: onSave,
backgroundColor: ColorsManager.primaryColor,
child: const Text('Save'),
),
),
],
);
}
}

View File

@ -0,0 +1,68 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_bloc.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_event.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_state.dart';
import 'package:syncrow_web/pages/device_managment/water_heater/models/water_heater_status_model.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
class ScheduleGarageDoorModeSelector extends StatelessWidget {
final GarageDoorLoadedState state;
const ScheduleGarageDoorModeSelector({super.key, required this.state});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Type:',
style: context.textTheme.bodySmall!.copyWith(
fontSize: 13,
color: ColorsManager.grayColor,
),
),
const SizedBox(height: 4),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildRadioTile(context, 'Schedule', ScheduleModes.schedule, state),
],
),
],
);
}
Widget _buildRadioTile(BuildContext context, String label, ScheduleModes mode, GarageDoorLoadedState state) {
return Flexible(
child: ListTile(
contentPadding: EdgeInsets.zero,
title: Text(
label,
style: context.textTheme.bodySmall!.copyWith(
fontSize: 13,
color: ColorsManager.blackColor,
),
),
leading: Radio<ScheduleModes>(
value: mode,
groupValue: state.scheduleMode,
onChanged: (ScheduleModes? value) {
if (value != null) {
if (value == ScheduleModes.schedule) {
context.read<GarageDoorBloc>().add(
FetchGarageDoorSchedulesEvent(
category: 'switch_1',
deviceId: state.status.uuid,
),
);
}
}
},
),
),
);
}
}

View File

@ -0,0 +1,84 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_bloc.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_state.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/helper/garage_door_helper.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/models/garage_door_model.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/widgets/schedule_garage_header.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/widgets/schedule_garage_managment_ui.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/widgets/schedule_garage_mode_selector.dart';
class BuildGarageDoorScheduleView extends StatefulWidget {
const BuildGarageDoorScheduleView({super.key, required this.status});
final GarageDoorStatusModel status;
@override
State<BuildGarageDoorScheduleView> createState() => _BuildScheduleViewState();
}
class _BuildScheduleViewState extends State<BuildGarageDoorScheduleView> {
@override
Widget build(BuildContext context) {
final bloc = BlocProvider.of<GarageDoorBloc>(context);
return BlocProvider.value(
value: bloc,
child: Dialog(
backgroundColor: Colors.white,
insetPadding: const EdgeInsets.all(20),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: SizedBox(
width: 700,
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0, vertical: 20),
child: BlocBuilder<GarageDoorBloc, GarageDoorState>(
builder: (context, state) {
if (state is GarageDoorLoadedState) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const ScheduleGarageHeader(),
const SizedBox(height: 20),
ScheduleGarageDoorModeSelector(state: state),
const SizedBox(height: 20),
ScheduleGarageManagementUI(
state: state,
onAddSchedule: () {
ScheduleGarageDoorDialogHelper.showAddGarageDoorScheduleDialog(context,
schedule: null, index: null, isEdit: false);
},
),
],
);
}
if (state is GarageDoorLoadingState) {
return const SizedBox(
height: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ScheduleGarageHeader(),
SizedBox(
height: 20,
),
Center(child: CircularProgressIndicator()),
],
));
}
return const SizedBox(
height: 200,
child: ScheduleGarageHeader(),
);
},
),
),
),
),
),
);
}
}