Files
syncrow-web/lib/pages/spaces_management/view/spaces_management_page.dart
2024-10-08 11:39:10 +04:00

302 lines
12 KiB
Dart

import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/common/buttons/add_space_button.dart';
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
import 'package:syncrow_web/pages/spaces_management/view/curved_line_painter.dart';
import 'package:syncrow_web/pages/spaces_management/view/dialogs/create_space_dialog.dart';
import 'package:syncrow_web/pages/spaces_management/view/sidebar_widget.dart';
import 'package:syncrow_web/pages/spaces_management/view/space_card_widget.dart';
import 'package:syncrow_web/pages/spaces_management/view/space_container_widget.dart';
import 'package:syncrow_web/services/space_mana_api.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class SpaceManagementPage extends StatefulWidget {
@override
SpaceManagementPageState createState() => SpaceManagementPageState();
}
class SpaceManagementPageState extends State<SpaceManagementPage> {
// Store created spaces
List<SpaceData> spaces = [];
List<Connection> connections = [];
// API instance
final CommunitySpaceManagementApi _api = CommunitySpaceManagementApi();
// Data structure to store community and associated spaces
Map<String, List<SpaceModel>> communitySpaces = {};
@override
void initState() {
super.initState();
_loadCommunityAndSpacesData();
}
// Function to load all communities and their respective spaces
void _loadCommunityAndSpacesData() async {
try {
// Fetch all communities
List<CommunityModel> communities = await _api.fetchCommunities();
for (CommunityModel community in communities) {
// Fetch spaces hierarchy for each community
List<SpaceModel> spaces = await _api.getSpaceHierarchy(community.uuid);
// Store the result in the communitySpaces map
community.spaces = spaces;
}
// Update the state to reflect loaded data
setState(() {
// Optionally, you can initialize something here based on the loaded data
});
} catch (e) {
debugPrint('Error loading communities and spaces: $e');
}
}
void _handleCommunitySelection(String community) {
// Handle community selection here
print("Selected Community: $community");
}
@override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: ColorsManager.whiteColors,
appBar: AppBar(
title: const Text('Space Management'),
),
body: Stack(
clipBehavior: Clip.none,
children: [
Row(
children: [
// Sidebar for navigation and community list
SidebarWidget(
communitySpaces: communitySpaces, // Pass communitySpaces here
onCommunitySelected: _handleCommunitySelection,
),
// Right Side: Community Structure Area
Expanded(
child: Container(
decoration: const BoxDecoration(
color: ColorsManager.whiteColors,
border: Border(
left: BorderSide(
color: ColorsManager.whiteColors,
width: 1.0), // Light left border to match
),
),
// Background color for canvas
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding:
const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 27.0),
width: double.infinity,
decoration: BoxDecoration(
color: ColorsManager.whiteColors,
boxShadow: [
BoxShadow(
color: ColorsManager
.shadowBlackColor, // Subtle shadow
spreadRadius: 0, // No spread
blurRadius: 8, // Softer shadow edges
offset: Offset(0, 4), // Shadow only on the bottom
),
],
),
child: Text(
'Community Structure',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
),
// Use Expanded to ensure InteractiveViewer takes the available space
Expanded(
child: InteractiveViewer(
boundaryMargin:
const EdgeInsets.all(500), // Adjusted to 500
minScale: 0.5, // Minimum zoom scale
maxScale: 2.5, // Maximum zoom scale
panEnabled: true, // Enable panning
scaleEnabled: true, // Enable zooming
child: Container(
width: 2000, // Large canvas
height: 2000, // Large canvas
color: ColorsManager
.transparentColor, // Transparent background
child: Stack(
clipBehavior: Clip.none,
children: [
// Draw lines using a CustomPaint widget
CustomPaint(
size:
Size(2000, 2000), // Explicit canvas size
painter: CurvedLinePainter(connections),
),
Center(
child: spaces.isEmpty
? AddSpaceButton(
onTap: () {
_showCreateSpaceDialog(screenSize);
},
)
: Stack(
children: spaces
.asMap()
.entries
.map((entry) => SpaceCardWidget(
index: entry.key,
screenSize: screenSize,
position: spaces[entry.key]
.position,
isHovered: spaces[entry.key]
.isHovered,
onPanUpdate: (int index,
Offset delta) {
setState(() {
spaces[index]
.position += delta;
});
},
onHoverChanged: (int index,
bool isHovered) {
setState(() {
spaces[index]
.isHovered =
isHovered;
});
},
onButtonTap: (int index,
Offset newPosition,
String direction) {
_showCreateSpaceDialog(
screenSize,
position: spaces[index]
.position +
newPosition,
parentIndex: index,
direction: direction,
);
},
buildSpaceContainer:
(int index) {
return SpaceContainerWidget(
index: index,
icon:
spaces[index].icon,
name:
spaces[index].name,
);
},
))
.toList(),
),
),
],
),
),
),
),
],
),
),
),
],
),
Positioned(
top: 0,
bottom: 0,
left: 300, // Align with the sidebar's width
width: 8, // Width of the gradient border
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
ColorsManager.semiTransparentBlackColor
.withOpacity(0.1), // Light gray
ColorsManager.transparentColor, // Transparent fade
],
),
),
),
),
],
),
);
}
// Function to open the Create Space dialog
void _showCreateSpaceDialog(Size screenSize,
{Offset? position, int? parentIndex, String? direction}) {
showDialog(
context: context,
builder: (BuildContext context) {
return CreateSpaceDialog(
onCreateSpace: (String name, String icon) {
setState(() {
// Set the first space in the center or use passed position
Offset centerPosition = position ??
Offset(
screenSize.width / 2 - 75, // Center horizontally
screenSize.height / 2 -
100, // Slightly above the center vertically
);
SpaceData newSpace =
SpaceData(name: name, icon: icon, position: centerPosition);
spaces.add(newSpace);
// Add connection for down-button
if (parentIndex != null && direction != null) {
connections.add(Connection(
startSpace: spaces[parentIndex],
endSpace: newSpace,
direction: direction,
));
}
});
},
);
},
);
}
}
// Model for storing space information
class SpaceData {
final String name;
final String icon;
Offset position;
bool isHovered;
SpaceData({
required this.name,
required this.icon,
required this.position,
this.isHovered = false,
});
}
// Class for connection lines between spaces
class Connection {
final SpaceData startSpace;
final SpaceData endSpace;
final String direction;
Connection(
{required this.startSpace,
required this.endSpace,
required this.direction});
}