Files
CTM-Concierge/electron/main/pocketbase.js
T

208 lines
5.9 KiB
JavaScript

import PocketBase from 'pocketbase'
import { POCKETBASE_URL, PB_ADMIN_EMAIL, PB_ADMIN_PASSWORD } from './pocketbase-config.js'
const COLLECTION = 'travellers'
const VACCINE_RECORDS_COLLECTION = 'records'
const VACCINES_COLLECTION = 'vaccines'
function parseVaccineRecord(r) {
return {
id: r.id,
travellerId: r.traveller_id ?? r.traveller ?? '',
travellerName: r.traveller_name ?? '',
emrID: r.emr_id ?? '',
timelines: r.timelines ?? r.vaccine_timelines ?? [],
created: r.created,
updated: r.updated,
}
}
/**
* Fetches all records from the vaccines collection.
* Returns raw records with all fields preserved.
*/
export async function fetchVaccines() {
await ensureAuth()
const list = await getClient().collection(VACCINES_COLLECTION).getFullList({ sort: 'name' })
return list.map((r) => ({
id: r.id,
name: r.name ?? '',
vaccine_type: r.vaccine_type ?? '',
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,
}))
}
export async function fetchVaccineRecords() {
await ensureAuth()
const list = await getClient().collection(VACCINE_RECORDS_COLLECTION).getFullList({ sort: '-created' })
return list.map(parseVaccineRecord)
}
export async function saveVaccineRecord(data) {
await ensureAuth()
const client = getClient()
const travellerId = data.traveller_id
let existing = null
try {
const list = await client.collection(VACCINE_RECORDS_COLLECTION).getList(1, 50, {
filter: `traveller_id = "${travellerId}"`
})
if (list.items && list.items.length > 0) {
existing = list.items[0]
}
} catch (e) {
// ignore filter error
}
const payload = {
traveller_id: travellerId,
traveller_name: data.travellerName || data.traveller_name || '',
emr_id: data.emrID || data.emr_id || null,
timelines: data.timelines || data.vaccineTimelines || data.vaccine_timelines || [],
}
if (existing) {
const record = await client.collection(VACCINE_RECORDS_COLLECTION).update(existing.id, payload)
return parseVaccineRecord(record)
} else {
const record = await client.collection(VACCINE_RECORDS_COLLECTION).create(payload)
return parseVaccineRecord(record)
}
}
export async function updateVaccineRecord(id, data) {
await ensureAuth()
const travellerId = data.traveller_id
const payload = {
traveller_id: travellerId,
traveller_name: data.travellerName || data.traveller_name || '',
emr_id: data.emrID || data.emr_id || null,
timelines: data.timelines || data.vaccineTimelines || data.vaccine_timelines || [],
}
const record = await getClient().collection(VACCINE_RECORDS_COLLECTION).update(id, payload)
return parseVaccineRecord(record)
}
let pb = null
let authPromise = null
function getClient() {
if (!pb) {
pb = new PocketBase(POCKETBASE_URL)
// Main process may receive overlapping IPC calls (e.g. React Strict Mode).
// Default auto-cancel would abort duplicate in-flight PocketBase requests.
pb.autoCancellation(false)
}
return pb
}
function parseEntry(r) {
return {
id: r.id,
recordID: r.record_id ?? r.recordID ?? '',
emrID: r.emr_id ?? '',
name: r.name ?? '',
location: r.location ?? '',
countryISO: r.country_iso ?? '',
countriesISO: r.countries_iso ?? [],
status: r.status ?? '',
departure: r.departure ?? '',
arrival: r.arrival ?? '',
created: r.created,
updated: r.updated,
}
}
export async function ensureAuth() {
const client = getClient()
if (client.authStore.isValid) return
if (authPromise) {
await authPromise
return
}
// PocketBase v0.23+ removed /api/admins/*; superusers authenticate as a collection.
authPromise = client
.collection('_superusers')
.authWithPassword(PB_ADMIN_EMAIL, PB_ADMIN_PASSWORD)
try {
await authPromise
} catch (err) {
authPromise = null
throw err
}
}
export async function fetchEntries() {
await ensureAuth()
const list = await getClient().collection(COLLECTION).getFullList({ sort: '-created' })
return list.map(parseEntry)
}
export async function createEntry(trip) {
await ensureAuth()
const payload = {
name: trip.name,
location: trip.location,
countries_iso: trip.countriesISO,
departure: trip.departure,
arrival: trip.arrival,
}
if (trip.status !== undefined) {
payload.status = trip.status
}
if (trip.recordID || trip.record_id) {
payload.record_id = trip.recordID || trip.record_id
}
if (trip.emrID !== undefined && trip.emrID !== null && trip.emrID !== '') {
const emrNum = Number(trip.emrID)
payload.emr_id = !isNaN(emrNum) ? emrNum : trip.emrID
}
const record = await getClient().collection(COLLECTION).create(payload)
return parseEntry(record)
}
export async function updateEntry(id, trip) {
await ensureAuth()
const payload = {
name: trip.name,
location: trip.location,
countries_iso: trip.countriesISO,
departure: trip.departure,
arrival: trip.arrival,
}
if (trip.status !== undefined) {
payload.status = trip.status
}
if (trip.recordID !== undefined || trip.record_id !== undefined) {
payload.record_id = trip.recordID || trip.record_id || null
}
if (trip.emrID !== undefined && trip.emrID !== null && trip.emrID !== '') {
const emrNum = Number(trip.emrID)
payload.emr_id = !isNaN(emrNum) ? emrNum : trip.emrID
} else if (trip.emrID === '') {
payload.emr_id = null
}
const record = await getClient().collection(COLLECTION).update(id, payload)
return parseEntry(record)
}
export async function deleteEntry(id) {
await ensureAuth()
await getClient().collection(COLLECTION).delete(id)
}