mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-11-27 12:14:56 +00:00
added space model link to space dialog
This commit is contained in:
@ -172,8 +172,12 @@ class SpaceManagementBloc
|
|||||||
}).toList(),
|
}).toList(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
List<SpaceTemplateModel> spaceModels =
|
||||||
|
await _spaceModelApi.listSpaceModels(page: 1);
|
||||||
emit(SpaceManagementLoaded(
|
emit(SpaceManagementLoaded(
|
||||||
communities: updatedCommunities, products: _cachedProducts ?? []));
|
communities: updatedCommunities,
|
||||||
|
products: _cachedProducts ?? [],
|
||||||
|
spaceModels: spaceModels));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(SpaceManagementError('Error loading communities and spaces: $e'));
|
emit(SpaceManagementError('Error loading communities and spaces: $e'));
|
||||||
}
|
}
|
||||||
@ -276,12 +280,16 @@ class SpaceManagementBloc
|
|||||||
final communities = List<CommunityModel>.from(
|
final communities = List<CommunityModel>.from(
|
||||||
(previousState as dynamic).communities,
|
(previousState as dynamic).communities,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final spaceModels = List<SpaceTemplateModel>.from(
|
||||||
|
(previousState as dynamic).spaceModels,
|
||||||
|
);
|
||||||
emit(SpaceManagementLoaded(
|
emit(SpaceManagementLoaded(
|
||||||
communities: communities,
|
communities: communities,
|
||||||
products: _cachedProducts ?? [],
|
products: _cachedProducts ?? [],
|
||||||
selectedCommunity: selectedCommunity,
|
selectedCommunity: selectedCommunity,
|
||||||
selectedSpace: selectedSpace,
|
selectedSpace: selectedSpace,
|
||||||
));
|
spaceModels: spaceModels ?? []));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(SpaceManagementError('Error updating state: $e'));
|
emit(SpaceManagementError('Error updating state: $e'));
|
||||||
|
|||||||
@ -20,12 +20,15 @@ class SpaceManagementLoaded extends SpaceManagementState {
|
|||||||
final List<ProductModel> products;
|
final List<ProductModel> products;
|
||||||
CommunityModel? selectedCommunity;
|
CommunityModel? selectedCommunity;
|
||||||
SpaceModel? selectedSpace;
|
SpaceModel? selectedSpace;
|
||||||
|
List<SpaceTemplateModel>? spaceModels;
|
||||||
|
|
||||||
SpaceManagementLoaded(
|
SpaceManagementLoaded(
|
||||||
{required this.communities,
|
{required this.communities,
|
||||||
required this.products,
|
required this.products,
|
||||||
this.selectedCommunity,
|
this.selectedCommunity,
|
||||||
this.selectedSpace});
|
this.selectedSpace,
|
||||||
|
this.spaceModels
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class SpaceModelManagenetLoaded extends SpaceManagementState {
|
class SpaceModelManagenetLoaded extends SpaceManagementState {
|
||||||
@ -35,10 +38,13 @@ class SpaceModelManagenetLoaded extends SpaceManagementState {
|
|||||||
class BlankState extends SpaceManagementState {
|
class BlankState extends SpaceManagementState {
|
||||||
final List<CommunityModel> communities;
|
final List<CommunityModel> communities;
|
||||||
final List<ProductModel> products;
|
final List<ProductModel> products;
|
||||||
|
List<SpaceTemplateModel>? spaceModels;
|
||||||
|
|
||||||
|
|
||||||
BlankState({
|
BlankState({
|
||||||
required this.communities,
|
required this.communities,
|
||||||
required this.products,
|
required this.products,
|
||||||
|
this.spaceModels
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/connection_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/connection_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
@ -21,6 +21,7 @@ class SpaceModel {
|
|||||||
bool isHovered;
|
bool isHovered;
|
||||||
SpaceStatus status;
|
SpaceStatus status;
|
||||||
String internalId;
|
String internalId;
|
||||||
|
SpaceTemplateModel? spaceModel;
|
||||||
|
|
||||||
List<Connection> outgoingConnections = []; // Connections from this space
|
List<Connection> outgoingConnections = []; // Connections from this space
|
||||||
Connection? incomingConnection; // Connections to this space
|
Connection? incomingConnection; // Connections to this space
|
||||||
@ -40,6 +41,7 @@ class SpaceModel {
|
|||||||
this.isHovered = false,
|
this.isHovered = false,
|
||||||
this.incomingConnection,
|
this.incomingConnection,
|
||||||
this.status = SpaceStatus.unchanged,
|
this.status = SpaceStatus.unchanged,
|
||||||
|
this.spaceModel,
|
||||||
}) : internalId = internalId ?? const Uuid().v4();
|
}) : internalId = internalId ?? const Uuid().v4();
|
||||||
|
|
||||||
factory SpaceModel.fromJson(Map<String, dynamic> json,
|
factory SpaceModel.fromJson(Map<String, dynamic> json,
|
||||||
|
|||||||
@ -51,19 +51,25 @@ class SpaceManagementPageState extends State<SpaceManagementPage> {
|
|||||||
selectedCommunity: null,
|
selectedCommunity: null,
|
||||||
selectedSpace: null,
|
selectedSpace: null,
|
||||||
products: state.products,
|
products: state.products,
|
||||||
|
shouldNavigateToSpaceModelPage: false,
|
||||||
);
|
);
|
||||||
} else if (state is SpaceManagementLoaded) {
|
} else if (state is SpaceManagementLoaded) {
|
||||||
|
print("sdksndsnadf ${state.spaceModels}");
|
||||||
return LoadedSpaceView(
|
return LoadedSpaceView(
|
||||||
communities: state.communities,
|
communities: state.communities,
|
||||||
selectedCommunity: state.selectedCommunity,
|
selectedCommunity: state.selectedCommunity,
|
||||||
selectedSpace: state.selectedSpace,
|
selectedSpace: state.selectedSpace,
|
||||||
products: state.products,
|
products: state.products,
|
||||||
|
spaceModels: state.spaceModels,
|
||||||
|
shouldNavigateToSpaceModelPage: false,
|
||||||
);
|
);
|
||||||
} else if (state is SpaceModelLoaded) {
|
} else if (state is SpaceModelLoaded) {
|
||||||
return LoadedSpaceView(
|
return LoadedSpaceView(
|
||||||
communities: state.communities,
|
communities: state.communities,
|
||||||
products: state.products,
|
products: state.products,
|
||||||
spaceModels: state.spaceModels);
|
spaceModels: state.spaceModels,
|
||||||
|
shouldNavigateToSpaceModelPage: true,
|
||||||
|
);
|
||||||
} else if (state is SpaceManagementError) {
|
} else if (state is SpaceManagementError) {
|
||||||
return Center(child: Text('Error: ${state.errorMessage}'));
|
return Center(child: Text('Error: ${state.errorMessage}'));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/dialogs/c
|
|||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/curved_line_painter.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/curved_line_painter.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/space_card_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/space_card_widget.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/space_container_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/space_container_widget.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class CommunityStructureArea extends StatefulWidget {
|
class CommunityStructureArea extends StatefulWidget {
|
||||||
@ -26,6 +27,8 @@ class CommunityStructureArea extends StatefulWidget {
|
|||||||
final ValueChanged<SpaceModel?>? onSpaceSelected;
|
final ValueChanged<SpaceModel?>? onSpaceSelected;
|
||||||
final List<CommunityModel> communities;
|
final List<CommunityModel> communities;
|
||||||
final List<SpaceModel> spaces;
|
final List<SpaceModel> spaces;
|
||||||
|
final List<SpaceTemplateModel>? spaceModels;
|
||||||
|
|
||||||
|
|
||||||
CommunityStructureArea({
|
CommunityStructureArea({
|
||||||
this.selectedCommunity,
|
this.selectedCommunity,
|
||||||
@ -34,6 +37,7 @@ class CommunityStructureArea extends StatefulWidget {
|
|||||||
this.products,
|
this.products,
|
||||||
required this.spaces,
|
required this.spaces,
|
||||||
this.onSpaceSelected,
|
this.onSpaceSelected,
|
||||||
|
this.spaceModels,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -49,9 +53,11 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
bool isEditingName = false;
|
bool isEditingName = false;
|
||||||
late TransformationController _transformationController;
|
late TransformationController _transformationController;
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
print("sxdsf ${widget.spaceModels}");
|
||||||
spaces = widget.spaces.isNotEmpty ? flattenSpaces(widget.spaces) : [];
|
spaces = widget.spaces.isNotEmpty ? flattenSpaces(widget.spaces) : [];
|
||||||
connections =
|
connections =
|
||||||
widget.spaces.isNotEmpty ? createConnections(widget.spaces) : [];
|
widget.spaces.isNotEmpty ? createConnections(widget.spaces) : [];
|
||||||
@ -284,6 +290,7 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return CreateSpaceDialog(
|
return CreateSpaceDialog(
|
||||||
products: widget.products,
|
products: widget.products,
|
||||||
|
spaceModels: widget.spaceModels,
|
||||||
parentSpace: parentIndex != null ? spaces[parentIndex] : null,
|
parentSpace: parentIndex != null ? spaces[parentIndex] : null,
|
||||||
onCreateSpace: (String name, String icon,
|
onCreateSpace: (String name, String icon,
|
||||||
List<SelectedProduct> selectedProducts) {
|
List<SelectedProduct> selectedProducts) {
|
||||||
|
|||||||
@ -7,8 +7,8 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_pr
|
|||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/add_device_type_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/add_device_type_widget.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/dialogs/icon_selection_dialog.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/dialogs/icon_selection_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/hoverable_button.dart';
|
import 'package:syncrow_web/pages/spaces_management/link_space_model/view/link_space_model_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/selected_products_button_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/constants/space_icon_const.dart';
|
import 'package:syncrow_web/utils/constants/space_icon_const.dart';
|
||||||
@ -23,6 +23,7 @@ class CreateSpaceDialog extends StatefulWidget {
|
|||||||
final List<SelectedProduct> selectedProducts;
|
final List<SelectedProduct> selectedProducts;
|
||||||
final SpaceModel? parentSpace;
|
final SpaceModel? parentSpace;
|
||||||
final SpaceModel? editSpace;
|
final SpaceModel? editSpace;
|
||||||
|
final List<SpaceTemplateModel>? spaceModels;
|
||||||
|
|
||||||
const CreateSpaceDialog(
|
const CreateSpaceDialog(
|
||||||
{super.key,
|
{super.key,
|
||||||
@ -33,7 +34,8 @@ class CreateSpaceDialog extends StatefulWidget {
|
|||||||
this.icon,
|
this.icon,
|
||||||
this.isEdit = false,
|
this.isEdit = false,
|
||||||
this.editSpace,
|
this.editSpace,
|
||||||
this.selectedProducts = const []});
|
this.selectedProducts = const [],
|
||||||
|
this.spaceModels});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
CreateSpaceDialogState createState() => CreateSpaceDialogState();
|
CreateSpaceDialogState createState() => CreateSpaceDialogState();
|
||||||
@ -59,32 +61,33 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
enteredName.isNotEmpty || nameController.text.isNotEmpty;
|
enteredName.isNotEmpty || nameController.text.isNotEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final screenWidth = MediaQuery.of(context).size.width;
|
final screenWidth = MediaQuery.of(context).size.width;
|
||||||
|
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: widget.isEdit
|
title: widget.isEdit
|
||||||
? const Text('Edit Space')
|
? const Text('Edit Space')
|
||||||
: const Text('Create New Space'),
|
: const Text('Create New Space'),
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
content: SizedBox(
|
content: SizedBox(
|
||||||
width: screenWidth * 0.5, // Limit dialog width
|
width: screenWidth * 0.5,
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
// Scrollable content to prevent overflow
|
child: Row(
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Expanded(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
flex: 1,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Stack(
|
Stack(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
width: screenWidth * 0.1, // Adjusted width
|
width: screenWidth * 0.1,
|
||||||
height: screenWidth * 0.1, // Adjusted height
|
height: screenWidth * 0.1,
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
color: ColorsManager.boxColor,
|
color: ColorsManager.boxColor,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
@ -96,30 +99,33 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
height: screenWidth * 0.04,
|
height: screenWidth * 0.04,
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 6,
|
top: 20,
|
||||||
right: 6,
|
right: 20,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: _showIconSelectionDialog,
|
onTap: _showIconSelectionDialog,
|
||||||
child: Container(
|
child: Container(
|
||||||
width: screenWidth * 0.020,
|
width: 24,
|
||||||
height: screenWidth * 0.020,
|
height: 24,
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
Assets.iconEdit,
|
Assets.iconEdit,
|
||||||
width: screenWidth * 0.06,
|
width: 16,
|
||||||
height: screenWidth * 0.06,
|
height: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 20),
|
||||||
Expanded(
|
Expanded(
|
||||||
// Ensure the text field expands responsively
|
flex: 2,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -193,9 +199,11 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
?.copyWith(color: ColorsManager.red),
|
?.copyWith(color: ColorsManager.red),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 10),
|
||||||
DefaultButton(
|
DefaultButton(
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
|
_showLinkSpaceModelDialog(context);
|
||||||
|
},
|
||||||
backgroundColor: ColorsManager.textFieldGreyColor,
|
backgroundColor: ColorsManager.textFieldGreyColor,
|
||||||
foregroundColor: Colors.black,
|
foregroundColor: Colors.black,
|
||||||
borderColor: ColorsManager.neutralGray,
|
borderColor: ColorsManager.neutralGray,
|
||||||
@ -209,9 +217,8 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 6.0),
|
padding: const EdgeInsets.only(left: 6.0),
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
Assets.addIcon,
|
Assets.link,
|
||||||
width: screenWidth *
|
width: screenWidth * 0.015, // Adjust icon size
|
||||||
0.015, // Adjust icon size
|
|
||||||
height: screenWidth * 0.015,
|
height: screenWidth * 0.015,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -219,17 +226,43 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Link a space model',
|
'Link a space model',
|
||||||
overflow: TextOverflow
|
overflow:
|
||||||
.ellipsis, // Prevent overflow
|
TextOverflow.ellipsis, // Prevent overflow
|
||||||
style: Theme.of(context)
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
.textTheme
|
|
||||||
.bodyMedium,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
const SizedBox(height: 30),
|
),
|
||||||
|
const SizedBox(height: 25),
|
||||||
|
const Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Divider(
|
||||||
|
color: ColorsManager.neutralGray,
|
||||||
|
thickness: 1.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: Text(
|
||||||
|
'OR',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Divider(
|
||||||
|
color: ColorsManager.neutralGray,
|
||||||
|
thickness: 1.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 25),
|
||||||
DefaultButton(
|
DefaultButton(
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
backgroundColor: ColorsManager.textFieldGreyColor,
|
backgroundColor: ColorsManager.textFieldGreyColor,
|
||||||
@ -246,8 +279,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
padding: const EdgeInsets.only(left: 6.0),
|
padding: const EdgeInsets.only(left: 6.0),
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
Assets.addIcon,
|
Assets.addIcon,
|
||||||
width: screenWidth *
|
width: screenWidth * 0.015, // Adjust icon size
|
||||||
0.015, // Adjust icon size
|
|
||||||
height: screenWidth * 0.015,
|
height: screenWidth * 0.015,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -255,28 +287,16 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Create sub space',
|
'Create sub space',
|
||||||
overflow: TextOverflow
|
overflow:
|
||||||
.ellipsis, // Prevent overflow
|
TextOverflow.ellipsis, // Prevent overflow
|
||||||
style: Theme.of(context)
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
.textTheme
|
|
||||||
.bodyMedium,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
if (selectedProducts.isNotEmpty)
|
),
|
||||||
SelectedProductsButtons(
|
const SizedBox(height: 10),
|
||||||
products: widget.products ?? [],
|
|
||||||
selectedProducts: selectedProducts,
|
|
||||||
onProductsUpdated: (updatedProducts) {
|
|
||||||
setState(() {
|
|
||||||
selectedProducts = updatedProducts;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
context: context,
|
|
||||||
)
|
|
||||||
else
|
|
||||||
DefaultButton(
|
DefaultButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showDialog(
|
showDialog(
|
||||||
@ -305,30 +325,26 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
padding: const EdgeInsets.only(left: 6.0),
|
padding: const EdgeInsets.only(left: 6.0),
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
Assets.addIcon,
|
Assets.addIcon,
|
||||||
width: screenWidth *
|
width: screenWidth * 0.015, // Adjust icon size
|
||||||
0.015, // Adjust icon size
|
|
||||||
height: screenWidth * 0.015,
|
height: screenWidth * 0.015,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 3),
|
const SizedBox(width: 3),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Add devices / Assign a space model',
|
'Add devices',
|
||||||
overflow: TextOverflow
|
overflow:
|
||||||
.ellipsis, // Prevent overflow
|
TextOverflow.ellipsis, // Prevent overflow
|
||||||
style: Theme.of(context)
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
.textTheme
|
|
||||||
.bodyMedium,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -401,4 +417,22 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
|
|||||||
(widget.editSpace?.children.any((child) => child.name == value) ??
|
(widget.editSpace?.children.any((child) => child.name == value) ??
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _showLinkSpaceModelDialog(BuildContext context) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return LinkSpaceModelDialog(
|
||||||
|
spaceModels: widget.spaceModels ?? [],
|
||||||
|
onSave: (selectedModel) {
|
||||||
|
if (selectedModel != null) {
|
||||||
|
print('Selected Model: ${selectedModel.modelName}');
|
||||||
|
} else {
|
||||||
|
print('No model selected');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,12 +11,13 @@ import 'package:syncrow_web/pages/spaces_management/space_model/models/space_tem
|
|||||||
import 'package:syncrow_web/pages/spaces_management/space_model/view/space_model_page.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/view/space_model_page.dart';
|
||||||
import 'package:syncrow_web/services/space_model_mang_api.dart';
|
import 'package:syncrow_web/services/space_model_mang_api.dart';
|
||||||
|
|
||||||
class LoadedSpaceView extends StatefulWidget {
|
class LoadedSpaceView extends StatelessWidget {
|
||||||
final List<CommunityModel> communities;
|
final List<CommunityModel> communities;
|
||||||
final CommunityModel? selectedCommunity;
|
final CommunityModel? selectedCommunity;
|
||||||
final SpaceModel? selectedSpace;
|
final SpaceModel? selectedSpace;
|
||||||
final List<ProductModel>? products;
|
final List<ProductModel>? products;
|
||||||
final List<SpaceTemplateModel>? spaceModels;
|
final List<SpaceTemplateModel>? spaceModels;
|
||||||
|
final bool shouldNavigateToSpaceModelPage;
|
||||||
|
|
||||||
const LoadedSpaceView({
|
const LoadedSpaceView({
|
||||||
super.key,
|
super.key,
|
||||||
@ -25,17 +26,11 @@ class LoadedSpaceView extends StatefulWidget {
|
|||||||
this.selectedSpace,
|
this.selectedSpace,
|
||||||
this.products,
|
this.products,
|
||||||
this.spaceModels,
|
this.spaceModels,
|
||||||
|
required this.shouldNavigateToSpaceModelPage
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
|
||||||
_LoadedStateViewState createState() => _LoadedStateViewState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _LoadedStateViewState extends State<LoadedSpaceView> {
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final bool hasSpaceModels =
|
|
||||||
widget.spaceModels != null && widget.spaceModels!.isNotEmpty;
|
|
||||||
|
|
||||||
return Stack(
|
return Stack(
|
||||||
clipBehavior: Clip.none,
|
clipBehavior: Clip.none,
|
||||||
@ -43,29 +38,29 @@ class _LoadedStateViewState extends State<LoadedSpaceView> {
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
SidebarWidget(
|
SidebarWidget(
|
||||||
communities: widget.communities,
|
communities: communities,
|
||||||
selectedSpaceUuid: widget.selectedSpace?.uuid ??
|
selectedSpaceUuid:
|
||||||
widget.selectedCommunity?.uuid ??
|
selectedSpace?.uuid ?? selectedCommunity?.uuid ?? '',
|
||||||
'',
|
|
||||||
),
|
),
|
||||||
hasSpaceModels
|
shouldNavigateToSpaceModelPage
|
||||||
? Expanded(
|
? Expanded(
|
||||||
child: BlocProvider(
|
child: BlocProvider(
|
||||||
create: (context) => SpaceModelBloc(
|
create: (context) => SpaceModelBloc(
|
||||||
api: SpaceModelManagementApi(),
|
api: SpaceModelManagementApi(),
|
||||||
initialSpaceModels: widget.spaceModels ?? [],
|
initialSpaceModels: spaceModels ?? [],
|
||||||
),
|
),
|
||||||
child: SpaceModelPage(
|
child: SpaceModelPage(
|
||||||
products: widget.products,
|
products: products,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: CommunityStructureArea(
|
: CommunityStructureArea(
|
||||||
selectedCommunity: widget.selectedCommunity,
|
selectedCommunity: selectedCommunity,
|
||||||
selectedSpace: widget.selectedSpace,
|
selectedSpace: selectedSpace,
|
||||||
spaces: widget.selectedCommunity?.spaces ?? [],
|
spaces: selectedCommunity?.spaces ?? [],
|
||||||
products: widget.products,
|
products: products,
|
||||||
communities: widget.communities,
|
communities: communities,
|
||||||
|
spaceModels: spaceModels,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -0,0 +1,12 @@
|
|||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/link_space_model/bloc/link_space_model_event.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/link_space_model/bloc/link_space_model_state.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class SpaceModelBloc extends Bloc<SpaceModelEvent, SpaceModelState> {
|
||||||
|
SpaceModelBloc() : super(SpaceModelInitial()) {
|
||||||
|
on<SpaceModelSelectedEvent>((event, emit) {
|
||||||
|
emit(SpaceModelSelectedState(event.selectedIndex));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
abstract class SpaceModelEvent {}
|
||||||
|
|
||||||
|
class SpaceModelSelectedEvent extends SpaceModelEvent {
|
||||||
|
final int selectedIndex;
|
||||||
|
|
||||||
|
SpaceModelSelectedEvent(this.selectedIndex);
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
abstract class SpaceModelState {}
|
||||||
|
|
||||||
|
class SpaceModelInitial extends SpaceModelState {}
|
||||||
|
|
||||||
|
class SpaceModelSelectedState extends SpaceModelState {
|
||||||
|
final int selectedIndex;
|
||||||
|
|
||||||
|
SpaceModelSelectedState(this.selectedIndex);
|
||||||
|
}
|
||||||
@ -0,0 +1,131 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/buttons/cancel_button.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/link_space_model/bloc/link_space_model_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/link_space_model/bloc/link_space_model_event.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/link_space_model/bloc/link_space_model_state.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/space_model_card_widget.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
|
class LinkSpaceModelDialog extends StatelessWidget {
|
||||||
|
final Function(SpaceTemplateModel?)? onSave;
|
||||||
|
final int? initialSelectedIndex;
|
||||||
|
final List<SpaceTemplateModel> spaceModels;
|
||||||
|
|
||||||
|
const LinkSpaceModelDialog({
|
||||||
|
Key? key,
|
||||||
|
this.onSave,
|
||||||
|
this.initialSelectedIndex,
|
||||||
|
required this.spaceModels,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => SpaceModelBloc()
|
||||||
|
..add(
|
||||||
|
SpaceModelSelectedEvent(initialSelectedIndex ?? -1),
|
||||||
|
),
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
final bloc = context.read<SpaceModelBloc>();
|
||||||
|
return AlertDialog(
|
||||||
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
|
title: const Text('Link a space model'),
|
||||||
|
content: spaceModels.isNotEmpty
|
||||||
|
? Container(
|
||||||
|
color: ColorsManager.textFieldGreyColor,
|
||||||
|
width: MediaQuery.of(context).size.width * 0.7,
|
||||||
|
height: MediaQuery.of(context).size.height * 0.6,
|
||||||
|
child: BlocBuilder<SpaceModelBloc, SpaceModelState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
int selectedIndex = -1;
|
||||||
|
if (state is SpaceModelSelectedState) {
|
||||||
|
selectedIndex = state.selectedIndex;
|
||||||
|
}
|
||||||
|
return GridView.builder(
|
||||||
|
gridDelegate:
|
||||||
|
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: 2,
|
||||||
|
crossAxisSpacing: 10.0,
|
||||||
|
mainAxisSpacing: 10.0,
|
||||||
|
childAspectRatio: 3,
|
||||||
|
),
|
||||||
|
itemCount: spaceModels.length,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
final model = spaceModels[index];
|
||||||
|
final isSelected = selectedIndex == index;
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
bloc.add(SpaceModelSelectedEvent(index));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.all(10.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: isSelected
|
||||||
|
? ColorsManager.spaceColor
|
||||||
|
: Colors.transparent,
|
||||||
|
width: 2.0,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
),
|
||||||
|
child: SpaceModelCardWidget(model: model),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const Text('No space models available.'),
|
||||||
|
actions: [
|
||||||
|
Center(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
CancelButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
label: 'Cancel',
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
BlocBuilder<SpaceModelBloc, SpaceModelState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final isEnabled = state is SpaceModelSelectedState &&
|
||||||
|
state.selectedIndex >= 0;
|
||||||
|
return SizedBox(
|
||||||
|
width: 140,
|
||||||
|
child: DefaultButton(
|
||||||
|
height: 40,
|
||||||
|
borderRadius: 10,
|
||||||
|
onPressed: isEnabled
|
||||||
|
? () {
|
||||||
|
if (onSave != null) {
|
||||||
|
final selectedModel =
|
||||||
|
state is SpaceModelSelectedState
|
||||||
|
? spaceModels[state.selectedIndex]
|
||||||
|
: null;
|
||||||
|
onSave!(selectedModel);
|
||||||
|
}
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
child: const Text('Save'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -94,14 +94,14 @@ class SpaceModelPage extends StatelessWidget {
|
|||||||
double _calculateChildAspectRatio(BuildContext context) {
|
double _calculateChildAspectRatio(BuildContext context) {
|
||||||
double screenWidth = MediaQuery.of(context).size.width;
|
double screenWidth = MediaQuery.of(context).size.width;
|
||||||
if (screenWidth > 1600) {
|
if (screenWidth > 1600) {
|
||||||
return 2; // Taller cards for larger screens
|
return 2;
|
||||||
}
|
}
|
||||||
if (screenWidth > 1200) {
|
if (screenWidth > 1200) {
|
||||||
return 3; // Adjusted height for medium screens
|
return 3;
|
||||||
} else if (screenWidth > 800) {
|
} else if (screenWidth > 800) {
|
||||||
return 3.5; // Adjusted height for smaller screens
|
return 3.5;
|
||||||
} else {
|
} else {
|
||||||
return 4.0; // Default ratio for smallest screens
|
return 4.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user