mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-11-27 14:44:56 +00:00
space canvas initial commit
This commit is contained in:
203
lib/pages/spaces_management/view/spaces_management_page.dart
Normal file
203
lib/pages/spaces_management/view/spaces_management_page.dart
Normal file
@ -0,0 +1,203 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/pages/common/buttons/add_space_button.dart';
|
||||
import 'package:syncrow_web/pages/spaces_management/view/dialogs/create_space_dialog.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 = [];
|
||||
|
||||
@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(
|
||||
children: [
|
||||
Center(
|
||||
child: spaces.isEmpty
|
||||
? AddSpaceButton(
|
||||
onTap: () {
|
||||
_showCreateSpaceDialog(screenSize);
|
||||
},
|
||||
)
|
||||
: Stack(
|
||||
children: spaces
|
||||
.asMap()
|
||||
.entries
|
||||
.map((entry) => _buildSpaceCard(entry.key, screenSize))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Function to open the Create Space dialog
|
||||
void _showCreateSpaceDialog(Size screenSize, {Offset? position}) {
|
||||
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
|
||||
);
|
||||
|
||||
spaces.add(SpaceData(name: name, icon: icon, position: centerPosition));
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Function to build a draggable space card
|
||||
Widget _buildSpaceCard(int index, Size screenSize) {
|
||||
return Positioned(
|
||||
left: spaces[index].position.dx,
|
||||
top: spaces[index].position.dy,
|
||||
child: GestureDetector(
|
||||
onPanUpdate: (details) {
|
||||
// Update the position of the space card while dragging
|
||||
setState(() {
|
||||
spaces[index].position += details.delta;
|
||||
});
|
||||
},
|
||||
child: MouseRegion(
|
||||
onEnter: (_) {
|
||||
// Show plus buttons on hover
|
||||
setState(() {
|
||||
spaces[index].isHovered = true;
|
||||
});
|
||||
},
|
||||
onExit: (_) {
|
||||
// Hide plus buttons when not hovered
|
||||
setState(() {
|
||||
spaces[index].isHovered = false;
|
||||
});
|
||||
},
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
_buildSpaceContainer(index),
|
||||
if (spaces[index].isHovered) ...[
|
||||
_buildPlusButton(index, 'left', const Offset(-21, 20), screenSize),
|
||||
_buildPlusButton(index, 'right', const Offset(140, 20), screenSize),
|
||||
_buildPlusButton(index, 'down', const Offset(63, 55), screenSize),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Function to build the space container with the styled format
|
||||
Widget _buildSpaceContainer(int index) {
|
||||
return Container(
|
||||
width: 150,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.5),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 5,
|
||||
offset: const Offset(0, 3),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 40,
|
||||
height: 60,
|
||||
decoration: const BoxDecoration(
|
||||
color: Color(0xFF023DFE),
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(15),
|
||||
bottomLeft: Radius.circular(15),
|
||||
),
|
||||
),
|
||||
child: Center(
|
||||
child: SvgPicture.asset(spaces[index].icon, width: 24, height: 24, color: Colors.white),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
spaces[index].name,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Function to build plus buttons for new space creation
|
||||
Widget _buildPlusButton(int index, String direction, Offset offset, Size screenSize) {
|
||||
return Positioned(
|
||||
left: offset.dx,
|
||||
top: offset.dy,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Offset newPosition;
|
||||
switch (direction) {
|
||||
case 'left':
|
||||
newPosition = spaces[index].position + const Offset(-200, 0);
|
||||
break;
|
||||
case 'right':
|
||||
newPosition = spaces[index].position + const Offset(200, 0);
|
||||
break;
|
||||
case 'down':
|
||||
newPosition = spaces[index].position + const Offset(0, 150);
|
||||
break;
|
||||
default:
|
||||
newPosition = spaces[index].position;
|
||||
}
|
||||
|
||||
_showCreateSpaceDialog(screenSize, position: newPosition);
|
||||
},
|
||||
child: Container(
|
||||
width: 30,
|
||||
height: 30,
|
||||
decoration: const BoxDecoration(
|
||||
color: Color(0xFF023DFE),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(Icons.add, color: Colors.white, size: 20),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 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});
|
||||
}
|
||||
Reference in New Issue
Block a user