Files
archy/packages/app/src/composables/useContentPanel.ts
T

87 lines
2.1 KiB
TypeScript
Raw Normal View History

import { ref, computed } from 'vue'
import type { Film } from '@aiui/core/types/content'
import { mockFilms } from '@/mocks/films'
const panelOpen = ref(false)
const panelFilms = ref<Film[]>([])
const selectedFilm = ref<Film | null>(null)
const panelTitle = ref('Recommended Films')
const FILM_TAG_RE = /\[\[film:(f?\d+)\]\]/gi
export function useContentPanel() {
function normalizeFilmId(raw: string): string {
return raw.startsWith('f') ? raw : `f${raw}`
}
function extractFilmIds(text: string): string[] {
const ids: string[] = []
let match: RegExpExecArray | null
const re = new RegExp(FILM_TAG_RE.source, 'gi')
while ((match = re.exec(text)) !== null) {
const id = normalizeFilmId(match[1])
if (!ids.includes(id)) ids.push(id)
}
return ids
}
function resolveFilms(ids: string[]): Film[] {
return ids
.map((id) => mockFilms.find((f) => f.id === id))
.filter((f): f is Film => !!f)
}
function updatePanelFromText(text: string) {
const ids = extractFilmIds(text)
if (ids.length > 0) {
const films = resolveFilms(ids)
if (films.length > 0) {
panelFilms.value = films
panelOpen.value = true
panelTitle.value = films.length === 1
? films[0].title
: `${films.length} Recommended Films`
}
}
}
function stripFilmTags(text: string): string {
return text.replace(FILM_TAG_RE, '').replace(/\n{3,}/g, '\n\n').trim()
}
function openFilmDetail(film: Film) {
selectedFilm.value = film
}
function closeFilmDetail() {
selectedFilm.value = null
}
function closePanel() {
panelOpen.value = false
selectedFilm.value = null
}
function showAllFilms() {
panelFilms.value = [...mockFilms]
panelTitle.value = 'Your Film Library'
panelOpen.value = true
selectedFilm.value = null
}
return {
panelOpen,
panelFilms,
selectedFilm,
panelTitle,
extractFilmIds,
resolveFilms,
updatePanelFromText,
stripFilmTags,
openFilmDetail,
closeFilmDetail,
closePanel,
showAllFilms,
}
}