Added Watch page

This commit is contained in:
2025-10-21 21:30:24 +03:30
parent 8e5249ab99
commit 1652d96859
4 changed files with 148 additions and 69 deletions

View File

@@ -102,7 +102,7 @@ const alreadyAdded = computed(() =>
transition"
@click="store.removeMovie(props.movie.imdbID)"
>
Delete
Remove
</button>
</div>
</div>

View File

@@ -17,83 +17,98 @@ const alreadyAdded = computed(() =>
<template>
<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 -->
<div v-if="props.movie === undefined" class="flex justify-center items-center">
<span class="loading loading-ring loading-lg text-primary"></span>
</div>
<!-- Hero content -->
<div
v-else
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 -->
<div
v-else
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>
<!-- Text -->
<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>
<!-- Text -->
<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>
<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 -->
<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>
<!-- Actions -->
<div class="card-actions">
<button
v-if="!alreadyAdded"
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
</button>
<button
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>
<!-- Actions -->
<div class="card-actions">
<RouterLink
:to="{ name: 'watch', params: { name: props.movie.Title, id: props.movie.imdbID } }"
>
<button
v-if="!alreadyAdded"
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)"
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"
>
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
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>
</RouterLink>
</div>
</div>
</div>
</template>

View File

@@ -4,6 +4,7 @@ import NotFoundView from '@/views/NotFoundView.vue'
import ListView from '@/views/ListView.vue'
import DetailsView from '@/views/DetailsView.vue'
import AddView from '@/views/AddView.vue'
import WatchView from '@/views/WatchView.vue'
const routes: RouteRecordRaw[] = [
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFoundView },
@@ -27,6 +28,11 @@ const routes: RouteRecordRaw[] = [
name: 'add',
component: AddView,
},
{
path: '/watch/:name/:id',
name: 'watch',
component: WatchView,
}
]
const router = createRouter({

58
src/views/WatchView.vue Normal file
View File

@@ -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">thirdparty service</span>.
Ads and popups may appear, and I do not control or endorse them.
</p>
</div>
</div>
</template>