Skip to content
Snippets Groups Projects

Profile view implemented, watchlist view and component implemented with a...

Merged Nallani, Abhishikth (UG - Comp Sci & Elec Eng) requested to merge top-rated into movie-details
11 files
+ 723
17
Compare changes
  • Side-by-side
  • Inline
Files
11
  • # Conflicts:
    #   movie-group-8/.env
    #   movie-group-8/package-lock.json
    #   movie-group-8/package.json
    #   movie-group-8/src/App.vue
    #   movie-group-8/src/components/TopRatedMovies.vue
    #   movie-group-8/src/router/index.js
    #   movie-group-8/src/views/Films.vue
    #   movie-group-8/src/views/Login.vue
    #   movie-group-8/src/views/Profile.vue
    #   movie-group-8/src/views/Watchlist.vue
    #   movie-group-8/vite.config.js
+ 120
0
<template>
<div class="movie-list">
<div v-if="!movies.length" class="no-results">
<slot name="empty">No movies found.</slot>
</div>
<ul v-else class="movies">
<li v-for="movie in movies" :key="movie.id" class="movie-item">
<router-link
:to="{ name: 'FilmDetails', params: { id: movie.id } }"
class="movie-link"
>
<img
v-if="movie.poster_path"
:src="getPosterUrl(movie.poster_path)"
:alt="`${movie.title} poster`"
class="poster"
/>
<div class="details">
<h2 class="title">{{ movie.title }}</h2>
<p class="release-date">{{ formatDate(movie.release_date) }}</p>
<p class="overview">{{ movie.overview || 'No overview available.' }}</p>
</div>
</router-link>
</li>
</ul>
</div>
</template>
<script setup>
import { defineProps } from 'vue'
const props = defineProps({
movies: {
type: Array,
required: true
}
})
// TMDB image base URL from Vite env or fallback
const IMAGE_BASE = import.meta.env.VITE_TMDB_IMAGE_BASE || 'https://image.tmdb.org/t/p/w200'
/**
* Build full poster URL
*/
function getPosterUrl(path) {
return `${IMAGE_BASE}${path}`
}
/**
* Format a date string to a more readable form
*/
function formatDate(dateString) {
if (!dateString) return 'Unknown'
const options = { year: 'numeric', month: 'long', day: 'numeric' }
return new Date(dateString).toLocaleDateString(undefined, options)
}
</script>
<style scoped>
.movie-list {
display: flex;
flex-direction: column;
}
.no-results {
text-align: center;
color: #666;
font-style: italic;
}
.movies {
list-style: none;
padding: 0;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}
.movie-item {
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
display: flex;
flex-direction: column;
}
.poster {
width: 100%;
object-fit: cover;
aspect-ratio: 2 / 3;
}
.details {
padding: 0.75rem;
display: flex;
flex-direction: column;
flex-grow: 1;
}
.title {
font-size: 1.1rem;
margin: 0 0 0.5rem;
}
.release-date {
font-size: 0.875rem;
color: #888;
margin: 0 0 0.5rem;
}
.overview {
font-size: 0.9rem;
color: #444;
flex-grow: 1;
}
</style>
Loading