Whereaboutes and dashboard IT Staff Pulse enhancements
This commit is contained in:
@@ -379,7 +379,20 @@ final dashboardMetricsProvider = Provider<AsyncValue<DashboardMetrics>>((ref) {
|
||||
final hasActiveCheckIn = userLogs.any((l) => !l.isCheckedOut);
|
||||
final String whereabouts;
|
||||
if (livePos != null) {
|
||||
whereabouts = livePos.inPremise ? 'In premise' : 'Outside premise';
|
||||
final stale =
|
||||
AppTime.now().difference(livePos.updatedAt) >
|
||||
const Duration(minutes: 15);
|
||||
if (stale) {
|
||||
final diff = AppTime.now().difference(livePos.updatedAt);
|
||||
final ago = diff.inMinutes < 60
|
||||
? '${diff.inMinutes}m ago'
|
||||
: '${diff.inHours}h ago';
|
||||
whereabouts = livePos.inPremise
|
||||
? 'Last seen in premise \u00b7 $ago'
|
||||
: 'Last seen outside \u00b7 $ago';
|
||||
} else {
|
||||
whereabouts = livePos.inPremise ? 'In premise' : 'Outside premise';
|
||||
}
|
||||
} else if (!staff.allowTracking) {
|
||||
// Tracking off — infer from active check-in (geofence validated).
|
||||
whereabouts = hasActiveCheckIn ? 'In premise' : 'Tracking off';
|
||||
@@ -944,20 +957,28 @@ class _StaffTableHeader extends StatelessWidget {
|
||||
flex: isMobile ? 2 : 3,
|
||||
child: Text('IT Staff', style: style),
|
||||
),
|
||||
Expanded(flex: 2, child: Text('Status', style: style)),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Center(child: Text('Status', style: style)),
|
||||
),
|
||||
if (!isMobile)
|
||||
Expanded(flex: 2, child: Text('Whereabouts', style: style)),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: Center(child: Text('Whereabouts', style: style)),
|
||||
),
|
||||
Expanded(
|
||||
flex: isMobile ? 1 : 2,
|
||||
child: Text(isMobile ? 'Tix' : 'Tickets', style: style),
|
||||
flex: isMobile ? 1 : 1,
|
||||
child: Center(
|
||||
child: Text(isMobile ? 'Tix' : 'Tickets', style: style),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: isMobile ? 1 : 2,
|
||||
child: Text(isMobile ? 'Tsk' : 'Tasks', style: style),
|
||||
flex: isMobile ? 1 : 1,
|
||||
child: Center(child: Text(isMobile ? 'Tsk' : 'Tasks', style: style)),
|
||||
),
|
||||
Expanded(
|
||||
flex: isMobile ? 1 : 2,
|
||||
child: Text(isMobile ? 'Evt' : 'Events', style: style),
|
||||
flex: isMobile ? 1 : 1,
|
||||
child: Center(child: Text(isMobile ? 'Evt' : 'Events', style: style)),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -1023,15 +1044,24 @@ class _StaffRow extends StatelessWidget {
|
||||
final valueStyle = Theme.of(context).textTheme.bodySmall;
|
||||
final isMobile = AppBreakpoints.isMobile(context);
|
||||
|
||||
// Team color dot
|
||||
Widget? teamDot;
|
||||
if (row.teamColor != null) {
|
||||
// Team marker: use team color dot when assigned, otherwise a circular no-team image.
|
||||
final Widget teamMarker;
|
||||
if (row.teamColor != null && row.teamColor!.isNotEmpty) {
|
||||
final color = Color(int.parse(row.teamColor!, radix: 16) | 0xFF000000);
|
||||
teamDot = Container(
|
||||
teamMarker = Container(
|
||||
width: 10,
|
||||
height: 10,
|
||||
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
|
||||
);
|
||||
} else {
|
||||
teamMarker = ClipOval(
|
||||
child: Image.asset(
|
||||
'assets/no_team.jpg',
|
||||
width: 14,
|
||||
height: 14,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// IT Staff cell: avatar on mobile, name on desktop, with team color dot
|
||||
@@ -1040,7 +1070,8 @@ class _StaffRow extends StatelessWidget {
|
||||
staffCell = Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (teamDot != null) ...[teamDot, const SizedBox(width: 4)],
|
||||
teamMarker,
|
||||
const SizedBox(width: 4),
|
||||
Flexible(
|
||||
child: Tooltip(
|
||||
message: row.name,
|
||||
@@ -1057,7 +1088,8 @@ class _StaffRow extends StatelessWidget {
|
||||
staffCell = Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (teamDot != null) ...[teamDot, const SizedBox(width: 6)],
|
||||
teamMarker,
|
||||
const SizedBox(width: 6),
|
||||
Flexible(child: Text(row.name, style: valueStyle)),
|
||||
],
|
||||
);
|
||||
@@ -1070,42 +1102,49 @@ class _StaffRow extends StatelessWidget {
|
||||
Expanded(flex: isMobile ? 2 : 3, child: staffCell),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: _PulseStatusPill(label: row.status),
|
||||
),
|
||||
child: Center(child: _PulseStatusPill(label: row.status)),
|
||||
),
|
||||
if (!isMobile)
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
row.whereabouts,
|
||||
style: valueStyle?.copyWith(
|
||||
color: row.whereabouts == 'In premise'
|
||||
? Colors.green
|
||||
: row.whereabouts == 'Outside premise'
|
||||
? Colors.grey
|
||||
: row.whereabouts == 'Tracking off'
|
||||
? Colors.grey
|
||||
: null,
|
||||
fontWeight: FontWeight.w600,
|
||||
flex: 4,
|
||||
child: Center(
|
||||
child: Text(
|
||||
row.whereabouts,
|
||||
style: valueStyle?.copyWith(
|
||||
color: row.whereabouts == 'In premise'
|
||||
? Colors.green
|
||||
: row.whereabouts == 'Outside premise'
|
||||
? Colors.grey
|
||||
: row.whereabouts == 'Tracking off'
|
||||
? Colors.grey
|
||||
: row.whereabouts.startsWith('Last seen')
|
||||
? Colors.grey
|
||||
: null,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: isMobile ? 1 : 2,
|
||||
child: Text(
|
||||
row.ticketsRespondedToday.toString(),
|
||||
style: valueStyle,
|
||||
flex: isMobile ? 1 : 1,
|
||||
child: Center(
|
||||
child: Text(
|
||||
row.ticketsRespondedToday.toString(),
|
||||
style: valueStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: isMobile ? 1 : 2,
|
||||
child: Text(row.tasksClosedToday.toString(), style: valueStyle),
|
||||
flex: isMobile ? 1 : 1,
|
||||
child: Center(
|
||||
child: Text(row.tasksClosedToday.toString(), style: valueStyle),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: isMobile ? 1 : 2,
|
||||
child: Text(row.eventsHandledToday.toString(), style: valueStyle),
|
||||
flex: isMobile ? 1 : 1,
|
||||
child: Center(
|
||||
child: Text(row.eventsHandledToday.toString(), style: valueStyle),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user