mirror of
https://github.com/mmahdium/TBW.git
synced 2026-08-14 16:22:48 +03:30
Added Watch page
This commit is contained in:
@@ -102,7 +102,7 @@ const alreadyAdded = computed(() =>
|
|||||||
transition"
|
transition"
|
||||||
@click="store.removeMovie(props.movie.imdbID)"
|
@click="store.removeMovie(props.movie.imdbID)"
|
||||||
>
|
>
|
||||||
Delete
|
Remove
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -17,83 +17,98 @@ const alreadyAdded = computed(() =>
|
|||||||
<template>
|
<template>
|
||||||
<ErrorAlert v-if="props.movie?.Error" :message="props.movie.ErrorMessage" />
|
<ErrorAlert v-if="props.movie?.Error" :message="props.movie.ErrorMessage" />
|
||||||
|
|
||||||
|
<!-- Loading state -->
|
||||||
|
<div v-if="props.movie === undefined" class="flex justify-center items-center">
|
||||||
|
<span class="loading loading-ring loading-lg text-primary"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Loading state -->
|
<!-- Hero content -->
|
||||||
<div v-if="props.movie === undefined" class="flex justify-center items-center">
|
<div
|
||||||
<span class="loading loading-ring loading-lg text-primary"></span>
|
v-else
|
||||||
</div>
|
class="flex flex-col lg:flex-row gap-12 items-center max-w-6xl w-full bg-white/70 backdrop-blur-md border border-gray-200/60 shadow-md rounded-xl p-8 transition"
|
||||||
|
v-motion-fade-visible-once
|
||||||
|
>
|
||||||
|
<!-- Poster -->
|
||||||
|
<figure class="flex-shrink-0">
|
||||||
|
<span v-if="!imageLoaded" class="loading loading-ring loading-lg text-primary"></span>
|
||||||
|
<img
|
||||||
|
v-show="imageLoaded"
|
||||||
|
:src="props.movie.Poster"
|
||||||
|
alt="Poster"
|
||||||
|
class="w-full max-w-sm rounded-lg shadow-lg transform transition-transform duration-500 hover:scale-105"
|
||||||
|
@load="imageLoaded = true"
|
||||||
|
/>
|
||||||
|
</figure>
|
||||||
|
|
||||||
<!-- Hero content -->
|
<!-- Text -->
|
||||||
<div
|
<div class="flex-1">
|
||||||
v-else
|
<h1 class="text-4xl font-bold text-gray-800 mb-4">
|
||||||
class="flex flex-col lg:flex-row gap-12 items-center max-w-6xl w-full
|
{{ props.movie.Title }}
|
||||||
bg-white/70 backdrop-blur-md border border-gray-200/60
|
<span class="text-gray-400 text-lg font-normal">({{ props.movie.Year }})</span>
|
||||||
shadow-md rounded-xl p-8 transition"
|
</h1>
|
||||||
v-motion-fade-visible-once
|
|
||||||
>
|
|
||||||
<!-- Poster -->
|
|
||||||
<figure class="flex-shrink-0">
|
|
||||||
<span v-if="!imageLoaded" class="loading loading-ring loading-lg text-primary"></span>
|
|
||||||
<img
|
|
||||||
v-show="imageLoaded"
|
|
||||||
:src="props.movie.Poster"
|
|
||||||
alt="Poster"
|
|
||||||
class="w-full max-w-sm rounded-lg shadow-lg transform transition-transform duration-500 hover:scale-105"
|
|
||||||
@load="imageLoaded = true"
|
|
||||||
/>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
<!-- Text -->
|
<p class="text-gray-600 leading-relaxed mb-6">{{ props.movie.Plot }}</p>
|
||||||
<div class="flex-1">
|
|
||||||
<h1 class="text-4xl font-bold text-gray-800 mb-4">
|
|
||||||
{{ props.movie.Title }}
|
|
||||||
<span class="text-gray-400 text-lg font-normal">({{ props.movie.Year }})</span>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<p class="text-gray-600 leading-relaxed mb-6">{{ props.movie.Plot }}</p>
|
<!-- Badges -->
|
||||||
|
<div class="flex flex-wrap gap-2 mb-6">
|
||||||
|
<span
|
||||||
|
class="px-3 py-1 rounded-md text-sm bg-gradient-to-r from-gray-100 to-gray-200 text-gray-700 border border-gray-300"
|
||||||
|
>
|
||||||
|
Language: {{ props.movie.Language }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="px-3 py-1 rounded-md text-sm bg-gradient-to-r from-gray-100 to-gray-200 text-gray-700 border border-gray-300"
|
||||||
|
>
|
||||||
|
Country: {{ props.movie.Country }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="px-3 py-1 rounded-md text-sm bg-gradient-to-r from-gray-100 to-gray-200 text-gray-700 border border-gray-300"
|
||||||
|
>
|
||||||
|
IMDB Rating: {{ props.movie.imdbRating }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Badges -->
|
<!-- Actions -->
|
||||||
<div class="flex flex-wrap gap-2 mb-6">
|
<div class="card-actions">
|
||||||
<span
|
<button
|
||||||
class="px-3 py-1 rounded-md text-sm
|
v-if="!alreadyAdded"
|
||||||
bg-gradient-to-r from-gray-100 to-gray-200 text-gray-700 border border-gray-300"
|
class="btn px-6 bg-gradient-to-r from-gray-100 to-gray-200 border border-gray-300 text-gray-700 hover:from-gray-200 hover:to-gray-300"
|
||||||
>
|
@click="store.addMovie(props.movie)"
|
||||||
Language: {{ props.movie.Language }}
|
>
|
||||||
</span>
|
Add to list
|
||||||
<span
|
</button>
|
||||||
class="px-3 py-1 rounded-md text-sm
|
<button
|
||||||
bg-gradient-to-r from-gray-100 to-gray-200 text-gray-700 border border-gray-300"
|
v-else
|
||||||
>
|
class="btn px-6 bg-gradient-to-r from-red-50 to-red-100 border border-red-200 text-red-600 hover:from-red-100 hover:to-red-200"
|
||||||
Country: {{ props.movie.Country }}
|
@click="store.removeMovie(props.movie.imdbID)"
|
||||||
</span>
|
>
|
||||||
<span
|
Remove from list
|
||||||
class="px-3 py-1 rounded-md text-sm
|
</button>
|
||||||
bg-gradient-to-r from-gray-100 to-gray-200 text-gray-700 border border-gray-300"
|
|
||||||
>
|
|
||||||
IMDB Rating: {{ props.movie.imdbRating }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Actions -->
|
<RouterLink
|
||||||
<div class="card-actions">
|
:to="{ name: 'watch', params: { name: props.movie.Title, id: props.movie.imdbID } }"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
v-if="!alreadyAdded"
|
class="btn relative flex items-center gap-2 px-6 bg-gradient-to-r from-indigo-500 to-violet-500 text-white border-0 shadow-md hover:opacity-90 transition"
|
||||||
class="btn px-6 bg-gradient-to-r from-gray-100 to-gray-200
|
|
||||||
border border-gray-300 text-gray-700 hover:from-gray-200 hover:to-gray-300"
|
|
||||||
@click="store.addMovie(props.movie)"
|
|
||||||
>
|
>
|
||||||
Add to list
|
<!-- Icon -->
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-5 w-5"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M6.5 5.5a1 1 0 0 1 1.52-.85l6 4.5a1 1 0 0 1 0 1.7l-6 4.5A1 1 0 0 1 6.5 14.5v-9z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>Watch</span>
|
||||||
|
<span class="badge badge-sm badge-secondary absolute -top-2 -right-2">Beta</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
</RouterLink>
|
||||||
v-else
|
|
||||||
class="btn px-6 bg-gradient-to-r from-red-50 to-red-100
|
|
||||||
border border-red-200 text-red-600 hover:from-red-100 hover:to-red-200"
|
|
||||||
@click="store.removeMovie(props.movie.imdbID)"
|
|
||||||
>
|
|
||||||
Remove from list
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import NotFoundView from '@/views/NotFoundView.vue'
|
|||||||
import ListView from '@/views/ListView.vue'
|
import ListView from '@/views/ListView.vue'
|
||||||
import DetailsView from '@/views/DetailsView.vue'
|
import DetailsView from '@/views/DetailsView.vue'
|
||||||
import AddView from '@/views/AddView.vue'
|
import AddView from '@/views/AddView.vue'
|
||||||
|
import WatchView from '@/views/WatchView.vue'
|
||||||
|
|
||||||
const routes: RouteRecordRaw[] = [
|
const routes: RouteRecordRaw[] = [
|
||||||
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFoundView },
|
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFoundView },
|
||||||
@@ -27,6 +28,11 @@ const routes: RouteRecordRaw[] = [
|
|||||||
name: 'add',
|
name: 'add',
|
||||||
component: AddView,
|
component: AddView,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/watch/:name/:id',
|
||||||
|
name: 'watch',
|
||||||
|
component: WatchView,
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const movieId = ref(route.params.id as string)
|
||||||
|
const movieName = ref(route.params.name as string)
|
||||||
|
const isLoaded = ref(false)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// You could add extra logic here if needed
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="flex justify-center min-h-auto px-4 py-12 bg-gradient-to-b from-gray-50 to-white"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="w-full max-w-6xl bg-white/70 backdrop-blur-md border border-gray-200/60
|
||||||
|
shadow-md rounded-xl p-4 lg:p-8 transition flex flex-col items-center"
|
||||||
|
v-motion-fade-visible-once
|
||||||
|
>
|
||||||
|
<!-- Title with Experimental badge -->
|
||||||
|
<div class="flex items-center gap-3 mb-6">
|
||||||
|
<h1 class="text-3xl font-bold text-gray-700">
|
||||||
|
Watch
|
||||||
|
<span class="bg-gradient-to-r from-indigo-500 to-cyan-400 bg-clip-text text-transparent">
|
||||||
|
{{ movieName }}
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
<span class="badge badge-warning">Experimental</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Loading spinner -->
|
||||||
|
<div v-if="!isLoaded" class="flex justify-center items-center h-64 w-full">
|
||||||
|
<span class="loading loading-ring loading-lg text-primary"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Responsive iframe -->
|
||||||
|
<div v-show="isLoaded" class="w-full aspect-video rounded-lg overflow-hidden shadow-lg">
|
||||||
|
<iframe
|
||||||
|
:src="'https://vidlink.pro/movie/' + movieId"
|
||||||
|
frameborder="0"
|
||||||
|
allowfullscreen
|
||||||
|
class="w-full h-full"
|
||||||
|
@load="isLoaded = true"
|
||||||
|
></iframe>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Disclaimer -->
|
||||||
|
<p class="mt-6 text-sm text-gray-500 text-center max-w-2xl">
|
||||||
|
⚠️ This player is provided by a <span class="font-semibold">third‑party service</span>.
|
||||||
|
Ads and pop‑ups may appear, and I do not control or endorse them.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
Reference in New Issue
Block a user