59 lines
1.6 KiB
TypeScript
59 lines
1.6 KiB
TypeScript
import type { H3Event } from 'h3'
|
|
|
|
export interface ReviewRow {
|
|
id: number
|
|
title: string | null
|
|
date: string | null
|
|
author_or_director: string | null
|
|
review: string | null
|
|
medium: SelectOption | null
|
|
}
|
|
|
|
interface SelectOption {
|
|
id: number
|
|
value: string
|
|
}
|
|
|
|
interface Field {
|
|
name: string
|
|
select_options?: SelectOption[]
|
|
}
|
|
|
|
const OPTION_CACHE_MS = 10 * 60_000
|
|
|
|
let mediumOptions: { ids: Partial<Record<Medium, number>>, fetchedAt: number } | null = null
|
|
|
|
function toMedium(value: string | undefined): Medium | null {
|
|
return MEDIUM_KEYS.find(medium => MEDIUMS[medium].label === value) ?? null
|
|
}
|
|
|
|
export function toReview(row: ReviewRow): Review {
|
|
return {
|
|
id: row.id,
|
|
date: row.date ?? '',
|
|
title: (row.title ?? '').trim(),
|
|
author: row.author_or_director?.trim() || null,
|
|
text: (row.review ?? '').replace(/ /g, ' ').trim(),
|
|
medium: toMedium(row.medium?.value)
|
|
}
|
|
}
|
|
|
|
export async function mediumOptionId(event: H3Event, medium: Medium): Promise<number> {
|
|
if (!mediumOptions || Date.now() - mediumOptions.fetchedAt > OPTION_CACHE_MS) {
|
|
const fields = await listFields<Field>(event, 'reviews')
|
|
const options = fields.find(field => field.name === 'medium')?.select_options ?? []
|
|
const ids: Partial<Record<Medium, number>> = {}
|
|
for (const option of options) {
|
|
const key = toMedium(option.value)
|
|
if (key) ids[key] = option.id
|
|
}
|
|
mediumOptions = { ids, fetchedAt: Date.now() }
|
|
}
|
|
|
|
const id = mediumOptions.ids[medium]
|
|
if (!id) {
|
|
throw createError({ statusCode: 500, statusMessage: `The medium field has no "${MEDIUMS[medium].label}" option` })
|
|
}
|
|
return id
|
|
}
|