Announcements
List
GET /parent/announcement/get-announcement?studentId={id}
{
"data": {
"announcements": [
{
"id": "uuid",
"title": "Mid-Term Exam Schedule Released",
"body": "The mid-term exam schedule has been published...",
"priority": "NORMAL",
"createdAt": "2024-04-01T10:00:00Z",
"attachments": [
{ "name": "schedule.pdf", "url": "https://cdn.syncad.in/..." }
]
}
]
}
}
Priority Indicator
| Priority | Visual |
|---|---|
NORMAL | Standard card |
URGENT | Red accent border + "URGENT" badge |
Push Notifications
Announcements trigger FCM push notifications:
// FCM listener in main.dart
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
if (message.data['type'] == 'ANNOUNCEMENT') {
// Show in-app banner or navigate to announcement detail
EventBus.instance.emit('NEW_ANNOUNCEMENT', message.data);
}
});
// Background handler
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
UI — Announcement Card
class AnnouncementCard extends StatelessWidget {
final Announcement announcement;
@override
Widget build(BuildContext context) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
side: announcement.priority == 'URGENT'
? const BorderSide(color: Colors.red, width: 2)
: BorderSide.none,
),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(child: Text(announcement.title, style: const TextStyle(fontWeight: FontWeight.bold))),
if (announcement.priority == 'URGENT')
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
decoration: BoxDecoration(color: Colors.red, borderRadius: BorderRadius.circular(4)),
child: const Text('URGENT', style: TextStyle(color: Colors.white, fontSize: 10)),
),
],
),
const SizedBox(height: 8),
Text(announcement.body),
if (announcement.attachments.isNotEmpty) ...[
const SizedBox(height: 8),
...announcement.attachments.map((a) => TextButton.icon(
onPressed: () => launchUrl(Uri.parse(a.url)),
icon: const Icon(Icons.attachment, size: 16),
label: Text(a.name),
)),
],
const SizedBox(height: 8),
Text(
_formatDate(announcement.createdAt),
style: const TextStyle(color: Colors.grey, fontSize: 12),
),
],
),
),
);
}
}