mirror of
				https://github.com/mmahdium/TBW.git
				synced 2025-11-04 04:28:13 +01:00 
			
		
		
		
	Added Watch page
This commit is contained in:
		@@ -102,7 +102,7 @@ const alreadyAdded = computed(() =>
 | 
			
		||||
                 transition"
 | 
			
		||||
          @click="store.removeMovie(props.movie.imdbID)"
 | 
			
		||||
        >
 | 
			
		||||
          Delete
 | 
			
		||||
          Remove
 | 
			
		||||
        </button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
 
 | 
			
		||||
@@ -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
									
								
							
							
						
						
									
										58
									
								
								src/views/WatchView.vue
									
									
									
									
									
										Normal 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">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