import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/common/buttons/add_space_button.dart'; import 'package:syncrow_web/pages/spaces_management/bloc/space_management_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/bloc/space_management_event.dart'; import 'package:syncrow_web/pages/spaces_management/bloc/space_management_state.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/community_list_view.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/widgets/gradient_canvas_border_widget.dart'; import 'package:syncrow_web/pages/spaces_management/widgets/sidebar_widget.dart'; import 'package:syncrow_web/pages/spaces_management/widgets/space_card_widget.dart'; import 'package:syncrow_web/pages/spaces_management/widgets/space_container_widget.dart'; import 'package:syncrow_web/services/space_mana_api.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/web_layout/web_scaffold.dart'; class SpaceManagementPage extends StatefulWidget { const SpaceManagementPage({super.key}); @override SpaceManagementPageState createState() => SpaceManagementPageState(); } class SpaceManagementPageState extends State { // Store created spaces List spaces = []; List connections = []; // Track whether to show the community list view or community structure bool showCommunityStructure = false; // Selected community CommunityModel? selectedCommunity; // API instance final CommunitySpaceManagementApi _api = CommunitySpaceManagementApi(); // Data structure to store community and associated spaces Map> communitySpaces = {}; @override void initState() { super.initState(); } @override Widget build(BuildContext context) { Size screenSize = MediaQuery.of(context).size; return BlocProvider( create: (context) => SpaceManagementBloc(CommunitySpaceManagementApi()) ..add(LoadCommunityAndSpacesEvent()), child: WebScaffold( appBarTitle: Text( 'Space Management', style: Theme.of(context).textTheme.headlineLarge, ), enableMenuSideba: false, scaffoldBody: BlocBuilder( builder: (context, state) { if (state is SpaceManagementLoading) { return const Center(child: CircularProgressIndicator()); } else if (state is SpaceManagementLoaded) { return _buildLoadedState(context, screenSize, state.communities); } else if (state is SpaceManagementError) { return Center(child: Text('Error: ${state.errorMessage}')); } return Container(); }, ), ), ); } Widget _buildLoadedState( BuildContext context, Size screenSize, List communities) { return Stack( clipBehavior: Clip.none, children: [ Row( children: [ SidebarWidget( communities: communities, onCommunitySelected: (community) {}, ), showCommunityStructure ? _buildCommunityStructureArea(context, screenSize) : CommunityListViewWidget( communities: communities, onCommunitySelected: (community) { setState(() { selectedCommunity = community; showCommunityStructure = true; }); }, ), ], ), const GradientCanvasBorderWidget() ], ); } Widget _buildCommunityStructureArea(BuildContext context, Size screenSize) { return 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: const Offset(0, 4), // Shadow only on the bottom ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Community Structure', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), if (selectedCommunity != null) ...[ Text( selectedCommunity!.name, // Show community name style: const TextStyle( fontSize: 16, color: ColorsManager.blackColor, // Slightly muted color ), ), ] ], ), ), // Use Expanded to ensure InteractiveViewer takes the available space Flexible( 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( color: ColorsManager .transparentColor, // Transparent background child: spaces.isEmpty ? Center( child: AddSpaceButton( onTap: () { _showCreateSpaceDialog(screenSize); }, ), ) : Stack( clipBehavior: Clip.none, children: [ CustomPaint( size: const Size(4000, 4000), painter: CurvedLinePainter(connections), ), ...spaces.asMap().entries.map((entry) { final space = entry.value; return Positioned( left: space.position.dx, top: space.position.dy, child: SpaceCardWidget( index: entry.key, screenSize: screenSize, position: space.position, isHovered: space.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, ); }, ), ); }), ], )), ), ), ], ), ), ); } 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, )); } }); }, ); }, ); } } // Function to open the Create Space dialog // 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}); }