feat: transfer table
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import 'package:enaklo_pos/core/components/flushbar.dart';
|
||||
import 'package:enaklo_pos/core/constants/colors.dart';
|
||||
import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
|
||||
import 'package:enaklo_pos/data/models/response/table_model.dart';
|
||||
@@ -5,7 +6,9 @@ import 'package:enaklo_pos/presentation/home/pages/dashboard_page.dart';
|
||||
import 'package:enaklo_pos/presentation/table/blocs/change_position_table/change_position_table_bloc.dart';
|
||||
import 'package:enaklo_pos/presentation/table/blocs/create_table/create_table_bloc.dart';
|
||||
import 'package:enaklo_pos/presentation/table/blocs/get_table/get_table_bloc.dart';
|
||||
import 'package:enaklo_pos/presentation/table/blocs/transfer_table/transfer_table_bloc.dart';
|
||||
import 'package:enaklo_pos/presentation/table/dialogs/form_table_new_dialog.dart';
|
||||
import 'package:enaklo_pos/presentation/table/dialogs/transfer_table_dialog.dart';
|
||||
import 'package:enaklo_pos/presentation/table/widgets/table_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -41,6 +44,8 @@ class _TablePageState extends State<TablePage> {
|
||||
// Untuk drag
|
||||
TableModel? draggingTable;
|
||||
|
||||
Offset? _tapPosition;
|
||||
|
||||
// Ubah function toggleSelectTable menjadi selectTable
|
||||
void selectTable(TableModel table) {
|
||||
if (table.status == 'occupied') return;
|
||||
@@ -112,141 +117,164 @@ class _TablePageState extends State<TablePage> {
|
||||
),
|
||||
),
|
||||
backgroundColor: const Color(0xFFF7F8FA),
|
||||
body: BlocBuilder<GetTableBloc, GetTableState>(
|
||||
builder: (context, state) {
|
||||
return state.maybeWhen(
|
||||
orElse: () => SizedBox.shrink(),
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
success: (tables) => SafeArea(
|
||||
child: Stack(
|
||||
children: [
|
||||
// Main content area
|
||||
Row(
|
||||
children: [
|
||||
// Area meja (zoom & pan & drag)
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: InteractiveViewer(
|
||||
panEnabled: true,
|
||||
scaleEnabled: true,
|
||||
constrained: false,
|
||||
boundaryMargin: const EdgeInsets.all(80),
|
||||
minScale: 0.3,
|
||||
maxScale: 3.0,
|
||||
alignment: Alignment.topLeft,
|
||||
child: Container(
|
||||
width: mapWidth,
|
||||
height: mapHeight,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF7F8FA),
|
||||
border: Border.all(
|
||||
color: Colors.grey[300]!, width: 2),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
// Optional: Grid background
|
||||
...List.generate(
|
||||
20,
|
||||
(i) => Positioned(
|
||||
left: i * 100.0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
width: 1,
|
||||
color: Colors.grey[200]),
|
||||
)),
|
||||
...List.generate(
|
||||
15,
|
||||
(i) => Positioned(
|
||||
top: i * 100.0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
height: 1,
|
||||
color: Colors.grey[200]),
|
||||
)),
|
||||
body: BlocListener<TransferTableBloc, TransferTableState>(
|
||||
listener: (context, state) {
|
||||
state.maybeWhen(
|
||||
orElse: () {},
|
||||
success: () {
|
||||
AppFlushbar.showSuccess(context, 'Transfer Table Success');
|
||||
context.read<GetTableBloc>().add(const GetTableEvent.getTables());
|
||||
},
|
||||
error: (message) {
|
||||
AppFlushbar.showError(context, message);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: BlocBuilder<GetTableBloc, GetTableState>(
|
||||
builder: (context, state) {
|
||||
return state.maybeWhen(
|
||||
orElse: () => SizedBox.shrink(),
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
success: (tables) => SafeArea(
|
||||
child: Stack(
|
||||
children: [
|
||||
// Main content area
|
||||
Row(
|
||||
children: [
|
||||
// Area meja (zoom & pan & drag)
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: InteractiveViewer(
|
||||
panEnabled: true,
|
||||
scaleEnabled: true,
|
||||
constrained: false,
|
||||
boundaryMargin: const EdgeInsets.all(80),
|
||||
minScale: 0.3,
|
||||
maxScale: 3.0,
|
||||
alignment: Alignment.topLeft,
|
||||
child: Container(
|
||||
width: mapWidth,
|
||||
height: mapHeight,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF7F8FA),
|
||||
border: Border.all(
|
||||
color: Colors.grey[300]!, width: 2),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
// Optional: Grid background
|
||||
...List.generate(
|
||||
20,
|
||||
(i) => Positioned(
|
||||
left: i * 100.0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
width: 1,
|
||||
color: Colors.grey[200]),
|
||||
)),
|
||||
...List.generate(
|
||||
15,
|
||||
(i) => Positioned(
|
||||
top: i * 100.0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
height: 1,
|
||||
color: Colors.grey[200]),
|
||||
)),
|
||||
|
||||
// Tables
|
||||
...tables.map((table) {
|
||||
final isSelected = selectedTable == table;
|
||||
return Positioned(
|
||||
left: table.positionX,
|
||||
top: table.positionY,
|
||||
child: Draggable<TableModel>(
|
||||
data: table,
|
||||
feedback: Material(
|
||||
color: Colors.transparent,
|
||||
child: TableWidget(
|
||||
table: table,
|
||||
isSelected: isSelected,
|
||||
// Tables
|
||||
...tables.map((table) {
|
||||
final isSelected = selectedTable == table;
|
||||
return Positioned(
|
||||
left: table.positionX,
|
||||
top: table.positionY,
|
||||
child: Draggable<TableModel>(
|
||||
data: table,
|
||||
feedback: Material(
|
||||
color: Colors.transparent,
|
||||
child: TableWidget(
|
||||
table: table,
|
||||
isSelected: isSelected,
|
||||
),
|
||||
),
|
||||
childWhenDragging: Opacity(
|
||||
opacity: 0.5,
|
||||
child: TableWidget(
|
||||
table: table,
|
||||
isSelected: isSelected,
|
||||
),
|
||||
),
|
||||
onDragStarted: () {
|
||||
setState(() {
|
||||
draggingTable = table;
|
||||
});
|
||||
},
|
||||
onDraggableCanceled:
|
||||
(velocity, offset) {
|
||||
setState(() {
|
||||
draggingTable = null;
|
||||
});
|
||||
},
|
||||
onDragEnd: (details) {
|
||||
setState(() {
|
||||
draggingTable = null;
|
||||
final RenderBox box =
|
||||
context.findRenderObject()
|
||||
as RenderBox;
|
||||
final Offset local = box
|
||||
.globalToLocal(details.offset);
|
||||
table.positionX = local.dx
|
||||
.clamp(0, mapWidth - 120);
|
||||
table.positionY = local.dy
|
||||
.clamp(0, mapHeight - 80);
|
||||
});
|
||||
context
|
||||
.read<ChangePositionTableBloc>()
|
||||
.add(ChangePositionTableEvent
|
||||
.changePositionTable(
|
||||
tableId: table.id ?? "",
|
||||
position: Offset(
|
||||
table.positionX ?? 0.0,
|
||||
table.positionY ?? 0.0,
|
||||
),
|
||||
));
|
||||
},
|
||||
child: GestureDetector(
|
||||
onTap: () => selectTable(table),
|
||||
onTapDown: (details) => _tapPosition =
|
||||
details.globalPosition,
|
||||
onLongPress: () {
|
||||
if (table.status == 'occupied') {
|
||||
_showPopupMenu(context, table);
|
||||
}
|
||||
},
|
||||
child: TableWidget(
|
||||
table: table,
|
||||
isSelected: isSelected,
|
||||
),
|
||||
),
|
||||
),
|
||||
childWhenDragging: Opacity(
|
||||
opacity: 0.5,
|
||||
child: TableWidget(
|
||||
table: table,
|
||||
isSelected: isSelected,
|
||||
),
|
||||
),
|
||||
onDragStarted: () {
|
||||
setState(() {
|
||||
draggingTable = table;
|
||||
});
|
||||
},
|
||||
onDraggableCanceled: (velocity, offset) {
|
||||
setState(() {
|
||||
draggingTable = null;
|
||||
});
|
||||
},
|
||||
onDragEnd: (details) {
|
||||
setState(() {
|
||||
draggingTable = null;
|
||||
final RenderBox box = context
|
||||
.findRenderObject() as RenderBox;
|
||||
final Offset local =
|
||||
box.globalToLocal(details.offset);
|
||||
table.positionX =
|
||||
local.dx.clamp(0, mapWidth - 120);
|
||||
table.positionY =
|
||||
local.dy.clamp(0, mapHeight - 80);
|
||||
});
|
||||
context
|
||||
.read<ChangePositionTableBloc>()
|
||||
.add(ChangePositionTableEvent
|
||||
.changePositionTable(
|
||||
tableId: table.id ?? "",
|
||||
position: Offset(
|
||||
table.positionX ?? 0.0,
|
||||
table.positionY ?? 0.0,
|
||||
),
|
||||
));
|
||||
},
|
||||
child: GestureDetector(
|
||||
onTap: () => selectTable(table),
|
||||
child: TableWidget(
|
||||
table: table,
|
||||
isSelected: isSelected,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Sidebar bar tables
|
||||
],
|
||||
),
|
||||
// Sidebar bar tables
|
||||
],
|
||||
),
|
||||
|
||||
// Floating bottom bar - hanya muncul jika ada table yang dipilih
|
||||
buildAlternativeFloatingBar(),
|
||||
],
|
||||
// Floating bottom bar - hanya muncul jika ada table yang dipilih
|
||||
buildAlternativeFloatingBar(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -366,17 +394,7 @@ class _TablePageState extends State<TablePage> {
|
||||
context.push(DashboardPage(
|
||||
table: selectedTable!,
|
||||
));
|
||||
} else {
|
||||
// Handle occupied table click - load draft order and navigate to payment
|
||||
// context.read<CheckoutBloc>().add(
|
||||
// CheckoutEvent.loadDraftOrder(data!),
|
||||
// );
|
||||
// log("Data Draft Order: ${data!.toMap()}");
|
||||
// context.push(PaymentTablePage(
|
||||
// table: widget.table,
|
||||
// draftOrder: data!,
|
||||
// ));
|
||||
}
|
||||
} else {}
|
||||
},
|
||||
child: const Text(
|
||||
"Tempatkan Pesanan",
|
||||
@@ -401,4 +419,39 @@ class _TablePageState extends State<TablePage> {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _showPopupMenu(BuildContext context, TableModel table) {
|
||||
final RenderBox overlay =
|
||||
Overlay.of(context).context.findRenderObject() as RenderBox;
|
||||
|
||||
showMenu(
|
||||
context: context,
|
||||
position: RelativeRect.fromRect(
|
||||
_tapPosition != null
|
||||
? Rect.fromLTWH(_tapPosition!.dx, _tapPosition!.dy, 0, 0)
|
||||
: Rect.fromLTWH(100, 100, 0, 0),
|
||||
Offset.zero & overlay.size,
|
||||
),
|
||||
color: AppColors.white,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||
elevation: 1,
|
||||
items: [
|
||||
PopupMenuItem(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => TransferTableDialog(fromTable: table),
|
||||
);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.swap_horiz),
|
||||
SizedBox(width: 8),
|
||||
Text('Transfer'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user