diff --git a/frontend/src/pages/clients/ClientsPage.css b/frontend/src/pages/clients/ClientsPage.css
index 085ce490..7081c2cc 100644
--- a/frontend/src/pages/clients/ClientsPage.css
+++ b/frontend/src/pages/clients/ClientsPage.css
@@ -62,6 +62,26 @@
.dot-orange { background: var(--ant-color-warning); }
.dot-gray { background: var(--ant-color-text-quaternary); }
+.online-dot {
+ display: inline-block;
+ width: 7px;
+ height: 7px;
+ border-radius: 50%;
+ margin-inline-end: 5px;
+ vertical-align: middle;
+ background: var(--ant-color-success);
+ animation: online-blink 1.1s ease-in-out infinite;
+}
+
+@keyframes online-blink {
+ 0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(82, 196, 26, 0.55); }
+ 50% { opacity: 0.35; box-shadow: 0 0 0 4px rgba(82, 196, 26, 0); }
+}
+
+@media (prefers-reduced-motion: reduce) {
+ .online-dot { animation: none; }
+}
+
.status-tag {
margin: 0 0 0 4px;
font-size: 11px;
diff --git a/frontend/src/pages/clients/ClientsPage.tsx b/frontend/src/pages/clients/ClientsPage.tsx
index 5ceefa06..adb8f323 100644
--- a/frontend/src/pages/clients/ClientsPage.tsx
+++ b/frontend/src/pages/clients/ClientsPage.tsx
@@ -626,10 +626,17 @@ export default function ClientsPage() {
render: (_v, record) => {
const bucket = clientBucket(record);
if (bucket === 'depleted') return {t('depleted')};
- if (record.enable && isOnline(record.email)) return {t('pages.clients.online')};
+ if (record.enable && isOnline(record.email)) return (
+ {t('pages.clients.online')}
+ );
if (!record.enable) return {t('disabled')};
if (bucket === 'expiring') return {t('depletingSoon')};
- return {t('pages.clients.offline')};
+ const lastOnline = record.traffic?.lastOnline ?? 0;
+ return (
+ 0 ? IntlUtil.formatDate(lastOnline, datepicker) : '-'}`}>
+ {t('pages.clients.offline')}
+
+ );
},
},
{
@@ -732,7 +739,7 @@ export default function ClientsPage() {
),
},
// eslint-disable-next-line react-hooks/exhaustive-deps
- ], [t, togglingEmail, clientBucket, isOnline, inboundsById, filters, allGroups]);
+ ], [t, togglingEmail, clientBucket, isOnline, inboundsById, filters, allGroups, datepicker]);
const tablePagination = {
current: currentPage,