Added Notifications screen and logic for Records.

This commit is contained in:
Bruno Silva committed 2026-09-28 16:41:51 -04:00
1 parent 72ec7472c5
commit 697d72f379
13 files changed
+2255 -145

No files matched your search

+126 -2
View File
@@ -5,6 +5,7 @@ const TRAVELLERS_COLLECTION = 'travellers'
const TRIPS_COLLECTION = 'trips'
const VACCINE_RECORDS_COLLECTION = 'records'
const VACCINES_COLLECTION = 'vaccines'
const NOTIFICATIONS_COLLECTION = 'notifications'
let pb = null
@@ -46,8 +47,6 @@ export async function fetchVaccines() {
total_doses: r.total_doses ?? 1,
dose_intervals: r.dose_intervals ?? [],
min_days_before_travel: r.min_days_before_travel ?? 0,
allows_grace_period: r.allows_grace_period ?? false,
has_accelerated_schedule: r.has_accelerated_schedule ?? false,
requires_icvp_certificate: r.requires_icvp_certificate ?? false,
created: r.created,
updated: r.updated,
@@ -224,6 +223,47 @@ export async function fetchTravellers() {
return list.map(parseTraveller)
}
export async function createTraveller(data) {
await ensureAuth()
const client = getClient()
const emrStr = data.emrID !== undefined && data.emrID !== null ? String(data.emrID).trim() : ''
const nameStr = data.name ? String(data.name).trim() : ''
if (!nameStr) {
throw new Error('Traveller name is required.')
}
// If already exists with this emr_id, return existing
if (emrStr) {
try {
const filter = client.filter
? client.filter('emr_id = {:emrId}', { emrId: emrStr })
: `emr_id = "${emrStr.replace(/"/g, '\\"')}"`
const list = await client.collection(TRAVELLERS_COLLECTION).getList(1, 1, { filter })
if (list.items && list.items.length > 0) {
return {
...parseTraveller(list.items[0]),
isExisting: true,
}
}
} catch (e) {
console.warn(`[pocketbase] Lookup existing traveller with emr_id "${emrStr}":`, e.message)
}
}
const travellerPayload = {
emr_id: emrStr,
name: nameStr,
}
const record = await client.collection(TRAVELLERS_COLLECTION).create(travellerPayload)
return {
...parseTraveller(record),
isExisting: false,
}
}
export async function createEntry(trip) {
await ensureAuth()
const client = getClient()
@@ -376,6 +416,90 @@ export async function deleteEntry(id) {
})
}
// ─── Notifications Helpers ──────────────────────────────────────────────────
function parseNotification(r) {
let message = r.message ?? ''
if (typeof message === 'string') {
const trimmed = message.trim()
if ((trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
try {
message = JSON.parse(trimmed)
} catch {
message = trimmed.slice(1, -1)
}
}
}
return {
id: r.id,
message,
module: r.module ?? 'records',
is_read: Boolean(r.is_read),
is_archived: Boolean(r.is_archived),
meta: r.meta ?? null,
application: r.application ?? '',
created: r.created,
updated: r.updated,
}
}
/**
* Fetches all notifications, sorted by created desc by default.
* Optional query options: { filter, sort }
*/
export async function fetchNotifications(options = {}) {
await ensureAuth()
const client = getClient()
const queryParams = {
sort: options.sort || '-created',
requestKey: null,
}
if (options.filter) {
queryParams.filter = options.filter
}
const list = await client.collection(NOTIFICATIONS_COLLECTION).getFullList(queryParams)
return list.map(parseNotification)
}
/**
* Updates a notification record by id (e.g. { is_read: true }, { is_archived: true }).
*/
export async function updateNotification(id, data) {
await ensureAuth()
const client = getClient()
const record = await client.collection(NOTIFICATIONS_COLLECTION).update(id, data)
return parseNotification(record)
}
/**
* Convenience method to mark a notification as read or unread.
*/
export async function markNotificationRead(id, isRead = true) {
return await updateNotification(id, { is_read: isRead })
}
/**
* Marks all unread notifications as read.
*/
export async function markAllNotificationsRead() {
await ensureAuth()
const client = getClient()
const unreadList = await client.collection(NOTIFICATIONS_COLLECTION).getFullList({
filter: 'is_read = false',
requestKey: null,
})
const updated = await Promise.all(
unreadList.map((item) =>
client.collection(NOTIFICATIONS_COLLECTION).update(item.id, { is_read: true })
)
)
return updated.map(parseNotification)
}
/**
* Archives or unarchives a notification.
*/
export async function archiveNotification(id, isArchived = true) {
return await updateNotification(id, { is_archived: isArchived })
}