feat: add wishlist
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import type { H3Event } from 'h3'
|
||||
|
||||
interface LookupValue {
|
||||
value: string | null
|
||||
}
|
||||
|
||||
// title, date and author_or_director are lookups through the `books` link
|
||||
export interface ReviewRow {
|
||||
id: number
|
||||
books: LookupValue[]
|
||||
title: LookupValue[]
|
||||
date: LookupValue[]
|
||||
author_or_director: LookupValue[]
|
||||
review: string | null
|
||||
medium: SelectOption | null
|
||||
}
|
||||
|
||||
interface SelectOption {
|
||||
id: number
|
||||
value: string
|
||||
}
|
||||
|
||||
interface Field {
|
||||
name: string
|
||||
select_options?: SelectOption[]
|
||||
link_row_table_id?: number
|
||||
}
|
||||
|
||||
const FIELD_CACHE_MS = 10 * 60_000
|
||||
|
||||
let reviewFields: { fields: Field[], fetchedAt: number } | null = null
|
||||
|
||||
async function fields(event: H3Event): Promise<Field[]> {
|
||||
if (!reviewFields || Date.now() - reviewFields.fetchedAt > FIELD_CACHE_MS) {
|
||||
reviewFields = { fields: await listFields<Field>(event, diaryTable(event, 'reviews')), fetchedAt: Date.now() }
|
||||
}
|
||||
return reviewFields.fields
|
||||
}
|
||||
|
||||
function toMedium(value: string | undefined): Medium | null {
|
||||
return MEDIUM_KEYS.find(medium => MEDIUMS[medium].label === value) ?? null
|
||||
}
|
||||
|
||||
export function lookupValues(values: LookupValue[] | null | undefined): string[] {
|
||||
return (values ?? []).map(({ value }) => value?.trim()).filter((value): value is string => !!value)
|
||||
}
|
||||
|
||||
export function toReview(row: ReviewRow): Review {
|
||||
return {
|
||||
id: row.id,
|
||||
date: lookupValues(row.date)[0] ?? '',
|
||||
title: lookupValues(row.title).join(' / ') || lookupValues(row.books).join(' / '),
|
||||
author: lookupValues(row.author_or_director).join(', ') || null,
|
||||
text: (row.review ?? '').replace(/ /g, ' ').trim(),
|
||||
medium: toMedium(row.medium?.value)
|
||||
}
|
||||
}
|
||||
|
||||
export async function mediumOptionId(event: H3Event, medium: Medium): Promise<number> {
|
||||
const options = (await fields(event)).find(field => field.name === 'medium')?.select_options ?? []
|
||||
const id = options.find(option => toMedium(option.value) === medium)?.id
|
||||
if (!id) {
|
||||
throw createError({ statusCode: 500, statusMessage: `The medium field has no "${MEDIUMS[medium].label}" option` })
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
/** The books table, taken from the reviews table's `books` link field. */
|
||||
export async function booksTableId(event: H3Event): Promise<string> {
|
||||
const id = (await fields(event)).find(field => field.name === 'books')?.link_row_table_id
|
||||
if (!id) {
|
||||
throw createError({ statusCode: 500, statusMessage: 'The reviews table has no "books" link field' })
|
||||
}
|
||||
return String(id)
|
||||
}
|
||||
Reference in New Issue
Block a user