feat(notifications): day sheet notification types
Add daySheetId field to NotificationItem model (Brick-managed), extract notificationTitle/notificationIcon to top-level testable functions, add five day-sheet notification cases, and wire tap/banner routing for day-sheet detail and approvals tab. Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -23,6 +23,9 @@ Future<NotificationItem> _$NotificationItemFromSupabase(
|
|||||||
? null
|
? null
|
||||||
: data['announcement_id'] as String?,
|
: data['announcement_id'] as String?,
|
||||||
messageId: data['message_id'] == null ? null : data['message_id'] as int?,
|
messageId: data['message_id'] == null ? null : data['message_id'] as int?,
|
||||||
|
daySheetId: data['day_sheet_id'] == null
|
||||||
|
? null
|
||||||
|
: data['day_sheet_id'] as String?,
|
||||||
type: data['type'] as String,
|
type: data['type'] as String,
|
||||||
createdAt: DateTime.parse(data['created_at'] as String),
|
createdAt: DateTime.parse(data['created_at'] as String),
|
||||||
readAt: data['read_at'] == null
|
readAt: data['read_at'] == null
|
||||||
@@ -49,6 +52,7 @@ Future<Map<String, dynamic>> _$NotificationItemToSupabase(
|
|||||||
'it_service_request_id': instance.itServiceRequestId,
|
'it_service_request_id': instance.itServiceRequestId,
|
||||||
'announcement_id': instance.announcementId,
|
'announcement_id': instance.announcementId,
|
||||||
'message_id': instance.messageId,
|
'message_id': instance.messageId,
|
||||||
|
'day_sheet_id': instance.daySheetId,
|
||||||
'type': instance.type,
|
'type': instance.type,
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
'read_at': instance.readAt?.toIso8601String(),
|
'read_at': instance.readAt?.toIso8601String(),
|
||||||
@@ -77,6 +81,9 @@ Future<NotificationItem> _$NotificationItemFromSqlite(
|
|||||||
? null
|
? null
|
||||||
: data['announcement_id'] as String?,
|
: data['announcement_id'] as String?,
|
||||||
messageId: data['message_id'] == null ? null : data['message_id'] as int?,
|
messageId: data['message_id'] == null ? null : data['message_id'] as int?,
|
||||||
|
daySheetId: data['day_sheet_id'] == null
|
||||||
|
? null
|
||||||
|
: data['day_sheet_id'] as String?,
|
||||||
type: data['type'] as String,
|
type: data['type'] as String,
|
||||||
createdAt: DateTime.parse(data['created_at'] as String),
|
createdAt: DateTime.parse(data['created_at'] as String),
|
||||||
readAt: data['read_at'] == null
|
readAt: data['read_at'] == null
|
||||||
@@ -103,6 +110,7 @@ Future<Map<String, dynamic>> _$NotificationItemToSqlite(
|
|||||||
'it_service_request_id': instance.itServiceRequestId,
|
'it_service_request_id': instance.itServiceRequestId,
|
||||||
'announcement_id': instance.announcementId,
|
'announcement_id': instance.announcementId,
|
||||||
'message_id': instance.messageId,
|
'message_id': instance.messageId,
|
||||||
|
'day_sheet_id': instance.daySheetId,
|
||||||
'type': instance.type,
|
'type': instance.type,
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
'read_at': instance.readAt?.toIso8601String(),
|
'read_at': instance.readAt?.toIso8601String(),
|
||||||
@@ -160,6 +168,10 @@ class NotificationItemAdapter
|
|||||||
association: false,
|
association: false,
|
||||||
columnName: 'message_id',
|
columnName: 'message_id',
|
||||||
),
|
),
|
||||||
|
'daySheetId': const RuntimeSupabaseColumnDefinition(
|
||||||
|
association: false,
|
||||||
|
columnName: 'day_sheet_id',
|
||||||
|
),
|
||||||
'type': const RuntimeSupabaseColumnDefinition(
|
'type': const RuntimeSupabaseColumnDefinition(
|
||||||
association: false,
|
association: false,
|
||||||
columnName: 'type',
|
columnName: 'type',
|
||||||
@@ -245,6 +257,12 @@ class NotificationItemAdapter
|
|||||||
iterable: false,
|
iterable: false,
|
||||||
type: int,
|
type: int,
|
||||||
),
|
),
|
||||||
|
'daySheetId': const RuntimeSqliteColumnDefinition(
|
||||||
|
association: false,
|
||||||
|
columnName: 'day_sheet_id',
|
||||||
|
iterable: false,
|
||||||
|
type: String,
|
||||||
|
),
|
||||||
'type': const RuntimeSqliteColumnDefinition(
|
'type': const RuntimeSqliteColumnDefinition(
|
||||||
association: false,
|
association: false,
|
||||||
columnName: 'type',
|
columnName: 'type',
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ import 'package:brick_supabase/brick_supabase.dart';
|
|||||||
// ignore: unused_import, unused_shown_name, unnecessary_import
|
// ignore: unused_import, unused_shown_name, unnecessary_import
|
||||||
import '../utils/app_time.dart';
|
import '../utils/app_time.dart';
|
||||||
// ignore: unused_import, unused_shown_name, unnecessary_import
|
// ignore: unused_import, unused_shown_name, unnecessary_import
|
||||||
|
import 'package:tasq/utils/programmer_daily_time.dart';
|
||||||
|
// ignore: unused_import, unused_shown_name, unnecessary_import
|
||||||
|
import 'package:tasq/utils/programmer_day_rows.dart';
|
||||||
|
// ignore: unused_import, unused_shown_name, unnecessary_import
|
||||||
|
import '../utils/programmer_daily_time.dart';
|
||||||
|
// ignore: unused_import, unused_shown_name, unnecessary_import
|
||||||
import 'package:tasq/models/team_member.dart';// GENERATED CODE DO NOT EDIT
|
import 'package:tasq/models/team_member.dart';// GENERATED CODE DO NOT EDIT
|
||||||
// ignore: unused_import
|
// ignore: unused_import
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// GENERATED CODE EDIT WITH CAUTION
|
||||||
|
// THIS FILE **WILL NOT** BE REGENERATED
|
||||||
|
// This file should be version controlled and can be manually edited.
|
||||||
|
part of 'schema.g.dart';
|
||||||
|
|
||||||
|
// While migrations are intelligently created, the difference between some commands, such as
|
||||||
|
// DropTable vs. RenameTable, cannot be determined. For this reason, please review migrations after
|
||||||
|
// they are created to ensure the correct inference was made.
|
||||||
|
|
||||||
|
// The migration version must **always** mirror the file name
|
||||||
|
|
||||||
|
const List<MigrationCommand> _migration_20260928065256_up = [
|
||||||
|
InsertColumn('day_sheet_id', Column.varchar, onTable: 'NotificationItem')
|
||||||
|
];
|
||||||
|
|
||||||
|
const List<MigrationCommand> _migration_20260928065256_down = [
|
||||||
|
DropColumn('day_sheet_id', onTable: 'NotificationItem')
|
||||||
|
];
|
||||||
|
|
||||||
|
//
|
||||||
|
// DO NOT EDIT BELOW THIS LINE
|
||||||
|
//
|
||||||
|
|
||||||
|
@Migratable(
|
||||||
|
version: '20260928065256',
|
||||||
|
up: _migration_20260928065256_up,
|
||||||
|
down: _migration_20260928065256_down,
|
||||||
|
)
|
||||||
|
class Migration20260928065256 extends Migration {
|
||||||
|
const Migration20260928065256()
|
||||||
|
: super(
|
||||||
|
version: 20260928065256,
|
||||||
|
up: _migration_20260928065256_up,
|
||||||
|
down: _migration_20260928065256_down,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,22 +1,24 @@
|
|||||||
// GENERATED CODE DO NOT EDIT
|
// GENERATED CODE DO NOT EDIT
|
||||||
// This file should be version controlled
|
// This file should be version controlled
|
||||||
import 'package:brick_sqlite/db.dart';
|
import 'package:brick_sqlite/db.dart';
|
||||||
part '20260927030348.migration.dart';
|
part '20260928065256.migration.dart';
|
||||||
part '20260411041808.migration.dart';
|
part '20260411041808.migration.dart';
|
||||||
part '20260411042152.migration.dart';
|
part '20260411042152.migration.dart';
|
||||||
part '20260926162926.migration.dart';
|
part '20260926162926.migration.dart';
|
||||||
|
part '20260927030348.migration.dart';
|
||||||
|
|
||||||
/// All intelligently-generated migrations from all `@Migratable` classes on disk
|
/// All intelligently-generated migrations from all `@Migratable` classes on disk
|
||||||
final migrations = <Migration>{
|
final migrations = <Migration>{
|
||||||
const Migration20260927030348(),
|
const Migration20260928065256(),
|
||||||
const Migration20260411041808(),
|
const Migration20260411041808(),
|
||||||
const Migration20260411042152(),
|
const Migration20260411042152(),
|
||||||
const Migration20260926162926(),
|
const Migration20260926162926(),
|
||||||
|
const Migration20260927030348(),
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A consumable database structure including the latest generated migration.
|
/// A consumable database structure including the latest generated migration.
|
||||||
final schema = Schema(
|
final schema = Schema(
|
||||||
20260926162926,
|
20260927030348,
|
||||||
generatorVersion: 1,
|
generatorVersion: 1,
|
||||||
tables: <SchemaTable>{
|
tables: <SchemaTable>{
|
||||||
SchemaTable(
|
SchemaTable(
|
||||||
@@ -271,6 +273,7 @@ final schema = Schema(
|
|||||||
SchemaColumn('it_service_request_id', Column.varchar),
|
SchemaColumn('it_service_request_id', Column.varchar),
|
||||||
SchemaColumn('announcement_id', Column.varchar),
|
SchemaColumn('announcement_id', Column.varchar),
|
||||||
SchemaColumn('message_id', Column.integer),
|
SchemaColumn('message_id', Column.integer),
|
||||||
|
SchemaColumn('day_sheet_id', Column.varchar),
|
||||||
SchemaColumn('type', Column.varchar),
|
SchemaColumn('type', Column.varchar),
|
||||||
SchemaColumn('created_at', Column.datetime),
|
SchemaColumn('created_at', Column.datetime),
|
||||||
SchemaColumn('read_at', Column.datetime),
|
SchemaColumn('read_at', Column.datetime),
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ class NotificationItem extends OfflineFirstWithSupabaseModel {
|
|||||||
final String? itServiceRequestId;
|
final String? itServiceRequestId;
|
||||||
final String? announcementId;
|
final String? announcementId;
|
||||||
final int? messageId;
|
final int? messageId;
|
||||||
|
@Sqlite(name: 'day_sheet_id')
|
||||||
|
final String? daySheetId;
|
||||||
final String type;
|
final String type;
|
||||||
final DateTime createdAt;
|
final DateTime createdAt;
|
||||||
final DateTime? readAt;
|
final DateTime? readAt;
|
||||||
@@ -38,6 +40,7 @@ class NotificationItem extends OfflineFirstWithSupabaseModel {
|
|||||||
required this.itServiceRequestId,
|
required this.itServiceRequestId,
|
||||||
this.announcementId,
|
this.announcementId,
|
||||||
required this.messageId,
|
required this.messageId,
|
||||||
|
this.daySheetId,
|
||||||
required this.type,
|
required this.type,
|
||||||
required this.createdAt,
|
required this.createdAt,
|
||||||
required this.readAt,
|
required this.readAt,
|
||||||
@@ -55,6 +58,7 @@ class NotificationItem extends OfflineFirstWithSupabaseModel {
|
|||||||
itServiceRequestId: map['it_service_request_id'] as String?,
|
itServiceRequestId: map['it_service_request_id'] as String?,
|
||||||
announcementId: map['announcement_id'] as String?,
|
announcementId: map['announcement_id'] as String?,
|
||||||
messageId: map['message_id'] as int?,
|
messageId: map['message_id'] as int?,
|
||||||
|
daySheetId: map['day_sheet_id'] as String?,
|
||||||
type: map['type'] as String? ?? 'mention',
|
type: map['type'] as String? ?? 'mention',
|
||||||
createdAt: AppTime.parse(map['created_at'] as String),
|
createdAt: AppTime.parse(map['created_at'] as String),
|
||||||
readAt: map['read_at'] == null
|
readAt: map['read_at'] == null
|
||||||
|
|||||||
@@ -16,6 +16,48 @@ import '../../widgets/responsive_body.dart';
|
|||||||
import '../../theme/app_surfaces.dart';
|
import '../../theme/app_surfaces.dart';
|
||||||
import '../../theme/m3_motion.dart';
|
import '../../theme/m3_motion.dart';
|
||||||
|
|
||||||
|
String notificationTitle(String type, String actorName) {
|
||||||
|
return switch (type) {
|
||||||
|
'assignment' => '$actorName assigned you',
|
||||||
|
'created' => '$actorName created a new item',
|
||||||
|
'swap_request' => '$actorName requested a shift swap',
|
||||||
|
'swap_update' => '$actorName updated a swap request',
|
||||||
|
'announcement' => '$actorName posted an announcement',
|
||||||
|
'announcement_comment' => '$actorName commented on an announcement',
|
||||||
|
'it_job_reminder' => 'IT Job submission reminder',
|
||||||
|
'isr_approved' => 'IT Service Request approved',
|
||||||
|
'isr_status_changed' => 'IT Service Request status updated',
|
||||||
|
'isr_assigned' => '$actorName assigned you an IT Service Request',
|
||||||
|
'day_sheet_submitted' => '$actorName submitted a day sheet',
|
||||||
|
'day_sheet_disapproved' => 'Day sheet disapproved',
|
||||||
|
'day_sheet_justified' => '$actorName justified a day sheet',
|
||||||
|
'day_sheet_approved' => 'Day sheet approved',
|
||||||
|
'day_sheet_digest' => 'Day sheets awaiting review',
|
||||||
|
_ => '$actorName mentioned you',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
IconData notificationIcon(String type) {
|
||||||
|
return switch (type) {
|
||||||
|
'assignment' => Icons.assignment_ind_outlined,
|
||||||
|
'created' => Icons.campaign_outlined,
|
||||||
|
'swap_request' => Icons.swap_horiz,
|
||||||
|
'swap_update' => Icons.update,
|
||||||
|
'announcement' => Icons.campaign,
|
||||||
|
'announcement_comment' => Icons.comment_outlined,
|
||||||
|
'it_job_reminder' => Icons.print,
|
||||||
|
'isr_approved' => Icons.check_circle_outline,
|
||||||
|
'isr_status_changed' => Icons.sync_alt_outlined,
|
||||||
|
'isr_assigned' => Icons.engineering_outlined,
|
||||||
|
'day_sheet_submitted' => Icons.assignment_turned_in_outlined,
|
||||||
|
'day_sheet_disapproved' => Icons.report_outlined,
|
||||||
|
'day_sheet_justified' => Icons.reply_outlined,
|
||||||
|
'day_sheet_approved' => Icons.verified_outlined,
|
||||||
|
'day_sheet_digest' => Icons.inbox_outlined,
|
||||||
|
_ => Icons.alternate_email,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
class NotificationsScreen extends ConsumerStatefulWidget {
|
class NotificationsScreen extends ConsumerStatefulWidget {
|
||||||
const NotificationsScreen({super.key});
|
const NotificationsScreen({super.key});
|
||||||
|
|
||||||
@@ -80,42 +122,11 @@ class _NotificationsScreenState extends ConsumerState<NotificationsScreen> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
String _notificationTitle(String type, String actorName) {
|
|
||||||
return switch (type) {
|
|
||||||
'assignment' => '$actorName assigned you',
|
|
||||||
'created' => '$actorName created a new item',
|
|
||||||
'swap_request' => '$actorName requested a shift swap',
|
|
||||||
'swap_update' => '$actorName updated a swap request',
|
|
||||||
'announcement' => '$actorName posted an announcement',
|
|
||||||
'announcement_comment' => '$actorName commented on an announcement',
|
|
||||||
'it_job_reminder' => 'IT Job submission reminder',
|
|
||||||
'isr_approved' => 'IT Service Request approved',
|
|
||||||
'isr_status_changed' => 'IT Service Request status updated',
|
|
||||||
'isr_assigned' => '$actorName assigned you an IT Service Request',
|
|
||||||
_ => '$actorName mentioned you',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
IconData _notificationIcon(String type) {
|
|
||||||
return switch (type) {
|
|
||||||
'assignment' => Icons.assignment_ind_outlined,
|
|
||||||
'created' => Icons.campaign_outlined,
|
|
||||||
'swap_request' => Icons.swap_horiz,
|
|
||||||
'swap_update' => Icons.update,
|
|
||||||
'announcement' => Icons.campaign,
|
|
||||||
'announcement_comment' => Icons.comment_outlined,
|
|
||||||
'it_job_reminder' => Icons.print,
|
|
||||||
'isr_approved' => Icons.check_circle_outline,
|
|
||||||
'isr_status_changed' => Icons.sync_alt_outlined,
|
|
||||||
'isr_assigned' => Icons.engineering_outlined,
|
|
||||||
_ => Icons.alternate_email,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _handleTap(BuildContext context, NotificationItem item) async {
|
Future<void> _handleTap(BuildContext context, NotificationItem item) async {
|
||||||
final ticketId = item.ticketId;
|
final ticketId = item.ticketId;
|
||||||
final taskId = item.taskId;
|
final taskId = item.taskId;
|
||||||
final isrId = item.itServiceRequestId;
|
final isrId = item.itServiceRequestId;
|
||||||
|
final daySheetId = item.daySheetId;
|
||||||
|
|
||||||
if (ticketId != null) {
|
if (ticketId != null) {
|
||||||
await ref
|
await ref
|
||||||
@@ -136,6 +147,10 @@ class _NotificationsScreenState extends ConsumerState<NotificationsScreen> {
|
|||||||
context.go('/tickets/$ticketId');
|
context.go('/tickets/$ticketId');
|
||||||
} else if (isrId != null) {
|
} else if (isrId != null) {
|
||||||
context.go('/it-service-requests/$isrId');
|
context.go('/it-service-requests/$isrId');
|
||||||
|
} else if (item.type == 'day_sheet_digest') {
|
||||||
|
context.go('/programmer-tasks?tab=approvals');
|
||||||
|
} else if (daySheetId != null) {
|
||||||
|
context.go('/programmer-tasks/day-sheets/$daySheetId');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,8 +263,8 @@ class _NotificationsScreenState extends ConsumerState<NotificationsScreen> {
|
|||||||
animDelay: Duration(
|
animDelay: Duration(
|
||||||
milliseconds: animIndexes[index].clamp(0, 6) * 50,
|
milliseconds: animIndexes[index].clamp(0, 6) * 50,
|
||||||
),
|
),
|
||||||
title: _notificationTitle(item.type, actorName),
|
title: notificationTitle(item.type, actorName),
|
||||||
icon: _notificationIcon(item.type),
|
icon: notificationIcon(item.type),
|
||||||
iconContainerColor:
|
iconContainerColor:
|
||||||
_iconContainerColor(context, item.type),
|
_iconContainerColor(context, item.type),
|
||||||
iconForegroundColor:
|
iconForegroundColor:
|
||||||
@@ -331,6 +346,7 @@ class _NotificationCard extends StatelessWidget {
|
|||||||
if (item.announcementId != null) return 'Announcement';
|
if (item.announcementId != null) return 'Announcement';
|
||||||
if (item.taskId != null) return taskTitle ?? 'Task';
|
if (item.taskId != null) return taskTitle ?? 'Task';
|
||||||
if (item.itServiceRequestId != null) return 'IT Service Request';
|
if (item.itServiceRequestId != null) return 'IT Service Request';
|
||||||
|
if (item.daySheetId != null) return 'Day Sheet';
|
||||||
return ticketSubject ?? 'Ticket';
|
return ticketSubject ?? 'Ticket';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,11 @@ class _NotificationBridgeState extends ConsumerState<NotificationBridge>
|
|||||||
'isr_approved' => 'IT Service Request approved',
|
'isr_approved' => 'IT Service Request approved',
|
||||||
'isr_status_changed' => 'IT Service Request updated',
|
'isr_status_changed' => 'IT Service Request updated',
|
||||||
'isr_assigned' => 'New IT Service Request assigned',
|
'isr_assigned' => 'New IT Service Request assigned',
|
||||||
|
'day_sheet_submitted' => 'Day sheet submitted',
|
||||||
|
'day_sheet_disapproved' => 'Day sheet disapproved',
|
||||||
|
'day_sheet_justified' => 'Day sheet justified',
|
||||||
|
'day_sheet_approved' => 'Day sheet approved',
|
||||||
|
'day_sheet_digest' => 'Day sheets awaiting review',
|
||||||
_ => 'New notification',
|
_ => 'New notification',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -121,7 +126,13 @@ class _NotificationBridgeState extends ConsumerState<NotificationBridge>
|
|||||||
action: SnackBarAction(
|
action: SnackBarAction(
|
||||||
label: 'View',
|
label: 'View',
|
||||||
onPressed: () => _goToDetail(
|
onPressed: () => _goToDetail(
|
||||||
route: item.announcementId != null ? '/announcements' : null,
|
route: item.announcementId != null
|
||||||
|
? '/announcements'
|
||||||
|
: item.type == 'day_sheet_digest'
|
||||||
|
? '/programmer-tasks?tab=approvals'
|
||||||
|
: item.daySheetId != null
|
||||||
|
? '/programmer-tasks/day-sheets/${item.daySheetId}'
|
||||||
|
: null,
|
||||||
taskId: item.taskId,
|
taskId: item.taskId,
|
||||||
ticketId: item.ticketId,
|
ticketId: item.ticketId,
|
||||||
itServiceRequestId: item.itServiceRequestId,
|
itServiceRequestId: item.itServiceRequestId,
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:tasq/screens/notifications/notifications_screen.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('notificationTitle', () {
|
||||||
|
test('assignment guard (existing case unchanged)', () {
|
||||||
|
expect(notificationTitle('assignment', 'Alice'), 'Alice assigned you');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('day_sheet_submitted', () {
|
||||||
|
expect(
|
||||||
|
notificationTitle('day_sheet_submitted', 'Bob'),
|
||||||
|
'Bob submitted a day sheet',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('day_sheet_disapproved', () {
|
||||||
|
expect(
|
||||||
|
notificationTitle('day_sheet_disapproved', 'Alice'),
|
||||||
|
'Day sheet disapproved',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('day_sheet_justified', () {
|
||||||
|
expect(
|
||||||
|
notificationTitle('day_sheet_justified', 'Bob'),
|
||||||
|
'Bob justified a day sheet',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('day_sheet_approved', () {
|
||||||
|
expect(
|
||||||
|
notificationTitle('day_sheet_approved', 'Alice'),
|
||||||
|
'Day sheet approved',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('day_sheet_digest', () {
|
||||||
|
expect(
|
||||||
|
notificationTitle('day_sheet_digest', 'System'),
|
||||||
|
'Day sheets awaiting review',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('notificationIcon', () {
|
||||||
|
test('assignment guard (existing case unchanged)', () {
|
||||||
|
expect(notificationIcon('assignment'), Icons.assignment_ind_outlined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('day_sheet_submitted', () {
|
||||||
|
expect(
|
||||||
|
notificationIcon('day_sheet_submitted'),
|
||||||
|
Icons.assignment_turned_in_outlined,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('day_sheet_disapproved', () {
|
||||||
|
expect(
|
||||||
|
notificationIcon('day_sheet_disapproved'),
|
||||||
|
Icons.report_outlined,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('day_sheet_justified', () {
|
||||||
|
expect(
|
||||||
|
notificationIcon('day_sheet_justified'),
|
||||||
|
Icons.reply_outlined,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('day_sheet_approved', () {
|
||||||
|
expect(
|
||||||
|
notificationIcon('day_sheet_approved'),
|
||||||
|
Icons.verified_outlined,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('day_sheet_digest', () {
|
||||||
|
expect(
|
||||||
|
notificationIcon('day_sheet_digest'),
|
||||||
|
Icons.inbox_outlined,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user