space model creation

This commit is contained in:
hannathkadher
2025-01-07 17:34:38 +04:00
parent e7e0149b3a
commit 1228e5e737
13 changed files with 110 additions and 41 deletions

View File

@ -0,0 +1,85 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_event.dart';
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_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/models/subspace_template_model.dart';
import 'package:syncrow_web/utils/constants/action_enum.dart';
class SubSpaceModelBloc extends Bloc<SubSpaceModelEvent, SubSpaceModelState> {
SubSpaceModelBloc() : super(SubSpaceModelState([], [], '')) {
// Handle AddSubSpaceModel Event
on<AddSubSpaceModel>((event, emit) {
// Check for duplicate names (case-insensitive)
final existingNames =
state.subSpaces.map((e) => e.subspaceName.toLowerCase()).toSet();
if (existingNames.contains(event.subSpace.subspaceName.toLowerCase())) {
// Emit state with an error message if duplicate name exists
emit(SubSpaceModelState(
state.subSpaces,
state.updatedSubSpaceModels,
'Subspace name already exists.',
));
} else {
// Add subspace if no duplicate exists
final updatedSubSpaces =
List<SubspaceTemplateModel>.from(state.subSpaces)
..add(event.subSpace);
emit(SubSpaceModelState(
updatedSubSpaces,
state.updatedSubSpaceModels,
'', // Clear error message
));
}
});
// Handle RemoveSubSpaceModel Event
on<RemoveSubSpaceModel>((event, emit) {
final updatedSubSpaces = List<SubspaceTemplateModel>.from(state.subSpaces)
..remove(event.subSpace);
final updatedSubspaceModels = List<UpdateSubspaceTemplateModel>.from(
state.updatedSubSpaceModels,
);
if (event.subSpace.uuid?.isNotEmpty ?? false) {
updatedSubspaceModels.add(UpdateSubspaceTemplateModel(
action: Action.delete,
uuid: event.subSpace.uuid!,
));
}
emit(SubSpaceModelState(
updatedSubSpaces,
updatedSubspaceModels,
'', // Clear error message
));
});
// Handle UpdateSubSpaceModel Event
on<UpdateSubSpaceModel>((event, emit) {
final updatedSubSpaces = state.subSpaces.map((subSpace) {
if (subSpace.uuid == event.updatedSubSpace.uuid) {
return event.updatedSubSpace;
}
return subSpace;
}).toList();
final updatedSubspaceModels = List<UpdateSubspaceTemplateModel>.from(
state.updatedSubSpaceModels,
);
updatedSubspaceModels.add(UpdateSubspaceTemplateModel(
action: Action.update,
uuid: event.updatedSubSpace.uuid!,
));
emit(SubSpaceModelState(
updatedSubSpaces,
updatedSubspaceModels,
'', // Clear error message
));
});
}
}

View File

@ -0,0 +1,18 @@
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
abstract class SubSpaceModelEvent {}
class AddSubSpaceModel extends SubSpaceModelEvent {
final SubspaceTemplateModel subSpace;
AddSubSpaceModel(this.subSpace);
}
class RemoveSubSpaceModel extends SubSpaceModelEvent {
final SubspaceTemplateModel subSpace;
RemoveSubSpaceModel(this.subSpace);
}
class UpdateSubSpaceModel extends SubSpaceModelEvent {
final SubspaceTemplateModel updatedSubSpace;
UpdateSubSpaceModel(this.updatedSubSpace);
}

View File

@ -0,0 +1,26 @@
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
class SubSpaceModelState {
final List<SubspaceTemplateModel> subSpaces;
final List<UpdateSubspaceTemplateModel> updatedSubSpaceModels;
final String errorMessage;
SubSpaceModelState(
this.subSpaces,
this.updatedSubSpaceModels,
this.errorMessage,
);
SubSpaceModelState copyWith({
List<SubspaceTemplateModel>? subSpaces,
List<UpdateSubspaceTemplateModel>? updatedSubSpaceModels,
String? errorMessage,
}) {
return SubSpaceModelState(
subSpaces ?? this.subSpaces,
updatedSubSpaceModels ?? this.updatedSubSpaceModels,
errorMessage ?? this.errorMessage,
);
}
}

