mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
push dragging
This commit is contained in:
@ -1,13 +1,22 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
part 'routine_event.dart';
|
||||
part 'routine_state.dart';
|
||||
|
||||
class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
|
||||
RoutineBloc() : super(RoutineInitial()) {
|
||||
on<RoutineEvent>((event, emit) {
|
||||
// TODO: implement event handler
|
||||
});
|
||||
RoutineBloc() : super(const RoutineState()) {
|
||||
on<AddToIfContainer>(_onAddToIfContainer);
|
||||
on<AddToThenContainer>(_onAddToThenContainer);
|
||||
}
|
||||
|
||||
void _onAddToIfContainer(AddToIfContainer event, Emitter<RoutineState> emit) {
|
||||
final updatedIfItems = List<Map<String, String>>.from(state.ifItems)..add(event.item);
|
||||
emit(state.copyWith(ifItems: updatedIfItems));
|
||||
}
|
||||
|
||||
void _onAddToThenContainer(AddToThenContainer event, Emitter<RoutineState> emit) {
|
||||
final updatedThenItems = List<Map<String, String>>.from(state.thenItems)..add(event.item);
|
||||
emit(state.copyWith(thenItems: updatedThenItems));
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,26 @@
|
||||
part of 'routine_bloc.dart';
|
||||
|
||||
@immutable
|
||||
sealed class RoutineEvent {}
|
||||
abstract class RoutineEvent extends Equatable {
|
||||
const RoutineEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class AddToIfContainer extends RoutineEvent {
|
||||
final Map<String, String> item;
|
||||
|
||||
const AddToIfContainer(this.item);
|
||||
|
||||
@override
|
||||
List<Object> get props => [item];
|
||||
}
|
||||
|
||||
class AddToThenContainer extends RoutineEvent {
|
||||
final Map<String, String> item;
|
||||
|
||||
const AddToThenContainer(this.item);
|
||||
|
||||
@override
|
||||
List<Object> get props => [item];
|
||||
}
|
||||
|
@ -1,6 +1,24 @@
|
||||
part of 'routine_bloc.dart';
|
||||
|
||||
@immutable
|
||||
sealed class RoutineState {}
|
||||
class RoutineState extends Equatable {
|
||||
final List<Map<String, String>> ifItems;
|
||||
final List<Map<String, String>> thenItems;
|
||||
|
||||
final class RoutineInitial extends RoutineState {}
|
||||
const RoutineState({
|
||||
this.ifItems = const [],
|
||||
this.thenItems = const [],
|
||||
});
|
||||
|
||||
RoutineState copyWith({
|
||||
List<Map<String, String>>? ifItems,
|
||||
List<Map<String, String>>? thenItems,
|
||||
}) {
|
||||
return RoutineState(
|
||||
ifItems: ifItems ?? this.ifItems,
|
||||
thenItems: thenItems ?? this.thenItems,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object> get props => [ifItems, thenItems];
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/conditions_routines_devices_view.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/if_container.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/routine_search_and_buttons.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/then_container.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class CreateNewRoutineView extends StatelessWidget {
|
||||
@ -8,74 +12,82 @@ class CreateNewRoutineView extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
alignment: Alignment.topLeft,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const RoutineSearchAndButtons(),
|
||||
const SizedBox(height: 20),
|
||||
Flexible(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Card(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.whiteColors,
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
),
|
||||
child: const ConditionsRoutinesDevicesView()),
|
||||
return BlocProvider(
|
||||
create: (context) => RoutineBloc(),
|
||||
child: Container(
|
||||
alignment: Alignment.topLeft,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const RoutineSearchAndButtons(),
|
||||
const SizedBox(height: 20),
|
||||
Flexible(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Card(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: ColorsManager.whiteColors,
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
),
|
||||
child: const ConditionsRoutinesDevicesView()),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Card(
|
||||
margin: EdgeInsets.zero,
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: ColorsManager.whiteColors,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(15),
|
||||
topRight: Radius.circular(15),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
/// IF Container
|
||||
Expanded(
|
||||
child: Card(
|
||||
margin: EdgeInsets.zero,
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: ColorsManager.whiteColors,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(15),
|
||||
topRight: Radius.circular(15),
|
||||
),
|
||||
),
|
||||
child: const IfContainer(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 2,
|
||||
width: double.infinity,
|
||||
color: ColorsManager.dialogBlueTitle,
|
||||
),
|
||||
Expanded(
|
||||
child: Card(
|
||||
margin: EdgeInsets.zero,
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: ColorsManager.boxColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(15),
|
||||
bottomRight: Radius.circular(15),
|
||||
Container(
|
||||
height: 2,
|
||||
width: double.infinity,
|
||||
color: ColorsManager.dialogBlueTitle,
|
||||
),
|
||||
|
||||
/// THEN Container
|
||||
Expanded(
|
||||
child: Card(
|
||||
margin: EdgeInsets.zero,
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: ColorsManager.boxColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(15),
|
||||
bottomRight: Radius.circular(15),
|
||||
),
|
||||
),
|
||||
child: const ThenContainer(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -9,14 +9,28 @@ class DraggableCard extends StatelessWidget {
|
||||
required this.imagePath,
|
||||
required this.title,
|
||||
this.titleColor,
|
||||
this.isDragged = false,
|
||||
});
|
||||
|
||||
final String imagePath;
|
||||
final String title;
|
||||
final Color? titleColor;
|
||||
final bool isDragged;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Draggable<Map<String, String>>(
|
||||
data: {'key': UniqueKey().toString(), 'imagePath': imagePath, 'title': title},
|
||||
feedback: Transform.rotate(
|
||||
angle: -0.1,
|
||||
child: _buildCardContent(context),
|
||||
),
|
||||
childWhenDragging: _buildGreyContainer(),
|
||||
child: isDragged ? _buildGreyContainer() : _buildCardContent(context),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCardContent(BuildContext context) {
|
||||
return Card(
|
||||
color: ColorsManager.whiteColors,
|
||||
child: SizedBox(
|
||||
@ -60,4 +74,15 @@ class DraggableCard extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildGreyContainer() {
|
||||
return Container(
|
||||
height: 123,
|
||||
width: 90,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[100],
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
47
lib/pages/routiens/widgets/if_container.dart
Normal file
47
lib/pages/routiens/widgets/if_container.dart
Normal file
@ -0,0 +1,47 @@
|
||||
// lib/pages/routiens/widgets/if_container.dart
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart';
|
||||
|
||||
class IfContainer extends StatelessWidget {
|
||||
const IfContainer({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||
builder: (context, state) {
|
||||
return DragTarget<Map<String, String>>(
|
||||
builder: (context, candidateData, rejectedData) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text('IF', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 16),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: state.ifItems
|
||||
.map((item) => DraggableCard(
|
||||
key: Key(item['key']!),
|
||||
imagePath: item['imagePath']!,
|
||||
title: item['title']!,
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
onAccept: (data) {
|
||||
context.read<RoutineBloc>().add(AddToIfContainer(data));
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
47
lib/pages/routiens/widgets/then_container.dart
Normal file
47
lib/pages/routiens/widgets/then_container.dart
Normal file
@ -0,0 +1,47 @@
|
||||
// lib/pages/routiens/widgets/then_container.dart
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart';
|
||||
|
||||
class ThenContainer extends StatelessWidget {
|
||||
const ThenContainer({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||
builder: (context, state) {
|
||||
return DragTarget<Map<String, String>>(
|
||||
builder: (context, candidateData, rejectedData) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text('THEN', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 16),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: state.thenItems
|
||||
.map((item) => DraggableCard(
|
||||
key: Key(item['key']!),
|
||||
imagePath: item['imagePath']!,
|
||||
title: item['title']!,
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
onAccept: (data) {
|
||||
context.read<RoutineBloc>().add(AddToThenContainer(data));
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user