feat(chat): enhance chat functionality with song integration and UI improvements

- Updated ChatHeader and ChatMessage components to support song selection and display.
- Enhanced useContentPanel to handle both film and song content, allowing for richer interactions.
- Improved FilmCard and added SongCard components for better media representation.
- Refactored environment variables for better configuration management.
- Updated .gitignore to include development chat history.

Made-with: Cursor
This commit is contained in:
Dorian
2026-03-02 18:16:04 +00:00
parent 6f79f0860d
commit 80aeefa4bf
27 changed files with 1751 additions and 143 deletions
@@ -1,25 +1,25 @@
<template>
<button
class="flex gap-3 p-2 rounded-xl transition-all duration-200 text-left w-full group"
class="flex gap-3 p-2 rounded-xl transition-all duration-200 text-left w-full group overflow-hidden"
:class="isDark
? 'hover:bg-white/5 active:bg-white/10'
: 'hover:bg-black/3 active:bg-black/5'"
: 'hover:bg-black/[0.03] active:bg-black/5'"
@click="$emit('select', film)"
>
<img
v-if="film.posterUrl"
:src="film.posterUrl"
:alt="film.title"
class="w-12 h-[72px] rounded-lg object-cover shrink-0 shadow-md"
loading="lazy"
@error="(e) => handleImgError(e, film.title, film.year)"
/>
<div
v-else
class="w-12 h-[72px] rounded-lg shrink-0 flex items-center justify-center text-lg"
:class="isDark ? 'bg-white/10' : 'bg-black/5'"
>
🎬
<div class="poster-card-sm shrink-0 w-12 aspect-[2/3] rounded-lg overflow-hidden">
<img
v-if="film.posterUrl"
:src="film.posterUrl"
:alt="film.title"
class="w-full h-full object-cover rounded-[6px] transition-transform duration-300 group-hover:scale-105"
loading="lazy"
@error="(e) => handleImgError(e, film.title, film.year)"
/>
<div
v-else
class="w-full h-full rounded-[6px]"
:class="isDark ? 'bg-white/10' : 'bg-black/5'"
/>
</div>
<div class="min-w-0 flex-1 py-0.5">
@@ -27,13 +27,19 @@
:class="isDark ? 'text-white/90' : 'text-gray-900'">{{ film.title }}</p>
<p class="text-[11px] mt-0.5"
:class="isDark ? 'text-white/40' : 'text-gray-500'">
{{ film.year }} · {{ film.director }}
{{ film.year }}<template v-if="film.director"> · {{ film.director }}</template>
</p>
<div class="flex items-center gap-1.5 mt-1.5">
<span class="text-[10px] font-semibold px-1.5 py-0.5 rounded"
<span v-if="film.rating > 0"
class="text-[10px] font-semibold px-1.5 py-0.5 rounded"
:class="ratingClass">
{{ film.rating }}
</span>
<span v-if="isExternal"
class="text-[9px] px-1.5 py-0.5 rounded font-medium"
:class="isDark ? 'bg-info/15 text-info/70' : 'bg-info/10 text-blue-600'">
not in library
</span>
<span
v-for="src in film.sources.slice(0, 3)"
:key="src.type"
@@ -58,6 +64,8 @@ defineEmits<{ select: [film: Film] }>()
const { isDark } = useTheme()
const isExternal = computed(() => props.film.id.startsWith('ext-'))
const ratingClass = computed(() => {
const r = props.film.rating
if (r >= 8.5) return isDark.value ? 'bg-success/20 text-success' : 'bg-success/10 text-green-700'