View File

@ -0,0 +1,188 @@
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/create_subspace_model/bloc/subspace_model_bloc.dart';
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_event.dart';
import 'package:syncrow_web/pages/spaces_management/create_subspace_model/bloc/subspace_model_state.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_template_model.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class CreateSubSpaceModelDialog extends StatelessWidget {
final bool isEdit;
final String dialogTitle;
final List<SubspaceTemplateModel>? existingSubSpaces;
const CreateSubSpaceModelDialog({
Key? key,
required this.isEdit,
required this.dialogTitle,
this.existingSubSpaces,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
final textController = TextEditingController();
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: BlocProvider(
create: (_) {
final bloc = SubSpaceModelBloc();
if (existingSubSpaces != null) {
for (var subSpace in existingSubSpaces!) {
bloc.add(AddSubSpaceModel(subSpace));
}
}
return bloc;
},
child: BlocBuilder<SubSpaceModelBloc, SubSpaceModelState>(
builder: (context, state) {
return Container(
color: ColorsManager.whiteColors,
child: SizedBox(
width: screenWidth * 0.35,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
dialogTitle,
style: Theme.of(context)
.textTheme
.headlineLarge
?.copyWith(color: ColorsManager.blackColor),
),
const SizedBox(height: 16),
Container(
width: screenWidth * 0.35,
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 16.0),
decoration: BoxDecoration(
color: ColorsManager.boxColor,
borderRadius: BorderRadius.circular(10),
),
child: Wrap(
spacing: 8.0,
runSpacing: 8.0,
children: [
...state.subSpaces.map(
(subSpace) => Chip(
label: Text(
subSpace.subspaceName,
style: const TextStyle(
color: ColorsManager.spaceColor),
),
backgroundColor: ColorsManager.whiteColors,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: const BorderSide(
color: ColorsManager.transparentColor,
width: 0,
),
),
deleteIcon: Container(
width: 24,
height: 24,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: ColorsManager.lightGrayColor,
width: 1.5,
),
),
child: const Icon(
Icons.close,
size: 16,
color: ColorsManager.lightGrayColor,
),
),
onDeleted: () => context
.read<SubSpaceModelBloc>()
.add(RemoveSubSpaceModel(subSpace)),
),
),
SizedBox(
width: 200,
child: TextField(
controller: textController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: state.subSpaces.isEmpty
? 'Please enter the name'
: null,
hintStyle: const TextStyle(
color: ColorsManager.lightGrayColor),
),
onSubmitted: (value) {
if (value.trim().isNotEmpty) {
context.read<SubSpaceModelBloc>().add(
AddSubSpaceModel(
SubspaceTemplateModel(
subspaceName: value.trim(),
disabled: false)));
textController.clear();
}
},
style: const TextStyle(
color: ColorsManager.blackColor),
),
),
if (state.errorMessage.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
state.errorMessage,
style: const TextStyle(
color: ColorsManager.warningRed,
fontSize: 12,
),
),
),
],
),
),
const SizedBox(height: 16),
Row(
children: [
Expanded(
child: CancelButton(
label: 'Cancel',
onPressed: () {
Navigator.of(context).pop();
},
),
),
const SizedBox(width: 10),
Expanded(
child: DefaultButton(
onPressed: () {
final subSpaces = context
.read<SubSpaceModelBloc>()
.state
.subSpaces;
Navigator.of(context).pop(subSpaces);
},
backgroundColor: ColorsManager.secondaryColor,
borderRadius: 10,
foregroundColor: ColorsManager.whiteColors,
child: const Text('OK'),
),
),
],
),
],
),
),
));
},
),
),
);
}
}