feat: creating invites frontend
This commit is contained in:
parent
d2f74d0296
commit
2f7bc9e6c5
@ -11,4 +11,5 @@ class ApiConstants {
|
|||||||
// Invitation endpoints
|
// Invitation endpoints
|
||||||
static const String getAllInvitationsEndpoint = '/invitations/all';
|
static const String getAllInvitationsEndpoint = '/invitations/all';
|
||||||
static const String acceptInvitationEndpoint = '/invitations/accept';
|
static const String acceptInvitationEndpoint = '/invitations/accept';
|
||||||
|
static const String createInvitationEndpoint = '/invitations/create';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -459,11 +459,14 @@ class _InvitationsPageState extends State<InvitationsPage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
Navigator.push(
|
final result = await Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (context) => CreateInvitationPage()),
|
MaterialPageRoute(builder: (context) => CreateInvitationPage()),
|
||||||
);
|
);
|
||||||
|
if (result == true) {
|
||||||
|
_loadInvitations();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
backgroundColor: Color(0xFF6A4C93),
|
backgroundColor: Color(0xFF6A4C93),
|
||||||
child: Icon(Icons.add, color: Colors.white),
|
child: Icon(Icons.add, color: Colors.white),
|
||||||
@ -487,16 +490,17 @@ class _CreateInvitationPageState extends State<CreateInvitationPage> {
|
|||||||
DateTime? _selectedDate;
|
DateTime? _selectedDate;
|
||||||
TimeOfDay? _selectedTime;
|
TimeOfDay? _selectedTime;
|
||||||
int? _selectedTagIndex;
|
int? _selectedTagIndex;
|
||||||
|
bool _isSubmitting = false;
|
||||||
|
|
||||||
final List<Map<String, dynamic>> _availableTags = [
|
final List<Map<String, dynamic>> _availableTags = [
|
||||||
{"name": "Sports", "color_hex": "#FF6B35", "icon_name": "sports_soccer"},
|
{"id": 1, "name": "Sports", "color_hex": "#FF6B35", "icon_name": "sports_soccer"},
|
||||||
{"name": "Food", "color_hex": "#F7931E", "icon_name": "restaurant"},
|
{"id": 2, "name": "Food", "color_hex": "#F7931E", "icon_name": "restaurant"},
|
||||||
{"name": "Gaming", "color_hex": "#FFD23F", "icon_name": "games"},
|
{"id": 3, "name": "Gaming", "color_hex": "#FFD23F", "icon_name": "games"},
|
||||||
{"name": "Study", "color_hex": "#06FFA5", "icon_name": "menu_book"},
|
{"id": 4, "name": "Study", "color_hex": "#06FFA5", "icon_name": "menu_book"},
|
||||||
{"name": "Social", "color_hex": "#118AB2", "icon_name": "group"},
|
{"id": 5, "name": "Social", "color_hex": "#118AB2", "icon_name": "group"},
|
||||||
{"name": "Travel", "color_hex": "#06D6A0", "icon_name": "flight"},
|
{"id": 6, "name": "Travel", "color_hex": "#06D6A0", "icon_name": "flight"},
|
||||||
{"name": "Music", "color_hex": "#8E44AD", "icon_name": "music_note"},
|
{"id": 7, "name": "Music", "color_hex": "#8E44AD", "icon_name": "music_note"},
|
||||||
{"name": "Movies", "color_hex": "#E74C3C", "icon_name": "movie"},
|
{"id": 8, "name": "Movies", "color_hex": "#E74C3C", "icon_name": "movie"},
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -577,7 +581,7 @@ class _CreateInvitationPageState extends State<CreateInvitationPage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleSubmit() {
|
Future<void> _handleSubmit() async {
|
||||||
if (_formKey.currentState!.validate()) {
|
if (_formKey.currentState!.validate()) {
|
||||||
if (_selectedTagIndex == null) {
|
if (_selectedTagIndex == null) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
@ -589,28 +593,54 @@ class _CreateInvitationPageState extends State<CreateInvitationPage> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_isSubmitting = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
DateTime? combinedDateTime;
|
||||||
|
if (_selectedDate != null) {
|
||||||
|
if (_selectedTime != null) {
|
||||||
|
combinedDateTime = DateTime(
|
||||||
|
_selectedDate!.year,
|
||||||
|
_selectedDate!.month,
|
||||||
|
_selectedDate!.day,
|
||||||
|
_selectedTime!.hour,
|
||||||
|
_selectedTime!.minute,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
combinedDateTime = _selectedDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final invitationData = {
|
final invitationData = {
|
||||||
"title": _titleController.text.trim(),
|
"title": _titleController.text.trim(),
|
||||||
"description": _descriptionController.text.trim(),
|
"description": _descriptionController.text.trim(),
|
||||||
"date": _selectedDate?.toIso8601String(),
|
"dateTime": combinedDateTime?.toIso8601String(),
|
||||||
"time": _selectedTime != null
|
|
||||||
? "${_selectedTime!.hour}:${_selectedTime!.minute.toString().padLeft(2, '0')}"
|
|
||||||
: null,
|
|
||||||
"location": _locationController.text.trim().isEmpty
|
"location": _locationController.text.trim().isEmpty
|
||||||
? null
|
? null
|
||||||
: _locationController.text.trim(),
|
: _locationController.text.trim(),
|
||||||
"max_participants": int.parse(_maxParticipantsController.text),
|
"maxParticipants": int.parse(_maxParticipantsController.text),
|
||||||
"tag": _availableTags[_selectedTagIndex!],
|
"tagId": _availableTags[_selectedTagIndex!]["id"],
|
||||||
};
|
};
|
||||||
|
|
||||||
print("Invitation JSON: $invitationData");
|
final result = await InvitationsService.createInvitation(invitationData);
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
if (mounted) {
|
||||||
SnackBar(
|
setState(() {
|
||||||
content: Text('Invitation created! Check console for JSON output.'),
|
_isSubmitting = false;
|
||||||
backgroundColor: Color(0xFF6A4C93),
|
});
|
||||||
),
|
|
||||||
);
|
if (result['success']) {
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
} else {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(result['message'] ?? 'Failed to create invitation'),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -932,7 +962,7 @@ class _CreateInvitationPageState extends State<CreateInvitationPage> {
|
|||||||
Container(
|
Container(
|
||||||
height: 56,
|
height: 56,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: _handleSubmit,
|
onPressed: _isSubmitting ? null : _handleSubmit,
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Color(0xFF6A4C93),
|
backgroundColor: Color(0xFF6A4C93),
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
@ -941,13 +971,22 @@ class _CreateInvitationPageState extends State<CreateInvitationPage> {
|
|||||||
),
|
),
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: _isSubmitting
|
||||||
'Create Invitation',
|
? SizedBox(
|
||||||
style: TextStyle(
|
height: 20,
|
||||||
fontSize: 18,
|
width: 20,
|
||||||
fontWeight: FontWeight.w600,
|
child: CircularProgressIndicator(
|
||||||
),
|
strokeWidth: 2,
|
||||||
),
|
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
'Create Invitation',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -85,4 +85,50 @@ class InvitationsService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<Map<String, dynamic>> createInvitation(Map<String, dynamic> invitationData) async {
|
||||||
|
try {
|
||||||
|
final response = await HttpService.post(
|
||||||
|
ApiConstants.createInvitationEndpoint,
|
||||||
|
invitationData,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final responseData = jsonDecode(response.body);
|
||||||
|
if (responseData['status'] == true) {
|
||||||
|
return {
|
||||||
|
'success': true,
|
||||||
|
'data': responseData['data'],
|
||||||
|
'message': responseData['message'],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'success': false,
|
||||||
|
'message': responseData['message'] ?? 'Failed to create invitation',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else if (response.statusCode == 401) {
|
||||||
|
return {
|
||||||
|
'success': false,
|
||||||
|
'message': 'Session expired. Please login again.',
|
||||||
|
};
|
||||||
|
} else if (response.statusCode == 403) {
|
||||||
|
return {
|
||||||
|
'success': false,
|
||||||
|
'message': 'Access denied. Invalid credentials.',
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'success': false,
|
||||||
|
'message': 'Server error (${response.statusCode})',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Error creating invitation: $e');
|
||||||
|
return {
|
||||||
|
'success': false,
|
||||||
|
'message': 'Network error. Please check your connection.',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user