Validate stale chat requests, show info instead of auto-dismiss
- Add validateIncomingRequest() — checks session status with backend - Home screen validates before showing sheet (on resume + listener) - IncomingRequestSheet shows "cancelled/accepted by other" message instead of silently dismissing when request becomes stale Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -130,6 +130,22 @@ class ChatRequest extends _$ChatRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the current incoming request is still valid (pending_acceptance).
|
||||||
|
/// If stale, reset to listening state.
|
||||||
|
Future<void> validateIncomingRequest() async {
|
||||||
|
if (state is! ChatRequestIncomingData) return;
|
||||||
|
final sessionId = (state as ChatRequestIncomingData).sessionId;
|
||||||
|
try {
|
||||||
|
final response = await _apiClient.get('/api/shared/chat/$sessionId/info');
|
||||||
|
final status = response['data']?['status'] as String?;
|
||||||
|
if (status != 'pending_acceptance') {
|
||||||
|
state = const ChatRequestListeningData();
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
state = const ChatRequestListeningData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> accept(String sessionId) async {
|
Future<void> accept(String sessionId) async {
|
||||||
state = const ChatRequestAcceptingData();
|
state = const ChatRequestAcceptingData();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -8,6 +8,18 @@ class IncomingRequestSheet extends ConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final requestState = ref.watch(chatRequestProvider);
|
||||||
|
|
||||||
|
// Request is still active — show accept/decline
|
||||||
|
if (requestState is ChatRequestIncomingData) {
|
||||||
|
return _buildActiveRequest(context, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request was taken by another mitra or cancelled — show info
|
||||||
|
return _buildStaleRequest(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildActiveRequest(BuildContext context, WidgetRef ref) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -52,4 +64,35 @@ class IncomingRequestSheet extends ConsumerWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildStaleRequest(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(24),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.info_outline, size: 48, color: Colors.orange),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
const Text(
|
||||||
|
'Permintaan tidak tersedia',
|
||||||
|
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
const Text(
|
||||||
|
'Permintaan ini sudah dibatalkan oleh customer atau diterima oleh Bestie lain.',
|
||||||
|
style: TextStyle(fontSize: 14, color: Colors.grey),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,13 @@ class _HomeScreenState extends ConsumerState<HomeScreen> with WidgetsBindingObse
|
|||||||
if (state == AppLifecycleState.resumed) {
|
if (state == AppLifecycleState.resumed) {
|
||||||
final chatState = ref.read(chatRequestProvider);
|
final chatState = ref.read(chatRequestProvider);
|
||||||
if (chatState is ChatRequestIncomingData) {
|
if (chatState is ChatRequestIncomingData) {
|
||||||
_showIncomingRequest(chatState.sessionId);
|
// Validate the request is still pending before showing
|
||||||
|
ref.read(chatRequestProvider.notifier).validateIncomingRequest().then((_) {
|
||||||
|
final current = ref.read(chatRequestProvider);
|
||||||
|
if (current is ChatRequestIncomingData) {
|
||||||
|
_showIncomingRequest(current.sessionId);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +71,13 @@ class _HomeScreenState extends ConsumerState<HomeScreen> with WidgetsBindingObse
|
|||||||
// Listen for incoming chat requests
|
// Listen for incoming chat requests
|
||||||
ref.listen(chatRequestProvider, (prev, next) {
|
ref.listen(chatRequestProvider, (prev, next) {
|
||||||
if (next is ChatRequestIncomingData) {
|
if (next is ChatRequestIncomingData) {
|
||||||
_showIncomingRequest(next.sessionId);
|
// Validate request is still pending before showing sheet
|
||||||
|
ref.read(chatRequestProvider.notifier).validateIncomingRequest().then((_) {
|
||||||
|
final current = ref.read(chatRequestProvider);
|
||||||
|
if (current is ChatRequestIncomingData) {
|
||||||
|
_showIncomingRequest(current.sessionId);
|
||||||
|
}
|
||||||
|
});
|
||||||
} else if (next is ChatRequestAcceptedData) {
|
} else if (next is ChatRequestAcceptedData) {
|
||||||
final session = next.session;
|
final session = next.session;
|
||||||
final sessionId = session['session_id'] as String? ?? session['id'] as String;
|
final sessionId = session['session_id'] as String? ?? session['id'] as String;
|
||||||
|
|||||||
Reference in New Issue
Block a user