mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-11 15:47:44 +00:00
Compare commits
5 Commits
bugfix/fix
...
SP-1493-FE
Author | SHA1 | Date | |
---|---|---|---|
d8f40badc0 | |||
fdd5d0feed | |||
fb1f79c7bb | |||
1923ac7014 | |||
c114161357 |
3
assets/icons/blank_calendar.svg
Normal file
3
assets/icons/blank_calendar.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M16.25 2.1875H14.6875V1.875C14.6875 1.62636 14.5887 1.3879 14.4129 1.21209C14.2371 1.03627 13.9986 0.9375 13.75 0.9375C13.5014 0.9375 13.2629 1.03627 13.0871 1.21209C12.9113 1.3879 12.8125 1.62636 12.8125 1.875V2.1875H7.1875V1.875C7.1875 1.62636 7.08873 1.3879 6.91291 1.21209C6.7371 1.03627 6.49864 0.9375 6.25 0.9375C6.00136 0.9375 5.7629 1.03627 5.58709 1.21209C5.41127 1.3879 5.3125 1.62636 5.3125 1.875V2.1875H3.75C3.3356 2.1875 2.93817 2.35212 2.64515 2.64515C2.35212 2.93817 2.1875 3.3356 2.1875 3.75V16.25C2.1875 16.6644 2.35212 17.0618 2.64515 17.3549C2.93817 17.6479 3.3356 17.8125 3.75 17.8125H16.25C16.6644 17.8125 17.0618 17.6479 17.3549 17.3549C17.6479 17.0618 17.8125 16.6644 17.8125 16.25V3.75C17.8125 3.3356 17.6479 2.93817 17.3549 2.64515C17.0618 2.35212 16.6644 2.1875 16.25 2.1875ZM5.3125 4.0625C5.3125 4.31114 5.41127 4.5496 5.58709 4.72541C5.7629 4.90123 6.00136 5 6.25 5C6.49864 5 6.7371 4.90123 6.91291 4.72541C7.08873 4.5496 7.1875 4.31114 7.1875 4.0625H12.8125C12.8125 4.31114 12.9113 4.5496 13.0871 4.72541C13.2629 4.90123 13.5014 5 13.75 5C13.9986 5 14.2371 4.90123 14.4129 4.72541C14.5887 4.5496 14.6875 4.31114 14.6875 4.0625H15.9375V5.9375H4.0625V4.0625H5.3125ZM4.0625 15.9375V7.8125H15.9375V15.9375H4.0625Z" fill="#475569"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1,18 @@
|
|||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/analytics/enums/analytics_page_tab.dart';
|
||||||
|
|
||||||
|
part 'analytics_tab_event.dart';
|
||||||
|
|
||||||
|
class AnalyticsTabBloc extends Bloc<AnalyticsTabEvent, AnalyticsPageTab> {
|
||||||
|
AnalyticsTabBloc() : super(AnalyticsPageTab.energyManagement) {
|
||||||
|
on<UpdateAnalyticsTabEvent>(_onUpdateAnalyticsTabEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onUpdateAnalyticsTabEvent(
|
||||||
|
UpdateAnalyticsTabEvent event,
|
||||||
|
Emitter<AnalyticsPageTab> emit,
|
||||||
|
) {
|
||||||
|
emit(event.analyticsTab);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
part of 'analytics_tab_bloc.dart';
|
||||||
|
|
||||||
|
sealed class AnalyticsTabEvent extends Equatable {
|
||||||
|
const AnalyticsTabEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateAnalyticsTabEvent extends AnalyticsTabEvent {
|
||||||
|
const UpdateAnalyticsTabEvent(this.analyticsTab);
|
||||||
|
|
||||||
|
final AnalyticsPageTab analyticsTab;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [analyticsTab];
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/energy_management/views/analytics_energy_management_view.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/occupancy/views/analytics_occupancy_view.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/overview/views/analytics_overview_view.dart';
|
||||||
|
|
||||||
|
enum AnalyticsPageTab {
|
||||||
|
overview(
|
||||||
|
title: 'Overview',
|
||||||
|
child: AnalyticsOverviewView(),
|
||||||
|
),
|
||||||
|
energyManagement(
|
||||||
|
title: 'Energy Management',
|
||||||
|
child: AnalyticsEnergyManagementView(),
|
||||||
|
),
|
||||||
|
occupancy(
|
||||||
|
title: 'Occupancy',
|
||||||
|
child: AnalyticsOccupancyView(),
|
||||||
|
);
|
||||||
|
|
||||||
|
const AnalyticsPageTab({
|
||||||
|
required this.title,
|
||||||
|
required this.child,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Widget child;
|
||||||
|
final String title;
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/analytics/blocs/bloc/analytics_tab_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/analytics/widgets/analytics_communities_sidebar.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/analytics/widgets/analytics_page_tabs_and_children.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
||||||
|
import 'package:syncrow_web/utils/theme/responsive_text_theme.dart';
|
||||||
|
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
||||||
|
|
||||||
|
class AnalyticsPage extends StatelessWidget {
|
||||||
|
const AnalyticsPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider<AnalyticsTabBloc>(
|
||||||
|
create: (context) => AnalyticsTabBloc(),
|
||||||
|
child: const AnalyticsPageForm(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnalyticsPageForm extends StatelessWidget {
|
||||||
|
const AnalyticsPageForm({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return WebScaffold(
|
||||||
|
rightBody: const NavigateHomeGridView(),
|
||||||
|
appBarTitle: Text(
|
||||||
|
'Syncrow Analytics',
|
||||||
|
style: ResponsiveTextTheme.of(context).deviceManagementTitle,
|
||||||
|
),
|
||||||
|
enableMenuSidebar: false,
|
||||||
|
scaffoldBody: const Row(
|
||||||
|
children: [
|
||||||
|
AnalyticsCommunitiesSidebar(),
|
||||||
|
Expanded(flex: 5, child: AnalyticsPageTabsAndChildren()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_tree/view/space_tree_view.dart';
|
||||||
|
|
||||||
|
class AnalyticsCommunitiesSidebar extends StatelessWidget {
|
||||||
|
const AnalyticsCommunitiesSidebar({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Expanded(
|
||||||
|
child: SpaceTreeView(
|
||||||
|
title: const Text('Communities'),
|
||||||
|
shouldDisableDeselectingChildrenOfSelectedParent: true,
|
||||||
|
onSelect: () {},
|
||||||
|
isSide: false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
|
class AnalyticsDateFilterButton extends StatelessWidget {
|
||||||
|
const AnalyticsDateFilterButton({super.key});
|
||||||
|
|
||||||
|
static final _color = ColorsManager.blackColor.withValues(alpha: 0.8);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return TextButton.icon(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
foregroundColor: _color,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
side: const BorderSide(
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
backgroundColor: ColorsManager.transparentColor,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 32,
|
||||||
|
vertical: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
icon: SvgPicture.asset(
|
||||||
|
Assets.blankCalendar,
|
||||||
|
height: 20,
|
||||||
|
width: 20,
|
||||||
|
colorFilter: ColorFilter.mode(_color, BlendMode.srcIn),
|
||||||
|
),
|
||||||
|
label: Text(
|
||||||
|
_concatenateDate(DateTime(2024, 1), DateTime(2024, 12)),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _formatDate(DateTime date) {
|
||||||
|
final formatter = DateFormat('MMM yyyy');
|
||||||
|
final formattedDate = formatter.format(date);
|
||||||
|
return formattedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
String _concatenateDate(DateTime startDate, DateTime endDate) {
|
||||||
|
final formattedStartDate = _formatDate(startDate);
|
||||||
|
final formattedEndDate = _formatDate(endDate);
|
||||||
|
return '$formattedStartDate - $formattedEndDate';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/analytics/blocs/bloc/analytics_tab_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/analytics/enums/analytics_page_tab.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
|
class AnalyticsPageTabButton extends StatelessWidget {
|
||||||
|
const AnalyticsPageTabButton({
|
||||||
|
super.key,
|
||||||
|
required this.tab,
|
||||||
|
required this.isSelected,
|
||||||
|
});
|
||||||
|
|
||||||
|
final AnalyticsPageTab tab;
|
||||||
|
final bool isSelected;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return TextButton(
|
||||||
|
onPressed: () => context.read<AnalyticsTabBloc>().add(
|
||||||
|
UpdateAnalyticsTabEvent(tab),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
tab.title,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
maxLines: 1,
|
||||||
|
softWrap: false,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: isSelected ? FontWeight.w700 : FontWeight.w400,
|
||||||
|
fontSize: 16,
|
||||||
|
color:
|
||||||
|
isSelected ? ColorsManager.slidingBlueColor : ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/analytics/blocs/bloc/analytics_tab_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/analytics/enums/analytics_page_tab.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/analytics/widgets/analytics_date_filter_button.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/analytics/widgets/analytics_page_tab_button.dart';
|
||||||
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
|
class AnalyticsPageTabsAndChildren extends StatelessWidget {
|
||||||
|
const AnalyticsPageTabsAndChildren({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocBuilder<AnalyticsTabBloc, AnalyticsPageTab>(
|
||||||
|
buildWhen: (previous, current) => previous != current,
|
||||||
|
builder: (context, selectedTab) => Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
width: MediaQuery.sizeOf(context).width * 1,
|
||||||
|
decoration: subSectionContainerDecoration,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 4,
|
||||||
|
child: FittedBox(
|
||||||
|
alignment: AlignmentDirectional.centerStart,
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
child: Row(
|
||||||
|
spacing: 32,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
...AnalyticsPageTab.values.map(
|
||||||
|
(tab) => AnimatedSwitcher(
|
||||||
|
switchInCurve: Curves.easeIn,
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: AnalyticsPageTabButton(
|
||||||
|
key: ValueKey(selectedTab),
|
||||||
|
tab: tab,
|
||||||
|
isSelected: tab == selectedTab,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
const Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: FittedBox(
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
alignment: AlignmentDirectional.centerEnd,
|
||||||
|
child: AnalyticsDateFilterButton(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 8,
|
||||||
|
child: SizedBox(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
child: AnimatedSwitcher(
|
||||||
|
switchInCurve: Curves.easeIn,
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: selectedTab.child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AnalyticsEnergyManagementView extends StatelessWidget {
|
||||||
|
const AnalyticsEnergyManagementView({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const Center(
|
||||||
|
child: Text('EnergyManagementView is Working!'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AnalyticsOccupancyView extends StatelessWidget {
|
||||||
|
const AnalyticsOccupancyView({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const Center(
|
||||||
|
child: Text('AnalyticsOccupancyView is Working!'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AnalyticsOverviewView extends StatelessWidget {
|
||||||
|
const AnalyticsOverviewView({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const Center(
|
||||||
|
child: Text('Coming Soon!'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -143,6 +143,19 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
|||||||
color: ColorsManager.primaryColor,
|
color: ColorsManager.primaryColor,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
HomeItemModel(
|
||||||
|
title: 'Syncrow Analytics',
|
||||||
|
icon: Assets.devicesIcon,
|
||||||
|
active: true,
|
||||||
|
onPress: (context) {
|
||||||
|
context.read<SpaceTreeBloc>().add(ClearCachedData());
|
||||||
|
BlocProvider.of<RoutineBloc>(context)
|
||||||
|
.add(const TriggerSwitchTabsEvent(isRoutineTab: false));
|
||||||
|
context.go(RoutesConst.analytics);
|
||||||
|
},
|
||||||
|
color: ColorsManager.primaryColor,
|
||||||
|
),
|
||||||
|
|
||||||
// HomeItemModel(
|
// HomeItemModel(
|
||||||
// title: 'Move in',
|
// title: 'Move in',
|
||||||
// icon: Assets.moveinIcon,
|
// icon: Assets.moveinIcon,
|
||||||
|
@ -50,8 +50,9 @@ class HomeMobilePage extends StatelessWidget {
|
|||||||
height: size.height * 0.6,
|
height: size.height * 0.6,
|
||||||
width: size.width * 0.68,
|
width: size.width * 0.68,
|
||||||
child: GridView.builder(
|
child: GridView.builder(
|
||||||
itemCount: 3,
|
itemCount: homeItems.length,
|
||||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
gridDelegate:
|
||||||
|
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
crossAxisCount: 2,
|
crossAxisCount: 2,
|
||||||
crossAxisSpacing: 20.0,
|
crossAxisSpacing: 20.0,
|
||||||
mainAxisSpacing: 20.0,
|
mainAxisSpacing: 20.0,
|
||||||
@ -60,10 +61,11 @@ class HomeMobilePage extends StatelessWidget {
|
|||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return HomeCard(
|
return HomeCard(
|
||||||
index: index,
|
index: index,
|
||||||
active: homeItems[index]['active'],
|
active: homeBloc.homeItems[index].active!,
|
||||||
name: homeItems[index]['title'],
|
name: homeBloc.homeItems[index].title!,
|
||||||
img: homeItems[index]['icon'],
|
img: homeBloc.homeItems[index].icon!,
|
||||||
onTap: () => homeBloc.homeItems[index].onPress(context),
|
onTap: () =>
|
||||||
|
homeBloc.homeItems[index].onPress(context),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -94,6 +96,11 @@ class HomeMobilePage extends StatelessWidget {
|
|||||||
'icon': Assets.devicesIcon,
|
'icon': Assets.devicesIcon,
|
||||||
'active': true,
|
'active': true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'title': 'Syncrow Analytics',
|
||||||
|
'icon': Assets.iconEdit,
|
||||||
|
'active': true,
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// 'title': 'Move in',
|
// 'title': 'Move in',
|
||||||
// 'icon': Assets.moveinIcon,
|
// 'icon': Assets.moveinIcon,
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
|
|
||||||
import 'package:syncrow_web/pages/home/view/agreement_and_privacy_dialog.dart';
|
|
||||||
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
|
||||||
import 'package:syncrow_web/pages/home/bloc/home_state.dart';
|
import 'package:syncrow_web/pages/home/bloc/home_state.dart';
|
||||||
|
import 'package:syncrow_web/pages/home/view/agreement_and_privacy_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/home/view/home_card.dart';
|
import 'package:syncrow_web/pages/home/view/home_card.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
||||||
@ -24,7 +24,7 @@ class _HomeWebPageState extends State<HomeWebPage> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
final homeBloc = BlocProvider.of<HomeBloc>(context);
|
final homeBloc = BlocProvider.of<HomeBloc>(context);
|
||||||
homeBloc.add(FetchUserInfo());
|
homeBloc.add(const FetchUserInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -97,7 +97,7 @@ class _HomeWebPageState extends State<HomeWebPage> {
|
|||||||
height: size.height * 0.6,
|
height: size.height * 0.6,
|
||||||
width: size.width * 0.68,
|
width: size.width * 0.68,
|
||||||
child: GridView.builder(
|
child: GridView.builder(
|
||||||
itemCount: 3, // Change this count if needed.
|
itemCount: homeBloc.homeItems.length,
|
||||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
crossAxisCount: 3, // Adjust as needed.
|
crossAxisCount: 3, // Adjust as needed.
|
||||||
crossAxisSpacing: 20.0,
|
crossAxisSpacing: 20.0,
|
||||||
|
@ -17,7 +17,15 @@ import 'package:syncrow_web/utils/style.dart';
|
|||||||
class SpaceTreeView extends StatefulWidget {
|
class SpaceTreeView extends StatefulWidget {
|
||||||
final bool? isSide;
|
final bool? isSide;
|
||||||
final Function onSelect;
|
final Function onSelect;
|
||||||
const SpaceTreeView({required this.onSelect, this.isSide, super.key});
|
final bool shouldDisableDeselectingChildrenOfSelectedParent;
|
||||||
|
final Widget? title;
|
||||||
|
const SpaceTreeView({
|
||||||
|
required this.onSelect,
|
||||||
|
this.isSide,
|
||||||
|
super.key,
|
||||||
|
this.shouldDisableDeselectingChildrenOfSelectedParent = false,
|
||||||
|
this.title,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<SpaceTreeView> createState() => _SpaceTreeViewState();
|
State<SpaceTreeView> createState() => _SpaceTreeViewState();
|
||||||
@ -41,17 +49,31 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<SpaceTreeBloc, SpaceTreeState>(builder: (context, state) {
|
return BlocBuilder<SpaceTreeBloc, SpaceTreeState>(builder: (context, state) {
|
||||||
final communities =
|
final communities = state.searchQuery.isNotEmpty
|
||||||
state.searchQuery.isNotEmpty ? state.filteredCommunity : state.communityList;
|
? state.filteredCommunity
|
||||||
|
: state.communityList;
|
||||||
return Container(
|
return Container(
|
||||||
height: MediaQuery.sizeOf(context).height,
|
height: MediaQuery.sizeOf(context).height,
|
||||||
decoration: widget.isSide == true
|
decoration: widget.isSide == true
|
||||||
? subSectionContainerDecoration.copyWith(color: ColorsManager.whiteColors)
|
? subSectionContainerDecoration.copyWith(
|
||||||
|
color: ColorsManager.whiteColors)
|
||||||
: const BoxDecoration(color: ColorsManager.whiteColors),
|
: const BoxDecoration(color: ColorsManager.whiteColors),
|
||||||
child: state is SpaceTreeLoadingState
|
child: state is SpaceTreeLoadingState
|
||||||
? const Center(child: CircularProgressIndicator())
|
? const Center(child: CircularProgressIndicator())
|
||||||
: Column(
|
: Column(
|
||||||
children: [
|
children: [
|
||||||
|
if (widget.title != null)
|
||||||
|
Container(
|
||||||
|
alignment: AlignmentDirectional.centerStart,
|
||||||
|
padding: const EdgeInsets.all(24),
|
||||||
|
child: DefaultTextStyle(
|
||||||
|
style: context.textTheme.titleMedium!.copyWith(
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
fontSize: 20,
|
||||||
|
),
|
||||||
|
child: widget.title!,
|
||||||
|
),
|
||||||
|
),
|
||||||
if (widget.isSide == true)
|
if (widget.isSide == true)
|
||||||
Container(
|
Container(
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
@ -79,10 +101,12 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
|
|||||||
style: context.textTheme.bodyMedium?.copyWith(
|
style: context.textTheme.bodyMedium?.copyWith(
|
||||||
color: ColorsManager.blackColor,
|
color: ColorsManager.blackColor,
|
||||||
),
|
),
|
||||||
onChanged: (value) => context.read<SpaceTreeBloc>().add(
|
onChanged: (value) =>
|
||||||
|
context.read<SpaceTreeBloc>().add(
|
||||||
SearchQueryEvent(value),
|
SearchQueryEvent(value),
|
||||||
),
|
),
|
||||||
decoration: textBoxDecoration(radios: 20)?.copyWith(
|
decoration:
|
||||||
|
textBoxDecoration(radios: 20)?.copyWith(
|
||||||
fillColor: Colors.white,
|
fillColor: Colors.white,
|
||||||
suffixIcon: Padding(
|
suffixIcon: Padding(
|
||||||
padding: const EdgeInsets.only(right: 16),
|
padding: const EdgeInsets.only(right: 16),
|
||||||
@ -92,7 +116,8 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
|
|||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
hintStyle: context.textTheme.bodyMedium?.copyWith(
|
hintStyle:
|
||||||
|
context.textTheme.bodyMedium?.copyWith(
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: ColorsManager.textGray,
|
color: ColorsManager.textGray,
|
||||||
@ -131,11 +156,12 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
|
|||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return CustomExpansionTileSpaceTree(
|
return CustomExpansionTileSpaceTree(
|
||||||
title: communities[index].name,
|
title: communities[index].name,
|
||||||
isSelected:
|
isSelected: state.selectedCommunities
|
||||||
state.selectedCommunities.contains(communities[index].uuid),
|
.contains(communities[index].uuid),
|
||||||
isSoldCheck:
|
isSoldCheck: state.selectedCommunities
|
||||||
state.selectedCommunities.contains(communities[index].uuid),
|
.contains(communities[index].uuid),
|
||||||
onExpansionChanged: () => context.read<SpaceTreeBloc>().add(
|
onExpansionChanged: () =>
|
||||||
|
context.read<SpaceTreeBloc>().add(
|
||||||
OnCommunityExpanded(
|
OnCommunityExpanded(
|
||||||
communities[index].uuid,
|
communities[index].uuid,
|
||||||
),
|
),
|
||||||
@ -156,8 +182,19 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
|
|||||||
(space) {
|
(space) {
|
||||||
return CustomExpansionTileSpaceTree(
|
return CustomExpansionTileSpaceTree(
|
||||||
title: space.name,
|
title: space.name,
|
||||||
isExpanded: state.expandedSpaces.contains(space.uuid),
|
isExpanded:
|
||||||
|
state.expandedSpaces.contains(space.uuid),
|
||||||
onItemSelected: () {
|
onItemSelected: () {
|
||||||
|
final isParentSelected = _isParentSelected(
|
||||||
|
state,
|
||||||
|
communities[index],
|
||||||
|
space,
|
||||||
|
);
|
||||||
|
if (widget
|
||||||
|
.shouldDisableDeselectingChildrenOfSelectedParent &&
|
||||||
|
isParentSelected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
context.read<SpaceTreeBloc>().add(
|
context.read<SpaceTreeBloc>().add(
|
||||||
OnSpaceSelected(
|
OnSpaceSelected(
|
||||||
communities[index],
|
communities[index],
|
||||||
@ -167,15 +204,18 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
|
|||||||
);
|
);
|
||||||
widget.onSelect();
|
widget.onSelect();
|
||||||
},
|
},
|
||||||
onExpansionChanged: () => context.read<SpaceTreeBloc>().add(
|
onExpansionChanged: () =>
|
||||||
|
context.read<SpaceTreeBloc>().add(
|
||||||
OnSpaceExpanded(
|
OnSpaceExpanded(
|
||||||
communities[index].uuid,
|
communities[index].uuid,
|
||||||
space.uuid ?? '',
|
space.uuid ?? '',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
isSelected: state.selectedSpaces.contains(space.uuid) ||
|
isSelected: state.selectedSpaces
|
||||||
|
.contains(space.uuid) ||
|
||||||
|
state.soldCheck.contains(space.uuid),
|
||||||
|
isSoldCheck:
|
||||||
state.soldCheck.contains(space.uuid),
|
state.soldCheck.contains(space.uuid),
|
||||||
isSoldCheck: state.soldCheck.contains(space.uuid),
|
|
||||||
children: _buildNestedSpaces(
|
children: _buildNestedSpaces(
|
||||||
context,
|
context,
|
||||||
state,
|
state,
|
||||||
@ -196,6 +236,13 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _isParentSelected(
|
||||||
|
SpaceTreeState state, CommunityModel community, SpaceModel space) {
|
||||||
|
return state.selectedCommunities.contains(community.uuid) ||
|
||||||
|
(space.spaceModel?.uuid != null &&
|
||||||
|
state.selectedSpaces.contains(space.spaceModel?.uuid));
|
||||||
|
}
|
||||||
|
|
||||||
List<Widget> _buildNestedSpaces(
|
List<Widget> _buildNestedSpaces(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
SpaceTreeState state,
|
SpaceTreeState state,
|
||||||
@ -204,8 +251,8 @@ class _SpaceTreeViewState extends State<SpaceTreeView> {
|
|||||||
) {
|
) {
|
||||||
return space.children.map((child) {
|
return space.children.map((child) {
|
||||||
return CustomExpansionTileSpaceTree(
|
return CustomExpansionTileSpaceTree(
|
||||||
isSelected:
|
isSelected: state.selectedSpaces.contains(child.uuid) ||
|
||||||
state.selectedSpaces.contains(child.uuid) || state.soldCheck.contains(child.uuid),
|
state.soldCheck.contains(child.uuid),
|
||||||
isSoldCheck: state.soldCheck.contains(child.uuid),
|
isSoldCheck: state.soldCheck.contains(child.uuid),
|
||||||
title: child.name,
|
title: child.name,
|
||||||
isExpanded: state.expandedSpaces.contains(child.uuid),
|
isExpanded: state.expandedSpaces.contains(child.uuid),
|
||||||
|
@ -457,17 +457,16 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
|
|||||||
emit(SpaceManagementLoading());
|
emit(SpaceManagementLoading());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final spaceTreeState = event.context.read<SpaceTreeBloc>().state;
|
|
||||||
|
|
||||||
final updatedSpaces =
|
final updatedSpaces =
|
||||||
await saveSpacesHierarchically(event.context, event.spaces, event.communityUuid);
|
await saveSpacesHierarchically(event.context, event.spaces, event.communityUuid);
|
||||||
|
|
||||||
final allSpaces = await _fetchSpacesForCommunity(event.communityUuid);
|
final allSpaces = await _fetchSpacesForCommunity(event.communityUuid);
|
||||||
|
|
||||||
emit(SpaceCreationSuccess(spaces: updatedSpaces));
|
emit(SpaceCreationSuccess(spaces: updatedSpaces));
|
||||||
|
|
||||||
if (previousState is SpaceManagementLoaded) {
|
if (previousState is SpaceManagementLoaded) {
|
||||||
await _updateLoadedState(
|
await _updateLoadedState(
|
||||||
spaceTreeState,
|
event.context,
|
||||||
previousState,
|
previousState,
|
||||||
allSpaces,
|
allSpaces,
|
||||||
event.communityUuid,
|
event.communityUuid,
|
||||||
@ -484,17 +483,15 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateLoadedState(
|
Future<void> _updateLoadedState(
|
||||||
SpaceTreeState spaceTreeState,
|
BuildContext context,
|
||||||
SpaceManagementLoaded previousState,
|
SpaceManagementLoaded previousState,
|
||||||
List<SpaceModel> allSpaces,
|
List<SpaceModel> allSpaces,
|
||||||
String communityUuid,
|
String communityUuid,
|
||||||
Emitter<SpaceManagementState> emit,
|
Emitter<SpaceManagementState> emit,
|
||||||
) async {
|
) async {
|
||||||
try {
|
|
||||||
var prevSpaceModels = await fetchSpaceModels();
|
var prevSpaceModels = await fetchSpaceModels();
|
||||||
|
|
||||||
await fetchTags();
|
await fetchTags();
|
||||||
|
final spaceTreeState = context.read<SpaceTreeBloc>().state;
|
||||||
final communities = spaceTreeState.searchQuery.isNotEmpty
|
final communities = spaceTreeState.searchQuery.isNotEmpty
|
||||||
? spaceTreeState.filteredCommunity
|
? spaceTreeState.filteredCommunity
|
||||||
: spaceTreeState.communityList;
|
: spaceTreeState.communityList;
|
||||||
@ -510,14 +507,12 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
|
|||||||
selectedCommunity: community,
|
selectedCommunity: community,
|
||||||
selectedSpace: null,
|
selectedSpace: null,
|
||||||
spaceModels: prevSpaceModels,
|
spaceModels: prevSpaceModels,
|
||||||
allTags: _cachedTags ?? [],
|
allTags: _cachedTags ?? []));
|
||||||
));
|
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
print("Community not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e, stackTrace) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<SpaceModel>> saveSpacesHierarchically(
|
Future<List<SpaceModel>> saveSpacesHierarchically(
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/view/access_management.dart';
|
import 'package:syncrow_web/pages/access_management/view/access_management.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/analytics/views/analytics_page.dart';
|
||||||
import 'package:syncrow_web/pages/auth/view/login_page.dart';
|
import 'package:syncrow_web/pages/auth/view/login_page.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/view/device_managment_page.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/view/device_managment_page.dart';
|
||||||
import 'package:syncrow_web/pages/home/view/home_page.dart';
|
import 'package:syncrow_web/pages/home/view/home_page.dart';
|
||||||
@ -37,6 +38,11 @@ class AppRoutes {
|
|||||||
GoRoute(
|
GoRoute(
|
||||||
path: RoutesConst.rolesAndPermissions,
|
path: RoutesConst.rolesAndPermissions,
|
||||||
builder: (context, state) => const RolesAndPermissionPage()),
|
builder: (context, state) => const RolesAndPermissionPage()),
|
||||||
|
GoRoute(
|
||||||
|
path: RoutesConst.analytics,
|
||||||
|
name: 'analytics',
|
||||||
|
builder: (context, state) => const AnalyticsPage(),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -480,4 +480,5 @@ class Assets {
|
|||||||
static const String DisappeDelayIcon = 'assets/icons/disappe_delay_icon.svg';
|
static const String DisappeDelayIcon = 'assets/icons/disappe_delay_icon.svg';
|
||||||
static const String indentLevelIcon = 'assets/icons/indent_level_icon.svg';
|
static const String indentLevelIcon = 'assets/icons/indent_level_icon.svg';
|
||||||
static const String triggerLevelIcon = 'assets/icons/trigger_level_icon.svg';
|
static const String triggerLevelIcon = 'assets/icons/trigger_level_icon.svg';
|
||||||
|
static const String blankCalendar = 'assets/icons/blank_calendar.svg';
|
||||||
}
|
}
|
||||||
|
@ -6,4 +6,5 @@ class RoutesConst {
|
|||||||
static const String deviceManagementPage = '/device-management-page';
|
static const String deviceManagementPage = '/device-management-page';
|
||||||
static const String spacesManagementPage = '/spaces_management-page';
|
static const String spacesManagementPage = '/spaces_management-page';
|
||||||
static const String rolesAndPermissions = '/roles_and_Permissions-page';
|
static const String rolesAndPermissions = '/roles_and_Permissions-page';
|
||||||
|
static const String analytics = '/syncrow_analytics';
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user