169 lines
3.7 KiB
Dart
169 lines
3.7 KiB
Dart
import '../utils/app_config.dart';
|
|
|
|
enum CommandType {
|
|
closeTab('close_tab');
|
|
|
|
final String value;
|
|
|
|
const CommandType(this.value);
|
|
|
|
static CommandType? fromValue(String value) {
|
|
for (final type in CommandType.values) {
|
|
if (type.value == value) return type;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
enum CommandResult { completed, conflict, failed, expired }
|
|
|
|
class RemoteCommand {
|
|
final String id;
|
|
final String rawType;
|
|
final String tabId;
|
|
final int expectedVersion;
|
|
final String paymentMethod;
|
|
final String requestedBy;
|
|
final DateTime createdAt;
|
|
|
|
const RemoteCommand({
|
|
required this.id,
|
|
required this.rawType,
|
|
required this.tabId,
|
|
required this.expectedVersion,
|
|
required this.paymentMethod,
|
|
required this.requestedBy,
|
|
required this.createdAt,
|
|
});
|
|
|
|
factory RemoteCommand.fromJson(Map<String, dynamic> json) {
|
|
return RemoteCommand(
|
|
id: json['id'] as String,
|
|
rawType: json['type'] as String,
|
|
tabId: json['tabId'] as String,
|
|
expectedVersion: json['expectedVersion'] as int,
|
|
paymentMethod: json['paymentMethod'] as String? ?? 'cash',
|
|
requestedBy: json['requestedBy'] as String? ?? '',
|
|
createdAt: DateTime.parse(json['createdAt'] as String),
|
|
);
|
|
}
|
|
|
|
/// Null when the server sends a command this app version doesn't know.
|
|
CommandType? get type => CommandType.fromValue(rawType);
|
|
|
|
bool get isExpired {
|
|
final cutoff = DateTime.now().subtract(
|
|
const Duration(hours: kCommandExpiryHours),
|
|
);
|
|
return createdAt.isBefore(cutoff);
|
|
}
|
|
}
|
|
|
|
class SyncResponse {
|
|
final List<RemoteCommand> commands;
|
|
final String? cursor;
|
|
final List<String> plannedTabNames;
|
|
|
|
const SyncResponse({
|
|
required this.commands,
|
|
this.cursor,
|
|
this.plannedTabNames = const [],
|
|
});
|
|
|
|
factory SyncResponse.fromJson(Map<String, dynamic> json) {
|
|
return SyncResponse(
|
|
commands: [
|
|
for (final command in json['commands'] as List<dynamic>? ?? [])
|
|
RemoteCommand.fromJson(command as Map<String, dynamic>),
|
|
],
|
|
cursor: json['cursor'] as String?,
|
|
plannedTabNames: [
|
|
for (final name in json['plannedTabNames'] as List<dynamic>? ?? [])
|
|
name as String,
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
class SnapshotTab {
|
|
final String id;
|
|
final String customerName;
|
|
final int version;
|
|
final int totalInCents;
|
|
final int itemCount;
|
|
|
|
const SnapshotTab({
|
|
required this.id,
|
|
required this.customerName,
|
|
required this.version,
|
|
required this.totalInCents,
|
|
required this.itemCount,
|
|
});
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
'id': id,
|
|
'customerName': customerName,
|
|
'version': version,
|
|
'totalInCents': totalInCents,
|
|
'itemCount': itemCount,
|
|
};
|
|
}
|
|
|
|
class SyncRequest {
|
|
final String deviceId;
|
|
final String? cursor;
|
|
final List<SnapshotTab> openTabs;
|
|
|
|
const SyncRequest({
|
|
required this.deviceId,
|
|
this.cursor,
|
|
required this.openTabs,
|
|
});
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
'deviceId': deviceId,
|
|
if (cursor != null) 'cursor': cursor,
|
|
'openTabs': openTabs.map((tab) => tab.toJson()).toList(),
|
|
};
|
|
}
|
|
|
|
class CommandAck {
|
|
final String commandId;
|
|
final CommandResult status;
|
|
final String? result;
|
|
|
|
const CommandAck({
|
|
required this.commandId,
|
|
required this.status,
|
|
this.result,
|
|
});
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
'commandId': commandId,
|
|
'status': status.name,
|
|
if (result != null) 'result': result,
|
|
};
|
|
}
|
|
|
|
enum RemoteSyncEventType {
|
|
tabClosedRemotely,
|
|
syncCompleted,
|
|
syncFailed,
|
|
conflict,
|
|
unauthorized,
|
|
}
|
|
|
|
class RemoteSyncEvent {
|
|
final RemoteSyncEventType type;
|
|
final String? tabCustomerName;
|
|
final String? requestedBy;
|
|
final String? message;
|
|
|
|
const RemoteSyncEvent({
|
|
required this.type,
|
|
this.tabCustomerName,
|
|
this.requestedBy,
|
|
this.message,
|
|
});
|
|
}
|