2026-05-24 22:35:13 +07:00
< script setup lang = "ts" >
2026-05-17 22:47:43 +07:00
import { ChevronDown , Heart , Play , Plus , Share2 , Star } from 'lucide-vue-next'
2026-05-17 21:01:33 +07:00
2026-05-17 20:30:19 +07:00
const route = useRoute ()
2026-05-24 22:35:13 +07:00
const requestedSource = computed (() => String ( route . query . source || 'nguonc' ))
2026-05-23 15:08:57 +07:00
const requestedSources = computed (() => typeof route . query . srcs === 'string' ? route . query . srcs : '' )
2026-05-17 20:30:19 +07:00
const selectedServer = ref ( 0 )
2026-05-17 22:47:43 +07:00
const movieInfoOpen = ref ( false )
2026-05-18 14:51:01 +07:00
const activeTab = ref < 'episodes' | 'actors' > ( 'episodes' )
2026-05-21 10:15:02 +07:00
const isFavoriteMovie = ref ( false )
const actionMessage = ref ( '' )
const actionBusy = ref ( false )
const { user , initAuth } = useSupabaseAuth ()
const {
isFavorite ,
saveFavorite ,
removeFavorite ,
saveWatchLater ,
} = useMovieLibrary ()
2026-05-17 20:30:19 +07:00
2026-05-18 14:51:01 +07:00
const { data : movie , pending , error } = await useFetch (() => `/api/movies/ ${ route . params . slug } ` , {
query : computed (() => ({
source : requestedSource . value ,
2026-05-23 15:08:57 +07:00
srcs : requestedSources . value || undefined ,
2026-05-18 14:51:01 +07:00
})),
2026-05-23 15:08:57 +07:00
watch : [ requestedSource , requestedSources ],
2026-05-17 20:30:19 +07:00
})
const servers = computed (() => movie . value ? . servers ?? [])
const activeServer = computed (() => servers . value [ selectedServer . value ])
2026-05-24 22:35:13 +07:00
const activeSource = computed (() => String ( activeServer . value ? . source || movie . value ? . source || route . query . source || 'nguonc' ))
2026-05-23 15:08:57 +07:00
const activeSourceSlug = computed (() => String ( activeServer . value ? . sourceSlug || movie . value ? . slug || route . params . slug ))
const activeSourceServerIndex = computed (() => Number ( activeServer . value ? . sourceServerIndex ?? 0 ))
const sourceOptions = computed (() =>
( movie . value ? . sources || [{ source : activeSource . value , slug : activeSourceSlug . value }])
. map (( source : any ) => ({
label : String ( source . source || '' ). toUpperCase (),
value : source . source ,
slug : source . slug ,
}))
. filter (( source : any ) => source . value && source . slug ),
)
2026-05-18 14:51:01 +07:00
const actors = computed (() => movie . value ? . actors ?? [])
const actorSummary = computed (() => actors . value . map (( actor : any ) => actor . name ). filter ( Boolean ). slice ( 0 , 6 ). join ( ', ' ))
2026-05-17 21:01:33 +07:00
const firstWatchLink = computed (() => ({
2026-05-23 15:08:57 +07:00
path : `/xem/ ${ activeSourceSlug . value } ` ,
2026-05-17 21:01:33 +07:00
query : {
2026-05-18 14:51:01 +07:00
source : activeSource . value ,
2026-05-23 15:08:57 +07:00
srcs : requestedSources . value || undefined ,
server : activeSourceServerIndex . value ,
2026-05-17 21:01:33 +07:00
ep : 1 ,
},
}))
2026-05-17 20:30:19 +07:00
const episodeCount = computed (() => servers . value . reduce (( total : number , server : any ) => total + ( server . episodes ? . length || 0 ), 0 ))
2026-05-21 10:15:02 +07:00
const libraryItem = computed (() => {
if ( ! movie . value ) return null
return {
source : activeSource . value ,
2026-05-23 15:08:57 +07:00
slug : activeSourceSlug . value ,
2026-05-21 10:15:02 +07:00
name : movie . value . name ,
originName : movie . value . originName ,
thumb : movie . value . thumb ,
poster : movie . value . poster ,
updatedAt : Date . now (),
}
})
2026-05-17 20:30:19 +07:00
2026-05-17 21:01:33 +07:00
function episodeLink ( index : number ) {
return {
2026-05-23 15:08:57 +07:00
path : `/xem/ ${ activeSourceSlug . value } ` ,
2026-05-17 21:01:33 +07:00
query : {
2026-05-18 14:51:01 +07:00
source : activeSource . value ,
2026-05-23 15:08:57 +07:00
srcs : requestedSources . value || undefined ,
server : activeSourceServerIndex . value ,
2026-05-17 21:01:33 +07:00
ep : index + 1 ,
},
}
}
2026-05-17 20:30:19 +07:00
2026-05-18 14:51:01 +07:00
function sourceLink ( source : string ) {
2026-05-23 15:08:57 +07:00
const ref = sourceOptions . value . find (( item : any ) => item . value === source )
2026-05-18 14:51:01 +07:00
return {
2026-05-23 15:08:57 +07:00
path : `/phim/ ${ ref ? . slug || route . params . slug } ` ,
query : {
source ,
srcs : requestedSources . value || undefined ,
},
2026-05-18 14:51:01 +07:00
}
}
2026-05-23 15:08:57 +07:00
function serverLabel ( server : any , index : number ) {
const label = String ( server ? . name || '' ). replace ( /^(ophim|nguonc|kkphim)\s*-\s*/i , '' ). trim ()
return label || `Server ${ index + 1 } `
}
2026-05-18 14:51:01 +07:00
function formatEpisodeName ( name : string , index : number ) {
const label = String ( name || index + 1 ). trim ()
return /^\d+$/ . test ( label ) ? `Tập ${ label } ` : label
}
function actorInitial ( name : string ) {
return name . trim (). charAt ( 0 ). toUpperCase ()
}
2026-05-21 10:15:02 +07:00
function flashActionMessage ( message : string ) {
actionMessage . value = message
window . setTimeout (() => {
if ( actionMessage . value === message ) actionMessage . value = ''
}, 2200 )
}
async function refreshFavoriteState () {
if ( ! libraryItem . value ) return
isFavoriteMovie . value = await isFavorite ( libraryItem . value )
}
async function toggleFavorite () {
if ( ! libraryItem . value || actionBusy . value ) return
actionBusy . value = true
if ( isFavoriteMovie . value ) {
await removeFavorite ( libraryItem . value )
isFavoriteMovie . value = false
flashActionMessage ( 'Đã bỏ khỏi yêu thích.' )
} else {
await saveFavorite ( libraryItem . value )
isFavoriteMovie . value = true
flashActionMessage ( user . value ? 'Đã lưu vào yêu thích.' : 'Đã lưu yêu thích trên thiết bị này.' )
}
actionBusy . value = false
}
async function addToWatchLater () {
if ( ! libraryItem . value || actionBusy . value ) return
actionBusy . value = true
await saveWatchLater ( libraryItem . value )
actionBusy . value = false
flashActionMessage ( user . value ? 'Đã thêm vào danh sách xem sau.' : 'Đã thêm vào danh sách xem sau trên thiết bị này.' )
}
async function shareMovie () {
if ( ! import . meta . client || ! movie . value ) return
const shareUrl = window . location . href
2026-05-24 22:35:13 +07:00
const shareTitle = ` ${ movie . value . name } - CineK`
2026-05-21 10:15:02 +07:00
try {
if ( navigator . share ) {
await navigator . share ({
title : shareTitle ,
text : movie . value . originName || movie . value . name ,
url : shareUrl ,
})
return
}
await navigator . clipboard . writeText ( shareUrl )
flashActionMessage ( 'Đã copy link phim.' )
} catch {
flashActionMessage ( 'Chưa chia sẻ được, bạn thử lại nhé.' )
}
}
onMounted ( async () => {
await initAuth ()
await refreshFavoriteState ()
})
2026-05-18 14:51:01 +07:00
watch ( requestedSource , () => {
selectedServer . value = 0
})
2026-05-23 15:08:57 +07:00
watch ( requestedSources , () => {
selectedServer . value = 0
})
2026-05-21 10:15:02 +07:00
watch ([ libraryItem , user ], () => {
refreshFavoriteState ()
})
2026-05-17 20:30:19 +07:00
useHead (() => ({
2026-05-24 22:35:13 +07:00
title : movie . value ? ` ${ movie . value . name } - Xem phim online - CineK` : 'Đang tải phim - CineK' ,
2026-05-17 20:30:19 +07:00
meta : [
{
name : 'description' ,
2026-05-24 22:35:13 +07:00
content : movie . value
? `Xem thông tin phim ${ movie . value . name }${ movie . value . originName ? ` ( ${ movie . value . originName } )` : '' } , danh sách tập, diễn viên và các server xem phim tại CineK.`
: 'Xem phim Hàn Quốc online tại CineK với Vietsub, thuyết minh và lồng tiếng.' ,
},
{
property : 'og:title' ,
content : movie . value ? ` ${ movie . value . name } - CineK` : 'CineK - Xem phim Hàn Quốc online' ,
},
{
property : 'og:description' ,
content : movie . value ? . content || 'Xem thông tin phim, trailer, diễn viên và danh sách tập mới trên CineK.' ,
},
{
property : 'og:image' ,
content : movie . value ? . poster || movie . value ? . thumb || '/icon.png' ,
2026-05-17 20:30:19 +07:00
},
],
}))
</ script >
< template >
2026-05-17 21:01:33 +07:00
< main class = "min-h-screen bg-[#08090d] text-white" >
2026-05-17 20:30:19 +07:00
< AppHeader />
2026-05-17 22:47:43 +07:00
< div v-if = "pending"
class = "mx-auto grid min-h-screen max-w-390 gap-6 px-4 pt-36 sm:px-6 lg:grid-cols-[22rem_minmax(0,1fr)] lg:px-8 lg:pt-40 xl:px-10" >
< div class = "h-114 animate-pulse rounded-md bg-white/10" />
2026-05-17 21:01:33 +07:00
< div class = "h-80 animate-pulse rounded-md bg-white/10" />
2026-05-17 20:30:19 +07:00
</ div >
< div v-else-if = "error || !movie" class="mx-auto flex min-h-screen max-w-4xl items-center px-4 pt-36 lg:pt-24" >
< div >
< h1 class = "text-3xl font-black" > Không mở được phim </ h1 >
2026-05-24 22:35:13 +07:00
< p class = "mt-3 text-slate-300" > Phim có thể đang được cập nhật hoặc hiện chưa có tập xem .</ p >
2026-05-17 20:30:19 +07:00
</ div >
</ div >
< template v-else >
2026-05-17 22:47:43 +07:00
< section class = "relative overflow-hidden pt-20 lg:pt-16" >
< div class = "absolute inset-x-0 top-0 h-96 overflow-hidden sm:h-112" >
2026-05-17 21:01:33 +07:00
< img : src = "movie.poster || movie.thumb" :alt = "movie.name" class = "h-full w-full object-cover opacity-45" >
2026-05-17 22:47:43 +07:00
< div class = "absolute inset-0 bg-linear-to-b from-slate-950/25 via-[#08090d]/75 to-[#08090d]" />
< div class = "absolute inset-0 bg-linear-to-r from-[#08090d] via-transparent to-[#08090d]" />
2026-05-17 21:01:33 +07:00
</ div >
2026-05-17 20:30:19 +07:00
2026-05-18 14:51:01 +07:00
< div class = "relative mx-auto max-w-390 px-3 pb-8 pt-40 sm:px-6 sm:pb-12 sm:pt-52 lg:px-8 lg:pt-56 xl:px-10" >
2026-05-17 22:47:43 +07:00
< div class = "lg:grid lg:grid-cols-[22rem_minmax(0,1fr)] lg:gap-6" >
< aside class = "mb-3 flex flex-col items-center text-center lg:mb-6 lg:items-start lg:text-left" >
< img : src = "movie.thumb || movie.poster" :alt = "movie.name"
class = "mx-auto aspect-2/3 w-29 rounded-md object-cover shadow-xl shadow-black/40 sm:w-52 lg:w-full" >
2026-05-17 21:01:33 +07:00
2026-05-17 22:47:43 +07:00
< h1 class = "mt-4 text-[1.35rem] font-black leading-tight sm:text-2xl lg:mt-5" >{{ movie . name }}</ h1 >
2026-05-24 22:35:13 +07:00
< p v-if = "movie.originName" class="mt-1 text-sm font-bold text-slate-100 sm:text-yellow-200" >{{
2026-05-17 22:47:43 +07:00
movie.originName }}</ p >
2026-05-17 21:01:33 +07:00
2026-05-17 22:47:43 +07:00
< div class = "mt-3 hidden flex-wrap justify-center gap-2 text-xs font-black sm:flex lg:justify-start" >
< span v-if = "movie.quality" class="rounded bg-white/12 px-2 py-1" >{{ movie.quality }}</ span >
< span v-if = "movie.episode" class="rounded bg-white/12 px-2 py-1" >{{ movie.episode }}</ span >
< span v-if = "movie.time" class="rounded bg-white/12 px-2 py-1" >{{ movie.time }}</ span >
< span v-if = "movie.rating" class="inline-flex items-center gap-1 rounded bg-white/12 px-2 py-1" >
2026-05-24 22:35:13 +07:00
< Star class = "size-3 fill-yellow-300 text-yellow-300" />
2026-05-17 22:47:43 +07:00
{{ movie . rating . toFixed ( 1 ) }}
</ span >
2026-05-17 21:01:33 +07:00
</ div >
2026-05-17 22:47:43 +07:00
< div v-if = "movie.categories?.length" class="mt-3 hidden sm:block lg:mt-4" >
< span class = "rounded bg-white/12 px-3 py-1 text-xs font-bold" >{{ movie . categories [ 0 ] }}</ span >
2026-05-17 20:30:19 +07:00
</ div >
2026-05-17 22:47:43 +07:00
< div class = "mt-4 hidden space-y-3 text-sm leading-6 text-slate-300 sm:block lg:mt-5" >
< p v-if = "movie.content" >
< span class = "block font-black text-white" > Giới thiệu : </ span >
{{ movie . content }}
</ p >
< p >< span class = "font-black text-white" > Số tập : </ span > {{
episodeCount || movie . episode || 'Đang cập nhật'
}}</ p >
< p v-if = "movie.countries?.length"><span class="font-black text-white" > Quốc gia : </ span > {{
movie.countries.join (', ') }}</ p >
2026-05-18 14:51:01 +07:00
< p v-if = "actorSummary"><span class="font-black text-white" > Diễn viên : </ span > {{
actorSummary }}</ p >
2026-05-17 22:47:43 +07:00
</ div >
</ aside >
< section
class = "mt-0 rounded-none border-y border-white/10 bg-transparent px-0 pb-0 pt-3 shadow-none sm:mt-0 sm:rounded-md sm:border sm:bg-[#15161b]/95 sm:p-5 sm:shadow-2xl sm:shadow-black/40 lg:p-5" >
< button type = "button"
2026-05-24 22:35:13 +07:00
class = "mx-auto flex items-center gap-1 pb-3 text-sm font-bold text-yellow-200 sm:hidden"
2026-05-17 22:47:43 +07:00
:aria-expanded = "movieInfoOpen" @click ="movieInfoOpen = !movieInfoOpen" >
< span > Thông tin phim </ span >
< ChevronDown class = "size-4 transition" : class = "movieInfoOpen ? 'rotate-180' : ''" />
</ button >
< div v-if = "movieInfoOpen"
class = "mb-4 space-y-3 border-b border-white/10 pb-4 text-sm leading-6 text-slate-300 sm:hidden" >
< p v-if = "movie.content" >
< span class = "block font-black text-white" > Giới thiệu : </ span >
{{ movie . content }}
</ p >
< p >< span class = "font-black text-white" > Số tập : </ span > {{
episodeCount || movie . episode || 'Đang cập nhật'
}}</ p >
< p v-if = "movie.countries?.length"><span class="font-black text-white" > Quốc gia : </ span > {{
movie.countries.join (', ') }}</ p >
2026-05-18 14:51:01 +07:00
< p v-if = "actorSummary"><span class="font-black text-white" > Diễn viên : </ span > {{
actorSummary }}</ p >
</ div >
< div class = "hidden" >
2026-05-24 22:35:13 +07:00
< p class = "text-sm font-black text-white" > Nguồn xem </ p >
2026-05-18 14:51:01 +07:00
< div class = "flex gap-2 overflow-x-auto pb-1 sm:pb-0" >
< NuxtLink v-for = "source in sourceOptions" :key="source.value" :to="sourceLink(source.value)"
class = "shrink-0 rounded-md px-4 py-2 text-sm font-black transition"
2026-05-24 22:35:13 +07:00
: class = "activeSource === source.value ? 'bg-yellow-400 text-slate-950' : 'bg-white/10 text-white hover:bg-white/16'" >
2026-05-18 14:51:01 +07:00
{{ source . label }}
</ NuxtLink >
</ div >
2026-05-17 20:30:19 +07:00
</ div >
2026-05-17 22:47:43 +07:00
< div
2026-05-18 14:51:01 +07:00
class = "flex flex-col gap-4 border-b border-white/10 py-4 sm:flex-row sm:items-center sm:justify-between sm:py-5" >
2026-05-17 22:47:43 +07:00
< div class = "flex flex-wrap justify-center gap-3 sm:justify-start" >
< NuxtLink :to = "firstWatchLink"
2026-05-24 22:35:13 +07:00
class = "inline-flex h-12 w-full items-center justify-center gap-2 rounded-full bg-linear-to-r from-yellow-400 to-yellow-300 px-7 text-sm font-black text-slate-950 transition hover:from-yellow-300 hover:to-white sm:w-auto" >
2026-05-17 22:47:43 +07:00
< Play class = "size-4 fill-current" />
Xem Ngay
</ NuxtLink >
</ div >
2026-05-18 14:51:01 +07:00
< div class = "flex flex-col gap-3 sm:items-end" >
2026-05-23 15:08:57 +07:00
< div class = "hidden" >
2026-05-24 22:35:13 +07:00
< span class = "text-xs font-black text-slate-300" > Nguồn xem </ span >
2026-05-18 14:51:01 +07:00
< NuxtLink v-for = "source in sourceOptions" :key="source.value" :to="sourceLink(source.value)"
class = "shrink-0 rounded-md px-4 py-2 text-sm font-black transition"
2026-05-24 22:35:13 +07:00
: class = "activeSource === source.value ? 'bg-yellow-400 text-slate-950' : 'bg-white/10 text-white hover:bg-white/16'" >
2026-05-18 14:51:01 +07:00
{{ source . label }}
</ NuxtLink >
</ div >
< div class = "flex items-center justify-between gap-3 px-8 sm:justify-center sm:px-0" >
2026-05-17 22:47:43 +07:00
< button type = "button"
2026-05-24 22:35:13 +07:00
class = "flex cursor-pointer flex-col items-center gap-1 text-xs font-bold transition hover:text-yellow-200 disabled:cursor-not-allowed disabled:opacity-70"
: class = "isFavoriteMovie ? 'text-yellow-300' : 'text-white'" aria -label =" Yêu thích "
2026-05-21 10:15:02 +07:00
:disabled = "actionBusy" @click ="toggleFavorite" >
< Heart class = "size-5" : class = "isFavoriteMovie ? 'fill-current' : ''" />
< span >{{ isFavoriteMovie ? 'Đã thích' : 'Yêu thích' }}</ span >
2026-05-17 22:47:43 +07:00
</ button >
< button type = "button"
2026-05-24 22:35:13 +07:00
class = "flex cursor-pointer flex-col items-center gap-1 text-xs font-bold text-white transition hover:text-yellow-200 disabled:cursor-not-allowed disabled:opacity-70"
2026-05-21 10:15:02 +07:00
aria -label =" Thêm vào " :disabled = "actionBusy" @click ="addToWatchLater" >
2026-05-17 22:47:43 +07:00
< Plus class = "size-5" />
< span > Thêm vào </ span >
</ button >
< button type = "button"
2026-05-24 22:35:13 +07:00
class = "flex cursor-pointer flex-col items-center gap-1 text-xs font-bold text-white transition hover:text-yellow-200"
2026-05-21 10:15:02 +07:00
aria -label =" Chia sẻ " @click ="shareMovie" >
2026-05-17 22:47:43 +07:00
< Share2 class = "size-5" />
< span > Chia sẻ </ span >
</ button >
< div v-if = "movie.rating"
2026-05-24 22:35:13 +07:00
class = "inline-flex items-center gap-1.5 rounded-full bg-yellow-400 px-3 py-1.5 text-sm font-black text-slate-950" >
2026-05-17 22:47:43 +07:00
< Star class = "size-3.5 fill-current" />
{{ movie . rating . toFixed ( 1 ) }}
</ div >
</ div >
2026-05-21 10:15:02 +07:00
< p v-if = "actionMessage"
2026-05-24 22:35:13 +07:00
class = "mt-2 text-center text-xs font-bold text-yellow-200 sm:text-right" >
2026-05-21 10:15:02 +07:00
{{ actionMessage }}
</ p >
2026-05-17 22:47:43 +07:00
</ div >
2026-05-18 14:51:01 +07:00
</ div >
2026-05-17 22:47:43 +07:00
< div
class = "mt-3 flex justify-between gap-6 border-b border-white/10 px-6 text-sm font-black sm:mt-0 sm:justify-center sm:px-0 sm:pt-5" >
2026-05-18 14:51:01 +07:00
< button type = "button" class = "px-5 pb-3 sm:px-0"
2026-05-24 22:35:13 +07:00
: class = "activeTab === 'episodes' ? 'border-b-2 border-yellow-300 text-yellow-200' : 'text-slate-300'"
2026-05-18 14:51:01 +07:00
@click ="activeTab = 'episodes'" > Tập phim </ button >
< button type = "button" class = "px-5 pb-3 sm:px-0"
2026-05-24 22:35:13 +07:00
: class = "activeTab === 'actors' ? 'border-b-2 border-yellow-300 text-yellow-200' : 'text-slate-300'"
2026-05-18 14:51:01 +07:00
@click ="activeTab = 'actors'" > Diễn viên </ button >
2026-05-17 22:47:43 +07:00
</ div >
2026-05-18 14:51:01 +07:00
< div v-if = "activeTab === 'episodes'" class="px-0 pt-6 sm:px-0 sm:pt-5" >
2026-05-17 22:47:43 +07:00
< h2 class = "text-[1.08rem] font-black sm:text-xl" > Danh sách tập </ h2 >
< div v-if = "servers.length > 1" class="mt-3 flex gap-2 overflow-x-auto pb-2" >
< button v-for = "(server, index) in servers" :key="server.name" type="button"
class = "shrink-0 rounded px-4 py-2 text-sm font-black"
2026-05-24 22:35:13 +07:00
: class = "selectedServer === index ? 'bg-yellow-400 text-slate-950' : 'bg-white/10 text-white hover:bg-white/16'"
2026-05-17 22:47:43 +07:00
@click ="selectedServer = index" >
2026-05-23 15:08:57 +07:00
{{ serverLabel ( server , index ) }}
2026-05-17 22:47:43 +07:00
</ button >
</ div >
< div v-if = "activeServer?.episodes?.length"
class = "mt-3 grid grid-cols-3 gap-2 rounded-md border border-white/10 p-3 sm:grid-cols-3 lg:grid-cols-6" >
< NuxtLink v-for = "(episode, index) in activeServer.episodes" :key="`${episode.name}-${index}`"
:to = "episodeLink(index)"
2026-05-24 22:35:13 +07:00
class = "rounded-md bg-white/10 px-4 py-3 text-center text-sm font-black text-white transition first:bg-yellow-400 first:text-slate-950 hover:bg-yellow-400 hover:text-slate-950" >
2026-05-18 14:51:01 +07:00
{{ formatEpisodeName ( episode . name , index ) }}
2026-05-17 22:47:43 +07:00
</ NuxtLink >
</ div >
< p v-else class = "mt-4 rounded-md border border-white/10 bg-slate-900/70 p-4 text-sm text-slate-300" >
2026-05-24 22:35:13 +07:00
Chưa có tập xem từ server này .
2026-05-17 22:47:43 +07:00
</ p >
</ div >
2026-05-18 14:51:01 +07:00
< div v-else class = "px-0 pt-6 sm:px-0 sm:pt-5" >
< h2 class = "text-[1.08rem] font-black sm:text-xl" > Diễn viên </ h2 >
< div v-if = "actors.length" class="mt-4 grid gap-3 sm:grid-cols-2 xl:grid-cols-3" >
< div v-for = "actor in actors" :key="actor.name"
class = "flex min-w-0 items-center gap-3 rounded-md border border-white/10 bg-white/5 p-3" >
< img v-if = "actor.avatar" :src="actor.avatar" :alt="actor.name"
class = "size-14 shrink-0 rounded-md object-cover" >
< div v-else
2026-05-24 22:35:13 +07:00
class = "grid size-14 shrink-0 place-items-center rounded-md bg-yellow-400/18 text-lg font-black text-yellow-100 ring-1 ring-yellow-300/20" >
2026-05-18 14:51:01 +07:00
{{ actorInitial ( actor . name ) }}
</ div >
< div class = "min-w-0" >
< p class = "truncate text-sm font-black text-white" >{{ actor . name }}</ p >
2026-05-24 22:35:13 +07:00
< p class = "mt-1 truncate text-xs font-semibold text-yellow-200" >
2026-05-18 14:51:01 +07:00
{{ actor . originalName || 'Tên quốc tế đang cập nhật' }}
</ p >
< p class = "mt-1 truncate text-xs font-semibold text-slate-400" >
{{ actor . role || 'Vai diễn đang cập nhật' }}
</ p >
</ div >
</ div >
</ div >
< p v-else class = "mt-4 rounded-md border border-white/10 bg-slate-900/70 p-4 text-sm text-slate-300" >
2026-05-24 22:35:13 +07:00
Mục này chưa có dữ liệu diễn viên .
2026-05-18 14:51:01 +07:00
</ p >
</ div >
2026-05-17 22:47:43 +07:00
</ section >
</ div >
2026-05-17 20:30:19 +07:00
</ div >
</ section >
</ template >
</ main >
</ template >