feat: add an accept button in view invitations page

This commit is contained in:
sBubshait 2025-07-28 11:24:58 +03:00
parent c9316b5190
commit 80a280a4aa
2 changed files with 486 additions and 386 deletions

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import '../../models/invitation_models.dart';
import '../../services/invitations_service.dart';
import '../../services/user_service.dart';
import '../../utils/invitation_utils.dart';
class InvitationDetailsPage extends StatefulWidget {
@ -23,11 +24,14 @@ class _InvitationDetailsPageState extends State<InvitationDetailsPage> {
InvitationDetails? _invitationDetails;
bool _isLoading = true;
bool _isCancelling = false;
bool _isAccepting = false;
bool _isCurrentlyParticipant = false;
String? _errorMessage;
@override
void initState() {
super.initState();
_isCurrentlyParticipant = widget.isParticipant;
_loadInvitationDetails();
}
@ -48,6 +52,11 @@ class _InvitationDetailsPageState extends State<InvitationDetailsPage> {
_errorMessage = result['message'];
}
});
// Update participation status after loading details
if (result['success']) {
await _updateParticipationStatus();
}
}
}
@ -150,6 +159,52 @@ class _InvitationDetailsPageState extends State<InvitationDetailsPage> {
}
}
Future<void> _updateParticipationStatus() async {
if (_invitationDetails == null) return;
final userResult = await UserService.getCurrentUser();
if (userResult['success'] && userResult['data'] != null) {
final currentUserId = userResult['data']['id'];
final isParticipant = _invitationDetails!.attendees.any((attendee) => attendee.id == currentUserId);
setState(() {
_isCurrentlyParticipant = isParticipant;
});
}
}
Future<void> _acceptInvitation() async {
setState(() {
_isAccepting = true;
});
final result = await InvitationsService.acceptInvitation(widget.invitationId);
if (mounted) {
setState(() {
_isAccepting = false;
});
if (result['success']) {
// Reload invitation details to reflect the new state
await _loadInvitationDetails();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Invitation accepted successfully!'),
backgroundColor: Colors.green,
),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(result['message'] ?? 'Failed to accept invitation'),
backgroundColor: Colors.red,
),
);
}
}
}
@override
Widget build(BuildContext context) {
return PopScope(
@ -509,7 +564,45 @@ class _InvitationDetailsPageState extends State<InvitationDetailsPage> {
),
),
],
if (widget.isParticipant) ...[
// Accept button for non-participants who are not owners
if (!_isCurrentlyParticipant && !widget.isOwner) ...[
SizedBox(height: 32),
Container(
width: double.infinity,
height: 56,
child: ElevatedButton(
onPressed: _isAccepting ? null : _acceptInvitation,
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF6A4C93),
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 2,
),
child: _isAccepting
? SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
)
: Text(
'Accept Invitation',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
),
),
],
// Cancel/Leave button for participants
if (_isCurrentlyParticipant) ...[
SizedBox(height: 32),
Container(
width: double.infinity,

View File

@ -49,7 +49,9 @@ class _InvitationsPageState extends State<InvitationsPage>
_isLoading = false;
_errorMessage = null;
});
print('Invitations UI updated with ${updatedInvitationsData.created.length + updatedInvitationsData.accepted.length + updatedInvitationsData.available.length} total invitations');
print(
'Invitations UI updated with ${updatedInvitationsData.created.length + updatedInvitationsData.accepted.length + updatedInvitationsData.available.length} total invitations',
);
}
},
onError: (error) {
@ -69,7 +71,9 @@ class _InvitationsPageState extends State<InvitationsPage>
});
}
final result = await InvitationsService.getAllInvitations(forceRefresh: forceRefresh);
final result = await InvitationsService.getAllInvitations(
forceRefresh: forceRefresh,
);
if (mounted) {
setState(() {
@ -551,7 +555,10 @@ class _InvitationsPageState extends State<InvitationsPage>
),
automaticallyImplyLeading: false,
actions: [
IconButton(icon: Icon(Icons.refresh), onPressed: () => _loadInvitations(forceRefresh: true)),
IconButton(
icon: Icon(Icons.refresh),
onPressed: () => _loadInvitations(forceRefresh: true),
),
],
),
body: _isLoading