Implemented home management and user invitation flows

This commit is contained in:
Abdullah Alassaf
2024-06-05 03:42:00 +03:00
parent 6a9c2967d2
commit 631ba53d7a
29 changed files with 968 additions and 288 deletions

View File

@ -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'));

View 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;
}
}
}

View File

@ -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];
}

View File

@ -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];
}

View File

@ -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,
),
),
),
],
),
),
],
),
),
],
),
),
),
],
),
),
),
);
}),
);
},
),
);
}
}

View File

@ -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,
),

View File

@ -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());
}));
}
}

View File

@ -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: [

View 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,
),
),
),
],
),
),
],
),
)
],
),
),
);
}));
}
}