mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-11-26 20:34:55 +00:00
Implemented home management and user invitation flows
This commit is contained in:
@ -1,9 +1,11 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/auth/model/user_model.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/create_unit_bloc/create_unit_event.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/create_unit_bloc/create_unit_state.dart';
|
||||
import 'package:syncrow_app/services/api/home_creation_api.dart';
|
||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
|
||||
class CreateUnitBloc extends Bloc<CreateUnitEvent, CreateUnitState> {
|
||||
List<String> rooms = [];
|
||||
@ -45,11 +47,16 @@ class CreateUnitBloc extends Bloc<CreateUnitEvent, CreateUnitState> {
|
||||
|
||||
void _save(SaveRooms event, Emitter<CreateUnitState> emit) async {
|
||||
try {
|
||||
emit(LoadingState());
|
||||
if (rooms.isEmpty) {
|
||||
const ErrorState(message: 'Please add at least one room!');
|
||||
if (event.unitName.isEmpty) {
|
||||
CustomSnackBar.displaySnackBar('Please enter the unit name');
|
||||
return;
|
||||
}
|
||||
if (rooms.isEmpty) {
|
||||
CustomSnackBar.displaySnackBar('Please add at least one room!');
|
||||
return;
|
||||
}
|
||||
|
||||
emit(LoadingState());
|
||||
|
||||
var storage = const FlutterSecureStorage();
|
||||
var userId = await storage.read(key: UserModel.userUuidKey) ?? '';
|
||||
@ -83,6 +90,7 @@ class CreateUnitBloc extends Bloc<CreateUnitEvent, CreateUnitState> {
|
||||
}
|
||||
// }
|
||||
}
|
||||
await HomeCubit.getInstance().fetchUnitsByUserId();
|
||||
emit(RoomsSavedSuccessfully());
|
||||
} catch (_) {
|
||||
emit(const ErrorState(message: 'Something went wrong'));
|
||||
|
||||
112
lib/features/menu/bloc/manage_unit_bloc/manage_unit_bloc.dart
Normal file
112
lib/features/menu/bloc/manage_unit_bloc/manage_unit_bloc.dart
Normal file
@ -0,0 +1,112 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_event.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_state.dart';
|
||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
import 'package:syncrow_app/services/api/home_creation_api.dart';
|
||||
import 'package:syncrow_app/services/api/home_management_api.dart';
|
||||
import 'package:syncrow_app/services/api/spaces_api.dart';
|
||||
|
||||
class ManageUnitBloc extends Bloc<ManageUnitEvent, ManageUnitState> {
|
||||
List<DeviceModel> allDevices = [];
|
||||
String unitName = '';
|
||||
|
||||
ManageUnitBloc() : super(InitialState()) {
|
||||
on<FetchRoomsEvent>(_fetchRoomsAndDevices);
|
||||
on<FetchDevicesByRoomIdEvent>(_fetchDevicesByRoomId);
|
||||
on<AssignRoomEvent>(_assignDevice);
|
||||
on<AddNewRoom>(_addNewRoom);
|
||||
}
|
||||
|
||||
void _fetchRoomsAndDevices(FetchRoomsEvent event, Emitter<ManageUnitState> emit) async {
|
||||
try {
|
||||
emit(LoadingState());
|
||||
final roomsList = await SpacesAPI.getRoomsBySpaceId(event.unitId);
|
||||
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
|
||||
} catch (e) {
|
||||
emit(const ErrorState(message: 'Something went wrong'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _fetchDevicesByRoomId(FetchDevicesByRoomIdEvent event, Emitter<ManageUnitState> emit) async {
|
||||
try {
|
||||
Map<String, bool> roomDevicesId = {};
|
||||
emit(LoadingState());
|
||||
final devicesList = await DevicesAPI.getDevicesByRoomId(event.roomId);
|
||||
allDevices = await HomeManagementAPI.fetchDevicesByUserId();
|
||||
|
||||
List<String> allDevicesIds = [];
|
||||
|
||||
allDevices.forEach((element) {
|
||||
allDevicesIds.add(element.uuid!);
|
||||
});
|
||||
|
||||
devicesList.forEach((e) {
|
||||
if (allDevicesIds.contains(e.uuid!)) {
|
||||
roomDevicesId[e.uuid!] = true;
|
||||
} else {
|
||||
roomDevicesId[e.uuid!] = false;
|
||||
}
|
||||
});
|
||||
emit(FetchDeviceByRoomIdState(
|
||||
roomDevices: devicesList,
|
||||
allDevices: allDevices,
|
||||
roomDevicesId: roomDevicesId,
|
||||
roomId: event.roomId));
|
||||
} catch (e) {
|
||||
emit(const ErrorState(message: 'Something went wrong'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _assignDevice(AssignRoomEvent event, Emitter<ManageUnitState> emit) async {
|
||||
try {
|
||||
Map<String, bool> roomDevicesId = {};
|
||||
emit(LoadingState());
|
||||
Map<String, String> body = {"deviceUuid": event.deviceId, "roomUuid": event.roomId};
|
||||
await HomeManagementAPI.assignDeviceToRoom(body);
|
||||
final devicesList = await DevicesAPI.getDevicesByRoomId(event.roomId);
|
||||
|
||||
List<String> allDevicesIds = [];
|
||||
|
||||
allDevices.forEach((element) {
|
||||
allDevicesIds.add(element.uuid!);
|
||||
});
|
||||
|
||||
devicesList.forEach((e) {
|
||||
if (allDevicesIds.contains(e.uuid!)) {
|
||||
roomDevicesId[e.uuid!] = true;
|
||||
} else {
|
||||
roomDevicesId[e.uuid!] = false;
|
||||
}
|
||||
});
|
||||
emit(FetchDeviceByRoomIdState(
|
||||
roomDevices: devicesList,
|
||||
allDevices: allDevices,
|
||||
roomDevicesId: roomDevicesId,
|
||||
roomId: event.roomId));
|
||||
} catch (e) {
|
||||
emit(const ErrorState(message: 'Something went wrong'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_addNewRoom(AddNewRoom event, Emitter<ManageUnitState> emit) async {
|
||||
Map<String, String> body = {'roomName': event.roomName, 'unitUuid': event.unitId};
|
||||
try {
|
||||
emit(LoadingState());
|
||||
final response = await HomeCreation.createRoom(body);
|
||||
if (response['data']['uuid'] != '') {
|
||||
final roomsList = await SpacesAPI.getRoomsBySpaceId(event.unitId);
|
||||
allDevices = await HomeManagementAPI.fetchDevicesByUserId();
|
||||
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
|
||||
} else {
|
||||
emit(const ErrorState(message: 'Something went wrong'));
|
||||
}
|
||||
} catch (_) {
|
||||
emit(const ErrorState(message: 'Something went wrong'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class ManageUnitEvent extends Equatable {
|
||||
const ManageUnitEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class InitialEvent extends ManageUnitEvent {}
|
||||
|
||||
class LoadingEvent extends ManageUnitEvent {}
|
||||
|
||||
class FetchRoomsEvent extends ManageUnitEvent {
|
||||
final String unitId;
|
||||
|
||||
const FetchRoomsEvent({required this.unitId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [unitId];
|
||||
}
|
||||
|
||||
class FetchDevicesByRoomIdEvent extends ManageUnitEvent {
|
||||
final String roomId;
|
||||
|
||||
const FetchDevicesByRoomIdEvent({required this.roomId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [roomId];
|
||||
}
|
||||
|
||||
class AddNewRoom extends ManageUnitEvent {
|
||||
final String roomName;
|
||||
final String unitId;
|
||||
|
||||
const AddNewRoom({required this.roomName, required this.unitId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [roomName, unitId];
|
||||
}
|
||||
|
||||
class AssignRoomEvent extends ManageUnitEvent {
|
||||
final String roomId;
|
||||
final String deviceId;
|
||||
|
||||
const AssignRoomEvent({required this.roomId, required this.deviceId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [roomId];
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||
|
||||
abstract class ManageUnitState extends Equatable {
|
||||
const ManageUnitState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class InitialState extends ManageUnitState {}
|
||||
|
||||
class LoadingState extends ManageUnitState {}
|
||||
|
||||
class FetchRoomsState extends ManageUnitState {
|
||||
final List<RoomModel> roomsList;
|
||||
final List<DeviceModel> devicesList;
|
||||
|
||||
const FetchRoomsState({required this.devicesList, required this.roomsList});
|
||||
|
||||
@override
|
||||
List<Object> get props => [devicesList];
|
||||
}
|
||||
|
||||
class FetchDeviceByRoomIdState extends ManageUnitState {
|
||||
final List<DeviceModel> roomDevices;
|
||||
final List<DeviceModel> allDevices;
|
||||
final Map<String, bool> roomDevicesId;
|
||||
final String roomId;
|
||||
|
||||
const FetchDeviceByRoomIdState(
|
||||
{required this.roomDevices,
|
||||
required this.allDevices,
|
||||
required this.roomDevicesId,
|
||||
required this.roomId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [roomDevices, allDevices, roomDevicesId, roomId];
|
||||
}
|
||||
|
||||
class AssignRoomState extends ManageUnitState {}
|
||||
|
||||
class ErrorState extends ManageUnitState {
|
||||
final String message;
|
||||
|
||||
const ErrorState({required this.message});
|
||||
|
||||
@override
|
||||
List<Object> get props => [message];
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
// ignore_for_file: unnecessary_const
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/create_unit_bloc/create_unit_bloc.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/create_unit_bloc/create_unit_event.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/create_unit_bloc/create_unit_state.dart';
|
||||
@ -23,245 +23,257 @@ class CreateUnitView extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
String unitName = '';
|
||||
String location = '';
|
||||
TextEditingController textEditingController = TextEditingController();
|
||||
|
||||
return BlocProvider(
|
||||
create: (context) => CreateUnitBloc(),
|
||||
child: BlocConsumer<CreateUnitBloc, CreateUnitState>(listener: (context, state) {
|
||||
if (state is RoomsSavedSuccessfully) {
|
||||
CustomSnackBar.displaySnackBar('Saved successfully');
|
||||
NavigationService.navigatorKey.currentState!.pushNamedAndRemoveUntil(
|
||||
Routes.homeRoute,
|
||||
(Route route) => false,
|
||||
);
|
||||
}
|
||||
child: BlocConsumer<CreateUnitBloc, CreateUnitState>(
|
||||
listener: (context, state) {
|
||||
if (state is RoomsSavedSuccessfully) {
|
||||
CustomSnackBar.displaySnackBar('Unit created successfully');
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
if (state is ErrorState) {
|
||||
CustomSnackBar.displaySnackBar(state.message);
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
textEditingController.text = '';
|
||||
return DefaultScaffold(
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
if (unitName.isNotEmpty) {
|
||||
if (state is ErrorState) {
|
||||
CustomSnackBar.displaySnackBar(state.message);
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
textEditingController.text = '';
|
||||
return DefaultScaffold(
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
BlocProvider.of<CreateUnitBloc>(context).add(SaveRooms(
|
||||
communityName: 'Community Test',
|
||||
buildingName: 'Building Test',
|
||||
floorName: 'Floor Test',
|
||||
unitName: unitName));
|
||||
} else {
|
||||
CustomSnackBar.displaySnackBar('Please enter the unit name');
|
||||
}
|
||||
},
|
||||
child: const BodyLarge(
|
||||
text: 'Save',
|
||||
fontWeight: FontWeight.bold,
|
||||
communityName: 'Community Test',
|
||||
buildingName: 'Building Test',
|
||||
floorName: 'Floor Test',
|
||||
unitName: unitName,
|
||||
));
|
||||
},
|
||||
child: const BodyLarge(
|
||||
text: 'Save',
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
title: 'Create a Unit',
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 40),
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
//Home Info
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 25,
|
||||
vertical: 5,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const BodyMedium(text: 'Unit Name'),
|
||||
Flexible(
|
||||
child: TextField(
|
||||
textAlign: TextAlign.end,
|
||||
onChanged: (value) {
|
||||
unitName = value;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Enter Name',
|
||||
hintStyle: context.bodyMedium.copyWith(color: Colors.grey),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
),
|
||||
],
|
||||
title: 'Create a Unit',
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 40),
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
child: state is LoadingState
|
||||
? const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
// Home Info
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 25,
|
||||
vertical: 5,
|
||||
),
|
||||
],
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const BodyMedium(text: 'Location '),
|
||||
Flexible(
|
||||
child: TextField(
|
||||
textAlign: TextAlign.end,
|
||||
onChanged: (value) {
|
||||
location = value;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Set',
|
||||
hintStyle: context.bodyMedium.copyWith(color: Colors.grey),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
//Rooms Info
|
||||
const SizedBox(height: 10),
|
||||
const Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 25,
|
||||
),
|
||||
BodySmall(
|
||||
text: 'Spaces',
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 25,
|
||||
vertical: 5,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
if (state is CreateRoomState)
|
||||
if (state.roomList.isNotEmpty)
|
||||
Column(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: (state.roomList.length) * 55,
|
||||
child: ListView.separated(
|
||||
physics:
|
||||
const NeverScrollableScrollPhysics(), // Disable scrolling
|
||||
separatorBuilder: (context, index) => const Divider(
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
itemCount: state.roomList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Dismissible(
|
||||
key: Key(state.roomList[index]),
|
||||
background: Container(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
alignment: AlignmentDirectional.centerEnd,
|
||||
decoration: ShapeDecoration(
|
||||
color: const Color(0xFFFF0000),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(index == 0 ? 20 : 0),
|
||||
topRight: Radius.circular(index == 0 ? 20 : 0),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: SvgPicture.asset(
|
||||
Assets.assetsDeleteIcon,
|
||||
width: 20,
|
||||
height: 22,
|
||||
),
|
||||
),
|
||||
direction: DismissDirection.endToStart,
|
||||
onDismissed: (direction) {
|
||||
String removedUnit = state.roomList[index];
|
||||
|
||||
BlocProvider.of<CreateUnitBloc>(context)
|
||||
.add(RemoveRoomEvent(roomName: removedUnit));
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('$removedUnit removed')),
|
||||
);
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const BodyMedium(text: 'Unit Name'),
|
||||
Flexible(
|
||||
child: TextField(
|
||||
textAlign: TextAlign.end,
|
||||
onChanged: (value) {
|
||||
unitName = value;
|
||||
},
|
||||
child: Container(
|
||||
height: 50,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
state.roomList[index],
|
||||
style: const TextStyle(
|
||||
color: Color(0xFF5D5D5D),
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Enter Name',
|
||||
hintStyle:
|
||||
context.bodyMedium.copyWith(color: Colors.grey),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
if (textEditingController.text.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Please add the room name')),
|
||||
);
|
||||
return;
|
||||
}
|
||||
BlocProvider.of<CreateUnitBloc>(context)
|
||||
.add(CreateRoomEvent(roomName: textEditingController.text));
|
||||
},
|
||||
child: const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodyMedium(
|
||||
text: 'Add Space',
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
const BodyMedium(text: 'Location '),
|
||||
Flexible(
|
||||
child: TextField(
|
||||
textAlign: TextAlign.end,
|
||||
onChanged: (value) {},
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Set',
|
||||
hintStyle:
|
||||
context.bodyMedium.copyWith(color: Colors.grey),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
Flexible(
|
||||
child: TextField(
|
||||
textAlign: TextAlign.end,
|
||||
controller: textEditingController,
|
||||
onChanged: (value) {
|
||||
textEditingController.text = value;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Set',
|
||||
hintStyle: context.bodyMedium.copyWith(color: Colors.grey),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Rooms Info
|
||||
const SizedBox(height: 10),
|
||||
const Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 25,
|
||||
),
|
||||
BodySmall(
|
||||
text: 'Spaces',
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Container(
|
||||
// margin: EdgeInsets.zero,
|
||||
// margin: const EdgeInsets.symmetric(
|
||||
// horizontal: 25,
|
||||
// vertical: 5,
|
||||
// ),
|
||||
decoration: const ShapeDecoration(
|
||||
color: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
if (state is CreateRoomState)
|
||||
if (state.roomList.isNotEmpty)
|
||||
Column(
|
||||
children: [
|
||||
ListView.separated(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
separatorBuilder: (context, index) => const Divider(
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
itemCount: state.roomList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Dismissible(
|
||||
key: Key(state.roomList[index]),
|
||||
background: Container(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
alignment: AlignmentDirectional.centerEnd,
|
||||
decoration: ShapeDecoration(
|
||||
color: const Color(0xFFFF0000),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(index == 0 ? 20 : 0),
|
||||
topRight:
|
||||
Radius.circular(index == 0 ? 20 : 0),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: SvgPicture.asset(
|
||||
Assets.assetsDeleteIcon,
|
||||
width: 20,
|
||||
height: 22,
|
||||
),
|
||||
),
|
||||
direction: DismissDirection.endToStart,
|
||||
onDismissed: (direction) {
|
||||
String removedUnit = state.roomList[index];
|
||||
|
||||
BlocProvider.of<CreateUnitBloc>(context)
|
||||
.add(RemoveRoomEvent(roomName: removedUnit));
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('$removedUnit removed')),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
height: 50,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 16, horizontal: 25),
|
||||
child: Text(
|
||||
state.roomList[index],
|
||||
style: const TextStyle(
|
||||
color: Color(0xFF5D5D5D),
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 5),
|
||||
child: Row(
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
if (textEditingController.text.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Please add the room name')),
|
||||
);
|
||||
return;
|
||||
}
|
||||
BlocProvider.of<CreateUnitBloc>(context).add(
|
||||
CreateRoomEvent(
|
||||
roomName: textEditingController.text));
|
||||
textEditingController.clear();
|
||||
},
|
||||
child: const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
BodyMedium(
|
||||
text: 'Add custom Space',
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: TextField(
|
||||
textAlign: TextAlign.end,
|
||||
controller: textEditingController,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Set',
|
||||
hintStyle:
|
||||
context.bodyMedium.copyWith(color: Colors.grey),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,16 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.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/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
|
||||
class JoinHomeView extends StatelessWidget {
|
||||
const JoinHomeView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
TextEditingController textEditingController = TextEditingController();
|
||||
return DefaultScaffold(
|
||||
title: "Join a Home",
|
||||
child: Column(
|
||||
@ -38,16 +41,27 @@ class JoinHomeView extends StatelessWidget {
|
||||
children: [
|
||||
Flexible(
|
||||
child: TextField(
|
||||
controller: textEditingController,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Invitatoin code',
|
||||
hintStyle:
|
||||
context.bodyMedium.copyWith(color: Colors.grey),
|
||||
hintStyle: context.bodyMedium.copyWith(color: Colors.grey),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
onPressed: () async {
|
||||
if (textEditingController.text.isEmpty) {
|
||||
CustomSnackBar.displaySnackBar('Please enter the invitation code');
|
||||
return;
|
||||
}
|
||||
if (await HomeCubit.getInstance().joinAUnit(textEditingController.text)) {
|
||||
CustomSnackBar.displaySnackBar('Done successfully');
|
||||
Navigator.of(context).pop();
|
||||
} else {
|
||||
CustomSnackBar.displaySnackBar('Wrong code!');
|
||||
}
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.arrow_right_alt,
|
||||
),
|
||||
|
||||
@ -0,0 +1,92 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_bloc.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_event.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_state.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
|
||||
class AssignDeviceView extends StatelessWidget {
|
||||
final String unitId;
|
||||
final String roomId;
|
||||
const AssignDeviceView({super.key, required this.unitId, required this.roomId});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => ManageUnitBloc()..add(FetchDevicesByRoomIdEvent(roomId: roomId)),
|
||||
child: BlocConsumer<ManageUnitBloc, ManageUnitState>(
|
||||
listener: (context, state) {},
|
||||
builder: (context, state) {
|
||||
return DefaultScaffold(
|
||||
title: 'Space Setting',
|
||||
child: state is LoadingState
|
||||
? const Center(child: RefreshProgressIndicator())
|
||||
: state is FetchDeviceByRoomIdState
|
||||
? Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
child: GridView.builder(
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10.0,
|
||||
mainAxisSpacing: 10.0,
|
||||
childAspectRatio: 1.0,
|
||||
),
|
||||
itemCount: state.allDevices.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: ShapeDecoration(
|
||||
color: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
state.allDevices[index].icon!,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (state.roomDevicesId[
|
||||
state.allDevices[index].uuid!] ??
|
||||
false == false) {
|
||||
BlocProvider.of<ManageUnitBloc>(context).add(
|
||||
AssignRoomEvent(
|
||||
deviceId:
|
||||
state.allDevices[index].uuid ??
|
||||
'',
|
||||
roomId: roomId));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
state.roomDevicesId[
|
||||
state.allDevices[index].uuid!] ??
|
||||
false
|
||||
? Assets.blueCheckboxIcon
|
||||
: Assets.emptyCheckboxIcon,
|
||||
width: 22,
|
||||
height: 22,
|
||||
))
|
||||
],
|
||||
),
|
||||
Text(state.allDevices[index].name ?? ''),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
)
|
||||
: Container());
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/manage_home/room_screen.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/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/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class HomeSettingsView extends StatelessWidget {
|
||||
@ -38,8 +42,7 @@ class HomeSettingsView extends StatelessWidget {
|
||||
textAlign: TextAlign.end,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Enter Name',
|
||||
hintStyle:
|
||||
context.bodyMedium.copyWith(color: Colors.grey),
|
||||
hintStyle: context.bodyMedium.copyWith(color: Colors.grey),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
),
|
||||
@ -52,16 +55,27 @@ class HomeSettingsView extends StatelessWidget {
|
||||
height: 1,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodyMedium(text: 'Rooms'),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 15,
|
||||
)
|
||||
],
|
||||
Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(CustomPageRoute(
|
||||
builder: (context) => RoomsView(
|
||||
unitId: space?.id ?? '',
|
||||
)));
|
||||
},
|
||||
child: const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodyMedium(text: 'Rooms'),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 15,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
//Divider
|
||||
Container(
|
||||
@ -78,14 +92,39 @@ class HomeSettingsView extends StatelessWidget {
|
||||
textAlign: TextAlign.end,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Set',
|
||||
hintStyle:
|
||||
context.bodyMedium.copyWith(color: Colors.grey),
|
||||
hintStyle: context.bodyMedium.copyWith(color: Colors.grey),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
//Divider
|
||||
Container(
|
||||
margin: const EdgeInsets.only(bottom: 10),
|
||||
height: 1,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
await HomeCubit.getInstance().generateInvitation(space?.id ?? '');
|
||||
},
|
||||
child: const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodyMedium(text: 'Invite a member'),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 15,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -104,14 +143,13 @@ class HomeSettingsView extends StatelessWidget {
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10,
|
||||
),
|
||||
itemCount: 4,
|
||||
itemCount: 2,
|
||||
itemBuilder: (context, index) => Stack(
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
DefaultContainer(
|
||||
margin: const EdgeInsets.only(top: 20),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 15, horizontal: 40),
|
||||
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 40),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
|
||||
137
lib/features/menu/view/widgets/manage_home/room_screen.dart
Normal file
137
lib/features/menu/view/widgets/manage_home/room_screen.dart
Normal file
@ -0,0 +1,137 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_bloc.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_event.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_state.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/manage_home/assign_devices.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class RoomsView extends StatelessWidget {
|
||||
final String unitId;
|
||||
const RoomsView({super.key, required this.unitId});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
TextEditingController textEditingController = TextEditingController();
|
||||
return BlocProvider(
|
||||
create: (context) => ManageUnitBloc()..add(FetchRoomsEvent(unitId: unitId)),
|
||||
child: BlocConsumer<ManageUnitBloc, ManageUnitState>(
|
||||
listener: (context, state) {},
|
||||
builder: (context, state) {
|
||||
return DefaultScaffold(
|
||||
title: 'Space Management',
|
||||
child: state is LoadingState
|
||||
? const Center(child: RefreshProgressIndicator())
|
||||
: Container(
|
||||
margin: const EdgeInsets.only(top: 32),
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
child: Column(
|
||||
children: [
|
||||
if (state is FetchRoomsState)
|
||||
Container(
|
||||
decoration: const ShapeDecoration(
|
||||
color: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
if (state.roomsList.isNotEmpty)
|
||||
ListView.separated(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
separatorBuilder: (context, index) => const Divider(
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
itemCount: state.roomsList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
// BlocProvider.of<ManageUnitBloc>(context).add(
|
||||
// FetchDevicesByRoomIdEvent(roomId: roomId));
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => AssignDeviceView(
|
||||
roomId: state.roomsList[index].id ?? '',
|
||||
unitId: unitId,
|
||||
)),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
height: 50,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 16, horizontal: 25),
|
||||
child: Text(
|
||||
state.roomsList[index].name ?? '',
|
||||
style: const TextStyle(
|
||||
color: Color(0xFF5D5D5D),
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
Container(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 25, vertical: 5),
|
||||
child: Row(
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
if (textEditingController.text.isEmpty) {
|
||||
CustomSnackBar.displaySnackBar(
|
||||
'Please add the room name');
|
||||
return;
|
||||
}
|
||||
BlocProvider.of<ManageUnitBloc>(context).add(
|
||||
AddNewRoom(
|
||||
roomName: textEditingController.text,
|
||||
unitId: unitId));
|
||||
textEditingController.clear();
|
||||
},
|
||||
child: const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
BodyMedium(
|
||||
text: 'Add Space',
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: TextField(
|
||||
textAlign: TextAlign.end,
|
||||
controller: textEditingController,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Set',
|
||||
hintStyle:
|
||||
context.bodyMedium.copyWith(color: Colors.grey),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user