diff --git a/movie-group-8/src/views/FilmDetails.vue b/movie-group-8/src/views/FilmDetails.vue index ebc1be66bed09a4459ba2f28e3a0edf377d69d5b..c3efd77e48c6cf4b1e4a565348fa537e5097503e 100644 --- a/movie-group-8/src/views/FilmDetails.vue +++ b/movie-group-8/src/views/FilmDetails.vue @@ -1,69 +1,94 @@ <template> - <div class="film-details"> - <button class="back-button" @click="$router.back()">↠Back</button> - - <div v-if="loading" class="loading">Loading movie...</div> - <div v-else-if="error" class="error">Error: {{ error }}</div> - - <div v-else class="details-container"> - <div class="poster-container"> - <img - v-if="movie.poster_path" - :src="`https://image.tmdb.org/t/p/w500${movie.poster_path}`" - :alt="`${movie.title} poster`" - class="poster" - /> - </div> + <div class="min-h-screen bg-neutral-900 p-6"> + <div class="max-w-[85rem] mx-auto"> + <button class="text-neutral-300 mb-4 hover:underline" @click="$router.back()">↠Back</button> + + <div v-if="loading" class="text-center text-neutral-400 text-lg">Loading movie...</div> + <div v-else-if="error" class="text-center text-red-500 text-lg">Error: {{ error }}</div> + + <div v-else class="bg-neutral-800 rounded-xl shadow-md p-6 md:p-10 space-y-10"> + <!-- Poster & Trailer Card Layout --> + <div class="flex flex-col lg:flex-row gap-6"> + <!-- Poster --> + <div class="w-full lg:w-1/3 flex justify-center items-start"> + <img + v-if="movie.poster_path" + :src="`https://image.tmdb.org/t/p/w500${movie.poster_path}`" + :alt="`${movie.title} poster`" + class="rounded-xl max-h-[473px] object-contain bg-neutral-700 p-2" + /> + </div> + + <!-- Trailer --> + <div class="w-full lg:w-2/3"> + <div + v-if="trailerUrl" + class="aspect-video w-full rounded-xl overflow-hidden bg-black" + > + <iframe + :src="trailerUrl" + class="w-full h-full" + frameborder="0" + allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" + allowfullscreen + ></iframe> + </div> + </div> + </div> - <div class="info-container"> - <h1 class="title">{{ movie.title }}</h1> - <p class="release-date">{{ formatDate(movie.release_date) }}</p> - <p class="overview">{{ movie.overview }}</p> - - <div v-if="trailerUrl" class="trailer"> - <h2>Trailer</h2> - <iframe - :src="trailerUrl" - frameborder="0" - allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" - allowfullscreen - ></iframe> + + <!-- Title and Watchlist --> + <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4"> + <h1 class="text-3xl font-bold text-neutral-200">{{ movie.title }}</h1> + <button + type="button" + @click="toggleWatchlist" + class="px-5 py-2 rounded-xl font-medium transition duration-300" + :class="isInWatchlist + ? 'bg-red-600 hover:bg-red-700' + : 'bg-green-600 hover:bg-green-700'" + > + {{ isInWatchlist ? 'Remove from Watchlist' : 'Add to Watchlist' }} + </button> </div> - <button - type="button" - @click="toggleWatchlist" - class="mt-4 px-4 py-2 rounded text-white transition" - :class="isInWatchlist - ? 'bg-red-600 hover:bg-red-700' - : 'bg-green-600 hover:bg-green-700'" - > - {{ isInWatchlist ? 'Remove from Watchlist' : 'Add to Watchlist' }} - </button> + <!-- Overview --> + <div> + <p class="text-neutral-400 text-sm mb-1">Released: {{ formatDate(movie.release_date) }}</p> + <p class="text-neutral-300 leading-relaxed">{{ movie.overview }}</p> + </div> + <!-- Review Button --> <RouterLink :to="{ name: 'ReviewFilm', params: { id: movie.id } }" - class="mt-2 inline-block px-4 py-2 bg-blue-600 rounded text-white hover:bg-blue-700 text-center" + class="inline-block bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-lg transition duration-300" > Review this Film </RouterLink> - <div class="mt-6 reviews-section"> - <h2 class="text-xl mb-2 text-white">User Reviews</h2> - <div v-if="reviewsLoading" class="text-gray-400">Loading reviews…</div> - <div v-else-if="!reviews.length" class="text-gray-400">No reviews yet.</div> + + <!-- Reviews --> + <div> + <h2 class="text-2xl font-semibold text-neutral-200 mb-4">User Reviews</h2> + <div v-if="reviewsLoading" class="text-neutral-400">Loading reviews…</div> + <div v-else-if="!reviews.length" class="text-neutral-500">No reviews yet.</div> <ul v-else class="space-y-4"> - <li v-for="(r, i) in reviews" :key="i" class="bg-neutral-800 p-4 rounded"> + <li + v-for="(r, i) in reviews" + :key="i" + class="bg-neutral-700 p-4 rounded-lg" + > <div class="flex items-center mb-2"> <img - v-if="r.authorPFP" - :src="r.authorPFP" + v-if="r.authorPFP" + :src="r.authorPFP" alt="" - class="h-8 w-8 rounded-full mr-2"/> - <span class="font-semibold text-white">{{ r.authorName }}</span> - <span class="text-gray-400 ml-2">{{ r.rating }}★</span> - </div> - <p class="text-gray-200">{{ r.text }}</p> - </li> + class="h-8 w-8 rounded-full mr-2" + /> + <span class="font-semibold text-neutral-100">{{ r.authorName }}</span> + <span class="text-yellow-400 ml-2">{{ r.rating }}★</span> + </div> + <p class="text-neutral-300">{{ r.text }}</p> + </li> </ul> </div> </div> @@ -71,13 +96,14 @@ </div> </template> + <script setup> import { ref, onMounted } from 'vue' import { useRoute } from 'vue-router' import { useWatchlist } from '@/composables/useWatchlist.js' import { getAuth } from 'firebase/auth' import { getFirestore, doc, getDoc } from 'firebase/firestore' -import { getAllReviews } from '@/composables/useReviews.js' +import { getAllReviews } from '@/composables/useReviews.js' const route = useRoute() const movie = ref(null) @@ -146,81 +172,3 @@ onMounted(async () => { loading.value = false }) </script> - -<style scoped> -.film-details { - background-color: #121212; - color: #ffffff; - min-height: 100vh; - padding: 2rem; - box-sizing: border-box; -} - -.back-button { - color: #ffffff; - background: transparent; - margin-bottom: 1rem; - font-size: 1rem; -} - -.loading, -.error { - color: #ffffff; - text-align: center; - margin: 2rem 0; -} - -.details-container { - display: flex; - flex-wrap: wrap; - gap: 2rem; - background-color: #1e1e1e; - padding: 2rem; - border-radius: 8px; - max-width: 900px; - margin: 2rem auto 0; -} - -.poster-container { - flex: 0 0 300px; -} - -.poster { - width: 100%; - border-radius: 4px; -} - -.info-container { - flex: 1; - display: flex; - flex-direction: column; -} - -.title { - font-size: 2rem; - margin: 0 0 0.5rem; -} - -.release-date { - color: #bbbbbb; - margin-bottom: 1rem; -} - -.overview { - color: #dddddd; - line-height: 1.6; - margin-bottom: 1.5rem; -} - -.trailer h2 { - margin-bottom: 0.5rem; - color: #ffffff; -} - -.trailer iframe { - width: 100%; - height: 300px; - border-radius: 8px; - border: none; -} -</style> diff --git a/movie-group-8/src/views/Profile.vue b/movie-group-8/src/views/Profile.vue index 50eed15283f6142cc70917aed1a7392ff4047ce2..82b407c6e273574d57f0ec052e24a81383069817 100644 --- a/movie-group-8/src/views/Profile.vue +++ b/movie-group-8/src/views/Profile.vue @@ -1,20 +1,19 @@ <template> <div class="min-h-screen bg-gray-100 dark:bg-neutral-900 text-center px-4 py-8 pt-20"> - <div class="text-center mb-10"> + <div class="bg-neutral-800 border border-neutral-700 text-center max-w-2xl mx-auto p-6 rounded-2xl shadow mb-10"> <img v-if="userPhotoURL" :src="userPhotoURL" alt="Profile Picture" - class="w-28 h-28 mx-auto rounded-full object-cover mb-4" + class="w-24 h-24 mx-auto rounded-full object-cover mb-4 border-2 border-white" /> - <h1 class="text-3xl font-bold text-gray-800 dark:text-white">{{ displayName || 'Anonymous' }}</h1> - <p class="text-sm text-gray-600 dark:text-neutral-400">{{ userEmail }}</p> - <p class="mt-2 text-base text-gray-600 dark:text-neutral-400">{{ description }}</p> - + <h1 class="text-2xl font-bold text-white">{{ displayName || 'Anonymous' }}</h1> + <p class="text-sm text-neutral-400">{{ userEmail }}</p> + <p class="mt-2 text-base text-neutral-400">{{ description }}</p> <router-link to="/settings" - class="mt-4 inline-block px-5 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition" - > + class="mt-4 inline-block px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition" + > Edit Profile </router-link> </div> @@ -56,10 +55,10 @@ :key="tab" @click="activeTab = tab" :class="[ - 'px-4 py-2 rounded-lg text-sm font-medium', + 'px-5 py-2 rounded-full text-sm font-medium transition', activeTab === tab - ? 'bg-blue-600 text-white' - : 'bg-white dark:bg-neutral-700 text-gray-800 dark:text-white border border-gray-300 dark:border-neutral-600' + ? 'bg-white text-black dark:bg-white dark:text-black' + : 'bg-neutral-700 text-white hover:bg-neutral-600' ]" > {{ tab.charAt(0).toUpperCase() + tab.slice(1) }} @@ -67,21 +66,39 @@ </div> <!-- Tab Content --> - <div v-if="activeTab === 'watchlist'" class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"> + <div v-if="activeTab === 'watchlist'" class="grid gap-4 sm:grid-cols-2 lg:grid-cols-5 xl:grid-cols-5"> <router-link v-for="movie in watchlist" :key="movie.id" :to="`/films/${movie.id}`" - class="block bg-white dark:bg-neutral-800 border dark:border-neutral-700 rounded-lg p-3 hover:opacity-90 transition" + class="rounded-xl overflow-hidden border border-neutral-700 bg-neutral-800 shadow hover:brightness-110 transition flex flex-col" > - <img - v-if="movie.poster_path" - :src="'https://image.tmdb.org/t/p/w342' + movie.poster_path" - alt="Poster" - class="w-full h-60 object-cover rounded mb-3" - /> - <p class="font-semibold text-gray-800 dark:text-white">{{ movie.title }}</p> - <p class="text-sm text-gray-600 dark:text-neutral-400">â {{ movie.vote_average }} — {{ movie.status }}</p> + <div class="rounded-t-xl overflow-hidden"> + <img + v-if="movie.poster_path" + :src="'https://image.tmdb.org/t/p/w342' + movie.poster_path" + alt="Poster" + class="w-full object-contain" + /> + </div> + + <div class="p-3 flex flex-col grow"> + <p class="text-base font-semibold text-white">{{ movie.title }}</p> + <p class="mt-1 text-sm text-neutral-400 line-clamp-3"> + {{ movie.overview }} + </p> + + <div class="mt-auto flex justify-between items-center border-t border-neutral-700 pt-2 mt-3"> + <span class="text-sm font-semibold text-blue-400"> + â {{ movie.vote_average.toFixed(1) }} + </span> + <span + class="px-3 py-1 text-xs rounded-md bg-neutral-700 text-white border border-neutral-600" + > + {{ movie.status === 'planned' ? 'Planned' : 'Watched' }} + </span> + </div> + </div> </router-link> </div> diff --git a/movie-group-8/src/views/UserProfile.vue b/movie-group-8/src/views/UserProfile.vue index e3b650ebab1cd98051851e8b453fffa22cf2fe62..4f27064b33ef8556084dbb04cd19fef2e8c508fe 100644 --- a/movie-group-8/src/views/UserProfile.vue +++ b/movie-group-8/src/views/UserProfile.vue @@ -1,6 +1,6 @@ <template> <div class="min-h-screen bg-gray-100 dark:bg-neutral-900 p-6"> - <div class="text-center mb-10"> + <div class="text-center mt-16 mb-10"> <img v-if="user.photoURL" :src="user.photoURL"