64 lines
1.8 KiB
JavaScript
64 lines
1.8 KiB
JavaScript
import { request } from '../lib/apiClient'
|
|
import { toDate } from '../lib/format'
|
|
|
|
/** In-app notifications — backend/notifications/app.py. Scoped to the caller; no RBAC tag. */
|
|
|
|
const KIND_META = {
|
|
application: { icon: 'user-plus', color: 'i-green' },
|
|
interview: { icon: 'calendar', color: 'i-blue' },
|
|
offer: { icon: 'check', color: 'i-teal' },
|
|
assessment: { icon: 'star', color: 'i-amber' },
|
|
approval: { icon: 'file', color: 'i-indigo' },
|
|
message: { icon: 'message', color: 'i-purple' },
|
|
system: { icon: 'info', color: 'i-gray' },
|
|
}
|
|
|
|
export function list({ unreadOnly, top, skip } = {}) {
|
|
return request('/notifications/fetch', {
|
|
params: { unread_only: unreadOnly, top, skip },
|
|
})
|
|
}
|
|
|
|
export function markRead(recordId) {
|
|
return request(`/notifications/${recordId}/read`, { method: 'POST' })
|
|
}
|
|
|
|
export function markAllRead() {
|
|
return request('/notifications/read-all', { method: 'POST' })
|
|
}
|
|
|
|
export function remove(recordId) {
|
|
return request('/notifications/delete', {
|
|
method: 'DELETE',
|
|
params: { record_id: recordId },
|
|
})
|
|
}
|
|
|
|
function relTime(iso) {
|
|
if (!iso) return ''
|
|
const then = toDate(iso)
|
|
if (!then) return ''
|
|
const mins = Math.max(0, Math.round((Date.now() - then.getTime()) / 60000))
|
|
if (mins < 60) return `${mins}m ago`
|
|
if (mins < 1440) return `${Math.floor(mins / 60)}h ago`
|
|
return `${Math.floor(mins / 1440)}d ago`
|
|
}
|
|
|
|
export function toNotificationView(row) {
|
|
const meta = KIND_META[row.kind] || KIND_META.system
|
|
return {
|
|
id: row.id,
|
|
kind: row.kind,
|
|
title: row.title,
|
|
text: row.body || '',
|
|
linkPath: row.link_path || null,
|
|
inboxId: row.inbox_id,
|
|
jobPostId: row.job_post_id,
|
|
unread: !row.is_read,
|
|
time: relTime(row.created_at),
|
|
createdAt: row.created_at,
|
|
icon: meta.icon,
|
|
color: meta.color,
|
|
}
|
|
}
|