mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2026-03-11 05:31:44 +00:00
Compare commits
12 Commits
feat/updat
...
SP-1397-FE
| Author | SHA1 | Date | |
|---|---|---|---|
| f2412aa867 | |||
| e4768c95aa | |||
| f25b4dbf6d | |||
| 9eff9ab371 | |||
| a2e68d6194 | |||
| 94c94b170f | |||
| 253cf15559 | |||
| 443eea9421 | |||
| 87a2c08f64 | |||
| dd66e7c747 | |||
| 7af61d2f65 | |||
| f37eacb0ee |
2
.env.dev
2
.env.dev
@ -1,3 +1,5 @@
|
|||||||
ENV_NAME=development
|
ENV_NAME=development
|
||||||
BASE_URL=https://syncrow-dev.azurewebsites.net
|
BASE_URL=https://syncrow-dev.azurewebsites.net
|
||||||
PROJECT_ID=0e62577c-06fa-41b9-8a92-99a21fbaf51c
|
PROJECT_ID=0e62577c-06fa-41b9-8a92-99a21fbaf51c
|
||||||
|
CLIENT_ID=c024573d191a327ce74db7d4502fdc29
|
||||||
|
CLIENT_SECRET=fec6ccbc33664f94a3b84a45c7cceef3f3ebd1613ef4307db8946ede530cd1ed
|
||||||
@ -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_dotenv/flutter_dotenv.dart';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:syncrow_app/features/auth/model/login_with_email_model.dart';
|
import 'package:syncrow_app/features/auth/model/login_with_email_model.dart';
|
||||||
import 'package:syncrow_app/features/auth/model/signup_model.dart';
|
import 'package:syncrow_app/features/auth/model/signup_model.dart';
|
||||||
@ -217,9 +218,22 @@ class AuthCubit extends Cubit<AuthState> {
|
|||||||
signUp() async {
|
signUp() async {
|
||||||
emit(AuthLoginLoading());
|
emit(AuthLoginLoading());
|
||||||
final response;
|
final response;
|
||||||
|
|
||||||
|
final clientId = dotenv.env['CLIENT_ID'] ?? '';
|
||||||
|
final clientSecret = dotenv.env['CLIENT_SECRET'] ?? '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<String> userFullName = fullName.split(' ');
|
List<String> userFullName = fullName.split(' ');
|
||||||
|
|
||||||
|
final clientToken = await AuthenticationAPI.fetchClientToken(
|
||||||
|
clientId: clientId,
|
||||||
|
clientSecret: clientSecret,
|
||||||
|
);
|
||||||
|
|
||||||
|
final accessToken = clientToken['accessToken'];
|
||||||
|
|
||||||
response = await AuthenticationAPI.signUp(
|
response = await AuthenticationAPI.signUp(
|
||||||
|
accessToken: accessToken,
|
||||||
model: SignUpModel(
|
model: SignUpModel(
|
||||||
hasAcceptedAppAgreement: true,
|
hasAcceptedAppAgreement: true,
|
||||||
email: email.toLowerCase(),
|
email: email.toLowerCase(),
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart';
|
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_event.dart';
|
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_event.dart';
|
||||||
@ -7,19 +5,31 @@ import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart
|
|||||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart';
|
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart';
|
||||||
|
|
||||||
class TabBarBloc extends Bloc<TabBarEvent, TabBarState> {
|
class TabBarBloc extends Bloc<TabBarEvent, TabBarState> {
|
||||||
final DeviceManagerBloc deviceManagerBloc;
|
TabBarBloc(this.deviceManagerBloc) : super(const TabBarInitialState()) {
|
||||||
TabBarBloc(this.deviceManagerBloc) : super(const Initial()) {
|
on<TabBarTabChangedEvent>(_onTabBarTabChangedEvent);
|
||||||
on<TabChanged>(_handleTabChanged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<void> _handleTabChanged(
|
final DeviceManagerBloc deviceManagerBloc;
|
||||||
TabChanged event, Emitter<TabBarState> emit) {
|
|
||||||
|
void _onTabBarTabChangedEvent(
|
||||||
|
TabBarTabChangedEvent event,
|
||||||
|
Emitter<TabBarState> emit,
|
||||||
|
) {
|
||||||
|
_getDevices(event);
|
||||||
|
|
||||||
|
emit(
|
||||||
|
TabBarTabSelectedState(
|
||||||
|
roomId: event.roomId,
|
||||||
|
selectedTabIndex: event.selectedIndex,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _getDevices(TabBarTabChangedEvent event) {
|
||||||
if (event.roomId == "-1") {
|
if (event.roomId == "-1") {
|
||||||
deviceManagerBloc.add(FetchAllDevices());
|
deviceManagerBloc.add(FetchAllDevices());
|
||||||
} else {
|
} else {
|
||||||
deviceManagerBloc.add(FetchDevicesByRoomId(event.roomId,event.unit));
|
deviceManagerBloc.add(FetchDevicesByRoomId(event.roomId, event.unit));
|
||||||
}
|
}
|
||||||
emit(TabSelected(
|
|
||||||
roomId: event.roomId, selectedTabIndex: event.selectedIndex));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,10 +4,14 @@ abstract class TabBarEvent {
|
|||||||
const TabBarEvent();
|
const TabBarEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
class TabChanged extends TabBarEvent {
|
class TabBarTabChangedEvent extends TabBarEvent {
|
||||||
|
const TabBarTabChangedEvent({
|
||||||
|
required this.selectedIndex,
|
||||||
|
required this.roomId,
|
||||||
|
required this.unit,
|
||||||
|
});
|
||||||
|
|
||||||
final int selectedIndex;
|
final int selectedIndex;
|
||||||
final String roomId;
|
final String roomId;
|
||||||
final SpaceModel unit;
|
final SpaceModel unit;
|
||||||
const TabChanged(
|
|
||||||
{required this.selectedIndex, required this.roomId, required this.unit});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,12 +2,16 @@ abstract class TabBarState {
|
|||||||
const TabBarState();
|
const TabBarState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class Initial extends TabBarState {
|
class TabBarInitialState extends TabBarState {
|
||||||
const Initial();
|
const TabBarInitialState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class TabSelected extends TabBarState {
|
class TabBarTabSelectedState extends TabBarState {
|
||||||
|
const TabBarTabSelectedState({
|
||||||
|
required this.roomId,
|
||||||
|
required this.selectedTabIndex,
|
||||||
|
});
|
||||||
|
|
||||||
final int selectedTabIndex;
|
final int selectedTabIndex;
|
||||||
final String roomId;
|
final String roomId;
|
||||||
const TabSelected({required this.roomId, required this.selectedTabIndex});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,82 +20,69 @@ class SceneRoomsTabBarDevicesView extends StatefulWidget {
|
|||||||
_SceneRoomsTabBarDevicesViewState();
|
_SceneRoomsTabBarDevicesViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SceneRoomsTabBarDevicesViewState
|
class _SceneRoomsTabBarDevicesViewState extends State<SceneRoomsTabBarDevicesView>
|
||||||
extends State<SceneRoomsTabBarDevicesView>
|
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
late final TabController _tabController;
|
late final TabController _tabController;
|
||||||
List<SubSpaceModel>? rooms = [];
|
|
||||||
late final SpaceModel selectedSpace;
|
late final SpaceModel selectedSpace;
|
||||||
|
var rooms = <SubSpaceModel>[];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
selectedSpace = HomeCubit.getInstance().selectedSpace!;
|
||||||
selectedSpace = HomeCubit.getInstance().selectedSpace!;
|
|
||||||
|
|
||||||
rooms = List.from(selectedSpace.subspaces ?? []);
|
rooms = List.from(selectedSpace.subspaces);
|
||||||
|
final defaultSubSpaceModel = SubSpaceModel(
|
||||||
|
name: 'All Devices',
|
||||||
|
devices: context.read<DevicesCubit>().allDevices,
|
||||||
|
id: '-1',
|
||||||
|
);
|
||||||
|
|
||||||
if (rooms != null && rooms!.isNotEmpty) {
|
if (rooms.isNotEmpty) {
|
||||||
if (rooms![0].id != '-1') {
|
final isFirstRoomIdValid = rooms[0].id != '-1';
|
||||||
rooms?.insert(
|
if (isFirstRoomIdValid) {
|
||||||
0,
|
rooms.insert(0, defaultSubSpaceModel);
|
||||||
SubSpaceModel(
|
|
||||||
name: 'All Devices',
|
|
||||||
devices: context.read<DevicesCubit>().allDevices,
|
|
||||||
id: '-1',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rooms = [
|
|
||||||
SubSpaceModel(
|
|
||||||
name: 'All Devices',
|
|
||||||
devices: context.read<DevicesCubit>().allDevices,
|
|
||||||
id: '-1',
|
|
||||||
)
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
_tabController = TabController(length: rooms!.length, vsync: this);
|
rooms = [defaultSubSpaceModel];
|
||||||
_tabController.addListener(_handleTabSwitched);
|
|
||||||
setState(() {});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _handleTabSwitched() {
|
|
||||||
if (_tabController.indexIsChanging) {
|
|
||||||
final value = _tabController.index;
|
|
||||||
|
|
||||||
/// select tab
|
|
||||||
context.read<TabBarBloc>().add(TabChanged(
|
|
||||||
selectedIndex: value,
|
|
||||||
roomId: rooms?[value].id ?? '',
|
|
||||||
unit: selectedSpace));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_tabController = TabController(length: rooms.length, vsync: this);
|
||||||
|
_tabController.addListener(_handleTabSwitched);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
_tabController.dispose();
|
|
||||||
_tabController.removeListener(() {});
|
_tabController.removeListener(() {});
|
||||||
|
_tabController.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleTabSwitched() {
|
||||||
|
if (_tabController.indexIsChanging) {
|
||||||
|
final index = _tabController.index;
|
||||||
|
|
||||||
|
context.read<TabBarBloc>().add(
|
||||||
|
TabBarTabChangedEvent(
|
||||||
|
selectedIndex: index,
|
||||||
|
roomId: rooms[index].id ?? '',
|
||||||
|
unit: selectedSpace,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DefaultScaffold(
|
return DefaultScaffold(
|
||||||
title: StringsManager.createScene,
|
padding: EdgeInsetsDirectional.zero,
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () {
|
onPressed: () => navigateToRoute(context, Routes.sceneTasksRoute),
|
||||||
navigateToRoute(context, Routes.sceneTasksRoute);
|
icon: const Icon(Icons.arrow_back_ios),
|
||||||
},
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.arrow_back_ios,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
title: StringsManager.createScene,
|
||||||
child: SceneDevicesBody(tabController: _tabController, rooms: rooms),
|
child: SceneDevicesBody(tabController: _tabController, rooms: rooms),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
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/flutter_svg.dart';
|
|
||||||
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart';
|
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_state.dart';
|
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_state.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
|
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
|
||||||
@ -8,60 +7,44 @@ import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart'
|
|||||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart';
|
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart';
|
||||||
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
||||||
import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
|
import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
|
||||||
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
import 'package:syncrow_app/features/scene/widgets/scene_devices/scene_devices_body_tab_bar.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
import 'package:syncrow_app/features/scene/widgets/scene_devices/scene_devices_list.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
import 'package:syncrow_app/features/shared_widgets/app_loading_indicator.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
|
||||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
|
||||||
import 'package:syncrow_app/utils/context_extension.dart';
|
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
|
||||||
|
|
||||||
class SceneDevicesBody extends StatelessWidget {
|
class SceneDevicesBody extends StatelessWidget {
|
||||||
const SceneDevicesBody({
|
const SceneDevicesBody({
|
||||||
super.key,
|
required this.tabController,
|
||||||
required TabController tabController,
|
|
||||||
required this.rooms,
|
required this.rooms,
|
||||||
}) : _tabController = tabController;
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
final TabController _tabController;
|
final TabController tabController;
|
||||||
final List<SubSpaceModel>? rooms;
|
final List<SubSpaceModel> rooms;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isAutomationDeviceStatus =
|
|
||||||
((ModalRoute.of(context)?.settings.arguments as SceneSettingsRouteArguments?)?.sceneType ==
|
|
||||||
CreateSceneEnum.deviceStatusChanges.name);
|
|
||||||
return BlocBuilder<TabBarBloc, TabBarState>(
|
return BlocBuilder<TabBarBloc, TabBarState>(
|
||||||
builder: (context, tabState) {
|
builder: (context, state) {
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
TabBar(
|
SceneDevicesBodyTabBar(
|
||||||
controller: _tabController,
|
tabController: tabController,
|
||||||
dividerColor: Colors.transparent,
|
rooms: rooms,
|
||||||
indicatorColor: Colors.transparent,
|
selectedRoomId: state is TabBarTabSelectedState ? state.roomId : '-1',
|
||||||
tabs: [
|
|
||||||
...rooms!.map((e) => Tab(
|
|
||||||
child: BodyLarge(
|
|
||||||
text: e.name ?? '',
|
|
||||||
textAlign: TextAlign.start,
|
|
||||||
style: context.bodyLarge.copyWith(
|
|
||||||
color: (tabState is TabSelected) && tabState.roomId == e.id
|
|
||||||
? ColorsManager.textPrimaryColor
|
|
||||||
: ColorsManager.textPrimaryColor.withOpacity(0.2),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
isScrollable: true,
|
|
||||||
tabAlignment: TabAlignment.start,
|
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TabBarView(
|
child: TabBarView(
|
||||||
controller: _tabController,
|
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
children:
|
controller: tabController,
|
||||||
rooms!.map((e) => _buildRoomTab(e, context, isAutomationDeviceStatus)).toList(),
|
children: rooms
|
||||||
|
.map(
|
||||||
|
(room) => _buildRoomTab(
|
||||||
|
room,
|
||||||
|
_isAutomationDeviceStatus(context),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -70,52 +53,46 @@ class SceneDevicesBody extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildRoomTab(SubSpaceModel room, BuildContext context, bool isAutomationDeviceStatus) {
|
bool _isAutomationDeviceStatus(BuildContext context) {
|
||||||
|
final routeArguments =
|
||||||
|
ModalRoute.of(context)?.settings.arguments as SceneSettingsRouteArguments?;
|
||||||
|
final deviceStatusChangesScene = CreateSceneEnum.deviceStatusChanges.name;
|
||||||
|
final sceneType = routeArguments?.sceneType;
|
||||||
|
|
||||||
|
return sceneType == deviceStatusChangesScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildRoomTab(
|
||||||
|
SubSpaceModel room,
|
||||||
|
bool isAutomationDeviceStatus,
|
||||||
|
) {
|
||||||
return BlocBuilder<DeviceManagerBloc, DeviceManagerState>(
|
return BlocBuilder<DeviceManagerBloc, DeviceManagerState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state.loading && state.devices == null) {
|
final isLoading = state.loading && state.devices == null;
|
||||||
return const Center(child: CircularProgressIndicator());
|
final hasData =
|
||||||
} else if (state.devices != null && state.devices!.isNotEmpty) {
|
state.devices != null && (state.devices?.isNotEmpty ?? false);
|
||||||
return ListView.builder(
|
final hasError = state.error != null;
|
||||||
itemCount: state.devices!.length,
|
|
||||||
itemBuilder: (context, index) {
|
final widgets = <bool, Widget>{
|
||||||
final device = state.devices![index];
|
isLoading: const AppLoadingIndicator(),
|
||||||
return DefaultContainer(
|
hasError: Center(child: Text('${state.error}')),
|
||||||
child: SceneListTile(
|
hasData: SceneDevicesList(
|
||||||
minLeadingWidth: 40,
|
devices: state.devices ?? [],
|
||||||
leadingWidget: SvgPicture.asset(device.icon ?? ''),
|
isAutomationDeviceStatus: isAutomationDeviceStatus,
|
||||||
titleWidget: BodyMedium(
|
),
|
||||||
text: device.name ?? '',
|
};
|
||||||
style: context.titleSmall.copyWith(
|
|
||||||
color: ColorsManager.secondaryTextColor,
|
final invalidWidgetEntry = MapEntry(
|
||||||
fontWeight: FontWeight.w400,
|
true,
|
||||||
fontSize: 20,
|
Center(child: Text('This subspace has no devices')),
|
||||||
),
|
);
|
||||||
),
|
|
||||||
trailingWidget: const Icon(
|
final validWidgetEntry = widgets.entries.firstWhere(
|
||||||
Icons.arrow_forward_ios_rounded,
|
(entry) => entry.key == true,
|
||||||
color: ColorsManager.greyColor,
|
orElse: () => invalidWidgetEntry,
|
||||||
size: 16,
|
);
|
||||||
),
|
|
||||||
onPressed: () {
|
return validWidgetEntry.value;
|
||||||
Navigator.pushNamed(
|
|
||||||
context,
|
|
||||||
Routes.deviceFunctionsRoute,
|
|
||||||
arguments: {
|
|
||||||
"device": device,
|
|
||||||
"isAutomationDeviceStatus": isAutomationDeviceStatus
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else if (state.error != null) {
|
|
||||||
return const Center(child: Text('Something went wrong'));
|
|
||||||
} else {
|
|
||||||
return const SizedBox();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,46 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
|
||||||
|
class SceneDevicesBodyTabBar extends StatelessWidget {
|
||||||
|
const SceneDevicesBodyTabBar({
|
||||||
|
required this.tabController,
|
||||||
|
required this.rooms,
|
||||||
|
required this.selectedRoomId,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String selectedRoomId;
|
||||||
|
|
||||||
|
final TabController tabController;
|
||||||
|
final List<SubSpaceModel> rooms;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return TabBar(
|
||||||
|
controller: tabController,
|
||||||
|
dividerColor: Colors.transparent,
|
||||||
|
indicatorColor: Colors.transparent,
|
||||||
|
isScrollable: true,
|
||||||
|
tabAlignment: TabAlignment.start,
|
||||||
|
tabs: rooms.map((e) {
|
||||||
|
final isSelected = selectedRoomId == e.id;
|
||||||
|
return Tab(
|
||||||
|
child: BodyLarge(
|
||||||
|
text: e.name ?? '',
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
style: context.bodyLarge.copyWith(
|
||||||
|
color: isSelected
|
||||||
|
? ColorsManager.textPrimaryColor
|
||||||
|
: ColorsManager.textPrimaryColor.withValues(
|
||||||
|
alpha: 0.2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||||
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
|
||||||
|
class SceneDevicesList extends StatelessWidget {
|
||||||
|
const SceneDevicesList({
|
||||||
|
required this.isAutomationDeviceStatus,
|
||||||
|
required this.devices,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
final List<DeviceModel> devices;
|
||||||
|
final bool isAutomationDeviceStatus;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: devices.length,
|
||||||
|
itemBuilder: (context, index) => _buildDeviceTile(context, devices[index]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildDeviceTile(
|
||||||
|
BuildContext context,
|
||||||
|
DeviceModel device,
|
||||||
|
) {
|
||||||
|
return DefaultContainer(
|
||||||
|
child: SceneListTile(
|
||||||
|
minLeadingWidth: 40,
|
||||||
|
leadingWidget: SvgPicture.asset(device.icon ?? ''),
|
||||||
|
titleWidget: BodyMedium(
|
||||||
|
text: device.name ?? '',
|
||||||
|
style: context.titleSmall.copyWith(
|
||||||
|
color: ColorsManager.secondaryTextColor,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailingWidget: const Icon(
|
||||||
|
Icons.arrow_forward_ios_rounded,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
size: 16,
|
||||||
|
),
|
||||||
|
onPressed: () => _navigateToDeviceFunctions(context, device),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _navigateToDeviceFunctions(
|
||||||
|
BuildContext context,
|
||||||
|
DeviceModel device,
|
||||||
|
) {
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
Routes.deviceFunctionsRoute,
|
||||||
|
arguments: {
|
||||||
|
"device": device,
|
||||||
|
"isAutomationDeviceStatus": isAutomationDeviceStatus,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,8 +3,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:syncrow_app/features/app_layout/model/community_model.dart';
|
import 'package:syncrow_app/features/app_layout/model/community_model.dart';
|
||||||
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
|
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
|
||||||
import 'package:syncrow_app/features/app_layout/view/app_layout.dart';
|
import 'package:syncrow_app/features/app_layout/view/app_layout.dart';
|
||||||
import 'package:syncrow_app/features/auth/view/otp_view.dart';
|
|
||||||
import 'package:syncrow_app/features/auth/view/login_view.dart';
|
import 'package:syncrow_app/features/auth/view/login_view.dart';
|
||||||
|
import 'package:syncrow_app/features/auth/view/otp_view.dart';
|
||||||
import 'package:syncrow_app/features/auth/view/sign_up_view.dart';
|
import 'package:syncrow_app/features/auth/view/sign_up_view.dart';
|
||||||
import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart';
|
import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart';
|
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart';
|
||||||
@ -17,11 +17,12 @@ import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart'
|
|||||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart';
|
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart';
|
||||||
import 'package:syncrow_app/features/scene/view/device_functions_view.dart';
|
import 'package:syncrow_app/features/scene/view/device_functions_view.dart';
|
||||||
import 'package:syncrow_app/features/scene/view/scene_auto_settings.dart';
|
import 'package:syncrow_app/features/scene/view/scene_auto_settings.dart';
|
||||||
import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
|
|
||||||
import 'package:syncrow_app/features/scene/view/scene_rooms_tabbar.dart';
|
import 'package:syncrow_app/features/scene/view/scene_rooms_tabbar.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
|
||||||
import 'package:syncrow_app/features/scene/view/scene_view.dart';
|
import 'package:syncrow_app/features/scene/view/scene_view.dart';
|
||||||
import 'package:syncrow_app/features/scene/view/smart_automation_select_route.dart';
|
import 'package:syncrow_app/features/scene/view/smart_automation_select_route.dart';
|
||||||
import 'package:syncrow_app/features/splash/view/splash_view.dart';
|
import 'package:syncrow_app/features/splash/view/splash_view.dart';
|
||||||
|
|
||||||
import 'routing_constants.dart';
|
import 'routing_constants.dart';
|
||||||
|
|
||||||
class Router {
|
class Router {
|
||||||
@ -88,7 +89,7 @@ class Router {
|
|||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (BuildContext context) =>
|
create: (BuildContext context) =>
|
||||||
TabBarBloc(context.read<DeviceManagerBloc>())
|
TabBarBloc(context.read<DeviceManagerBloc>())
|
||||||
..add(TabChanged(
|
..add(TabBarTabChangedEvent(
|
||||||
selectedIndex: 0,
|
selectedIndex: 0,
|
||||||
roomId: '-1',
|
roomId: '-1',
|
||||||
unit: SpaceModel(
|
unit: SpaceModel(
|
||||||
|
|||||||
@ -11,7 +11,7 @@ abstract class ApiEndpoints {
|
|||||||
static const String sendOtp = '/authentication/user/send-otp';
|
static const String sendOtp = '/authentication/user/send-otp';
|
||||||
static const String verifyOtp = '/authentication/user/verify-otp';
|
static const String verifyOtp = '/authentication/user/verify-otp';
|
||||||
static const String forgetPassword = '/authentication/user/forget-password';
|
static const String forgetPassword = '/authentication/user/forget-password';
|
||||||
|
static const String clientLogin = 'client/token';
|
||||||
////////////////////////////////////// Spaces ///////////////////////////////////////
|
////////////////////////////////////// Spaces ///////////////////////////////////////
|
||||||
|
|
||||||
///Community Module
|
///Community Module
|
||||||
|
|||||||
@ -25,11 +25,15 @@ class AuthenticationAPI {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool> signUp({required SignUpModel model}) async {
|
static Future<bool> signUp({
|
||||||
|
required SignUpModel model,
|
||||||
|
required String accessToken,
|
||||||
|
}) async {
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.signUp,
|
path: ApiEndpoints.signUp,
|
||||||
body: model.toJson(),
|
body: model.toJson(),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
|
accessToken: accessToken,
|
||||||
expectedResponseModel: (json) => json['statusCode'] == 201);
|
expectedResponseModel: (json) => json['statusCode'] == 201);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@ -63,4 +67,20 @@ class AuthenticationAPI {
|
|||||||
expectedResponseModel: (json) => json['data']);
|
expectedResponseModel: (json) => json['data']);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<Map<String, dynamic>> fetchClientToken({
|
||||||
|
required String clientId,
|
||||||
|
required String clientSecret,
|
||||||
|
}) async {
|
||||||
|
final response = await HTTPService().post(
|
||||||
|
path: ApiEndpoints.clientLogin,
|
||||||
|
body: {
|
||||||
|
'clientId': clientId,
|
||||||
|
'clientSecret': clientSecret,
|
||||||
|
},
|
||||||
|
showServerMessage: false,
|
||||||
|
expectedResponseModel: (json) => json['data'],
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,13 +48,26 @@ class HTTPService {
|
|||||||
Options? options,
|
Options? options,
|
||||||
dynamic body,
|
dynamic body,
|
||||||
bool showServerMessage = true,
|
bool showServerMessage = true,
|
||||||
|
String? accessToken,
|
||||||
required T Function(dynamic) expectedResponseModel}) async {
|
required T Function(dynamic) expectedResponseModel}) async {
|
||||||
try {
|
try {
|
||||||
|
final authOptions = options ??
|
||||||
|
Options(
|
||||||
|
headers: accessToken != null
|
||||||
|
? {
|
||||||
|
'Authorization': 'Bearer $accessToken',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
final response = await client.post(
|
final response = await client.post(
|
||||||
path,
|
path,
|
||||||
data: body,
|
data: body,
|
||||||
queryParameters: queryParameters,
|
queryParameters: queryParameters,
|
||||||
options: options,
|
options: authOptions,
|
||||||
);
|
);
|
||||||
return expectedResponseModel(response.data);
|
return expectedResponseModel(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user