initial commit
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
import type { Entry } from '~/types/entry'
|
||||
|
||||
const KIND_ORDER: Record<Entry['kind'], number> = { review: 0, note: 1 }
|
||||
|
||||
function toEntries(reviews: Review[], notes: Note[]): Entry[] {
|
||||
return [
|
||||
...reviews.map(review => ({ kind: 'review' as const, key: `review-${review.id}`, date: review.date, text: review.text, review })),
|
||||
...notes.map(note => ({ kind: 'note' as const, key: `note-${note.id}`, date: note.date, text: note.text, note }))
|
||||
]
|
||||
}
|
||||
|
||||
function searchableText(entry: Entry): string {
|
||||
const date = `${formatDate(entry.date)} ${entry.date}`
|
||||
const text = entry.kind === 'review'
|
||||
? `review ${entry.review.medium ?? ''} ${date} ${entry.review.title} ${entry.review.author ?? ''} ${entry.text}`
|
||||
: `note ${date} ${entry.text}`
|
||||
return text.toLowerCase()
|
||||
}
|
||||
|
||||
function newestFirst(a: Entry, b: Entry): number {
|
||||
return b.date.localeCompare(a.date) || KIND_ORDER[a.kind] - KIND_ORDER[b.kind] || b.key.localeCompare(a.key)
|
||||
}
|
||||
|
||||
function entryIcon(entry: Entry): string {
|
||||
if (entry.kind === 'note') return NOTE_ICON
|
||||
return entry.review.medium ? MEDIUM_ICONS[entry.review.medium] : REVIEW_ICON
|
||||
}
|
||||
|
||||
function groupByYear(entries: Entry[]) {
|
||||
const years = new Map<string, Entry[]>()
|
||||
for (const entry of entries) {
|
||||
const year = entry.date.slice(0, 4)
|
||||
years.set(year, [...(years.get(year) ?? []), entry])
|
||||
}
|
||||
return [...years].map(([year, entries]) => ({
|
||||
year,
|
||||
items: entries.map(entry => ({ value: entry.key, icon: entryIcon(entry), entry }))
|
||||
}))
|
||||
}
|
||||
|
||||
export function useDiary(search: Ref<string>) {
|
||||
const { data: reviews, error: reviewsError } = useFetch<Review[]>('/api/reviews', { key: 'reviews', default: () => [] })
|
||||
const { data: notes, error: notesError } = useFetch<Note[]>('/api/notes', { key: 'notes', default: () => [] })
|
||||
|
||||
const years = computed(() => {
|
||||
const terms = searchTerms(search.value)
|
||||
const matches = toEntries(reviews.value, notes.value)
|
||||
.filter(entry => entry.text)
|
||||
.filter((entry) => {
|
||||
const text = searchableText(entry)
|
||||
return terms.every(term => text.includes(term))
|
||||
})
|
||||
.toSorted(newestFirst)
|
||||
return groupByYear(matches)
|
||||
})
|
||||
|
||||
const errors = computed(() => [
|
||||
{ what: 'reviews', error: reviewsError.value },
|
||||
{ what: 'notes', error: notesError.value }
|
||||
].filter(({ error }) => error))
|
||||
|
||||
return { years, errors }
|
||||
}
|
||||
Reference in New Issue
Block a user