157 lines
4.2 KiB
Dart
157 lines
4.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import 'package:pshared/models/payment/status.dart';
|
|
|
|
import 'package:pweb/generated/i18n/app_localizations.dart';
|
|
|
|
|
|
class StatusView {
|
|
final String label;
|
|
final Color backgroundColor;
|
|
final Color foregroundColor;
|
|
|
|
StatusView({
|
|
required this.label,
|
|
required this.backgroundColor,
|
|
Color? foregroundColor,
|
|
}) : foregroundColor =
|
|
foregroundColor ??
|
|
(backgroundColor.computeLuminance() > 0.5
|
|
? Colors.black
|
|
: Colors.white);
|
|
|
|
Color get color => backgroundColor;
|
|
}
|
|
|
|
StatusView operationStatusView(
|
|
AppLocalizations l10n,
|
|
ColorScheme scheme,
|
|
OperationStatus status,
|
|
) {
|
|
return operationStatusViewFromToken(
|
|
l10n,
|
|
scheme,
|
|
operationStatusTokenFromEnum(status),
|
|
);
|
|
}
|
|
|
|
StatusView operationStatusViewFromToken(
|
|
AppLocalizations l10n,
|
|
ColorScheme scheme,
|
|
String? rawState, {
|
|
String? fallbackLabel,
|
|
}) {
|
|
final token = normalizeOperationStatusToken(rawState);
|
|
switch (token) {
|
|
case 'success':
|
|
case 'succeeded':
|
|
case 'completed':
|
|
case 'confirmed':
|
|
case 'settled':
|
|
return StatusView(
|
|
label: l10n.operationStatusSuccessful,
|
|
backgroundColor: scheme.tertiaryContainer,
|
|
foregroundColor: scheme.onTertiaryContainer,
|
|
);
|
|
case 'skipped':
|
|
return StatusView(
|
|
label: l10n.operationStepStateSkipped,
|
|
backgroundColor: scheme.secondaryContainer,
|
|
foregroundColor: scheme.onSecondaryContainer,
|
|
);
|
|
case 'error':
|
|
case 'failed':
|
|
case 'rejected':
|
|
case 'aborted':
|
|
return StatusView(
|
|
label: l10n.operationStatusUnsuccessful,
|
|
backgroundColor: scheme.errorContainer,
|
|
foregroundColor: scheme.onErrorContainer,
|
|
);
|
|
case 'cancelled':
|
|
case 'canceled':
|
|
return StatusView(
|
|
label: l10n.paymentStatusCancelled,
|
|
backgroundColor: scheme.surfaceContainerHighest,
|
|
foregroundColor: scheme.onSurfaceVariant,
|
|
);
|
|
case 'processing':
|
|
case 'running':
|
|
case 'executing':
|
|
case 'in_progress':
|
|
case 'started':
|
|
return StatusView(
|
|
label: l10n.paymentStatusProcessing,
|
|
backgroundColor: scheme.primaryContainer,
|
|
foregroundColor: scheme.onPrimaryContainer,
|
|
);
|
|
case 'pending':
|
|
case 'queued':
|
|
case 'waiting':
|
|
case 'created':
|
|
case 'scheduled':
|
|
return StatusView(
|
|
label: l10n.operationStatusPending,
|
|
backgroundColor: scheme.secondary,
|
|
foregroundColor: scheme.onSecondary,
|
|
);
|
|
case 'needs_attention':
|
|
return StatusView(
|
|
label: l10n.operationStepStateNeedsAttention,
|
|
backgroundColor: scheme.tertiary,
|
|
foregroundColor: scheme.onTertiary,
|
|
);
|
|
case 'retrying':
|
|
return StatusView(
|
|
label: l10n.operationStepStateRetrying,
|
|
backgroundColor: scheme.primary,
|
|
foregroundColor: scheme.onPrimary,
|
|
);
|
|
default:
|
|
return StatusView(
|
|
label: fallbackLabel ?? humanizeOperationStatusToken(token),
|
|
backgroundColor: scheme.surfaceContainerHighest,
|
|
foregroundColor: scheme.onSurfaceVariant,
|
|
);
|
|
}
|
|
}
|
|
|
|
String operationStatusTokenFromEnum(OperationStatus status) {
|
|
switch (status) {
|
|
case OperationStatus.pending:
|
|
return 'pending';
|
|
case OperationStatus.processing:
|
|
return 'processing';
|
|
case OperationStatus.retrying:
|
|
return 'retrying';
|
|
case OperationStatus.success:
|
|
return 'success';
|
|
case OperationStatus.skipped:
|
|
return 'skipped';
|
|
case OperationStatus.cancelled:
|
|
return 'cancelled';
|
|
case OperationStatus.needsAttention:
|
|
return 'needs_attention';
|
|
case OperationStatus.error:
|
|
return 'error';
|
|
}
|
|
}
|
|
|
|
String normalizeOperationStatusToken(String? state) {
|
|
final normalized = (state ?? '').trim().toLowerCase();
|
|
if (normalized.isEmpty) return 'pending';
|
|
return normalized
|
|
.replaceFirst(RegExp(r'^step_execution_state_'), '')
|
|
.replaceFirst(RegExp(r'^orchestration_state_'), '');
|
|
}
|
|
|
|
String humanizeOperationStatusToken(String token) {
|
|
final parts = token.split('_').where((part) => part.isNotEmpty).toList();
|
|
if (parts.isEmpty) return token;
|
|
return parts
|
|
.map(
|
|
(part) => '${part[0].toUpperCase()}${part.substring(1).toLowerCase()}',
|
|
)
|
|
.join(' ');
|
|
}
|