Asset Management: Add Last Contact Time and Created Columns
Date: 2026-01-15 Author: AI Assistant Status: Completed
Overview
Added two new columns to the Asset Management table to display:
Last Contact- Shows the last contact time fromlast_contact_time_utcfieldCreated- Shows the creation timestamp fromcreated_atfield
Changes Made
1. Updated SortField Type
File: src/features/assets/services/assetsService.ts
Added last_contact_time_utc to the SortField type to enable sorting by last contact time.
typescript
export type SortField =
| "display_id"
| "asset_id"
| "serial_number"
| "asset_type_code"
| "telematics_provider_code"
| "mine_site"
| "operational_status_code"
| "archived"
| "created_at"
| "last_contact_time_utc" // Added
| "client_name"
| "fleet_name";2. Updated Asset Management Page
File: src/app/(admin)/(pages)/asset-management/index.tsx
Added Date Formatting Function
typescript
const formatDateTime = (value?: string | null) => {
if (!value) return "-";
const date = new Date(value);
if (Number.isNaN(date.getTime())) return "-";
return date.toLocaleString("en-AU", {
dateStyle: "short",
timeStyle: "short",
});
};Updated Table Headers
Added two new sortable headers:
- "Last Contact" (11% width) - sorts by
last_contact_time_utc - "Created" (10% width) - sorts by
created_at
Adjusted existing column widths to accommodate the new columns:
- Display ID: 18% → 14%
- Asset ID: 20% → 16% → 13% (further reduced for better spacing)
- Serial: 10% → 8% → 12% (increased for better visibility)
- Type: 12% → 9%
- Provider: 10% → 8%
- Mine Site: 14% → 10%
- Status: 8% → 7%
- Actions: 8% → 7% → 6% (reduced for better spacing)
Updated Table Body
Added two new data cells in each table row:
tsx
<td className="px-4 py-3 text-xs text-slate-600 dark:text-slate-400">
{formatDateTime(asset.last_contact_time_utc)}
</td>
<td className="px-4 py-3 text-xs text-slate-600 dark:text-slate-400">
{formatDateTime(asset.created_at)}
</td>Updated Empty State
Changed the empty state colspan from 8 to 10 to match the new column count.
Features
- Sortable Columns: Both new columns support ascending/descending sorting
- Date Formatting: Dates are displayed in Australian format (en-AU) with short date and time
- Null Handling: Shows "-" when date values are null or invalid
- Responsive Design: Column widths adjusted to maintain table layout
- Dark Mode Support: Text colors adapt to light/dark themes
Testing
To test the changes:
- Navigate to Asset Management page (
/asset-management) - Verify the two new columns appear in the table
- Click on column headers to test sorting functionality
- Check that dates display correctly in format: "dd/MM/yy, h:mm am/pm"
- Verify empty/null values show as "-"
Data Source
- Last Contact Time:
data_assets.last_contact_time_utc- UTC timestamp from SingleSourceIOT API - Created:
data_assets.created_at- Database creation timestamp (auto-managed)
Additional Enhancement: Serial Number Styling
Updated Serial Column Display
Changed the Serial Number column to match the Asset ID column styling:
Before:
- Plain text display
- No truncation for long serial numbers
- No copy functionality
After:
- Styled code block with background (
bg-slate-100 dark:bg-slate-700) - Truncated display with
truncateclass for long values - Hover tooltip shows full serial number via
titleattribute - Copy button appears on row hover (same as Asset ID)
- Monospace font for better readability
Implementation:
tsx
{asset.serial_number ? (
<div className="flex items-center gap-1.5 group">
<code
className="text-xs bg-slate-100 dark:bg-slate-700 px-2 py-1 rounded font-mono text-slate-600 dark:text-slate-400 truncate block"
title={asset.serial_number}
>
{asset.serial_number}
</code>
<button
className="p-1 text-slate-400 hover:text-blue-600 dark:hover:text-blue-400 opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0"
title="Copy Serial Number"
onClick={(e) => {
e.stopPropagation();
void navigator.clipboard.writeText(asset.serial_number || "");
}}
>
<Icon className="w-3.5 h-3.5" icon="solar:copy-linear" />
</button>
</div>
) : (
<span className="text-sm text-slate-400 dark:text-slate-500">—</span>
)}Notes
- The
last_contact_time_utcfield may be null for assets that haven't connected yet - The
created_atfield is automatically populated by the database on record creation - Both fields are already present in the database schema - no migration needed
- Date format uses Australian locale (en-AU) consistent with other pages in the application
- Serial Number and Asset ID columns now share consistent styling and UX patterns