forked from DebaucheryLibrarian/traxxx
				
			
		
			
				
	
	
		
			304 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Vue
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			304 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Vue
		
	
	
		
			Executable File
		
	
	
| <template>
 | |
| 	<div class="tile">
 | |
| 		<Details :release="movie" />
 | |
| 
 | |
| 		<div class="movie">
 | |
| 			<RouterLink
 | |
| 				:to="{ name: 'movie', params: { releaseId: movie.id, releaseSlug: movie.slug } }"
 | |
| 				class="cover"
 | |
| 			>
 | |
| 				<img
 | |
| 					v-if="movie.covers[0]"
 | |
| 					:src="getPath(movie.covers[0], 'thumbnail')"
 | |
| 					:style="{ 'background-image': getBgPath(movie.covers[0], 'lazy') }"
 | |
| 					loading="lazy"
 | |
| 				>
 | |
| 
 | |
| 				<div
 | |
| 					v-else
 | |
| 					:title="movie.title"
 | |
| 					class="unavailable"
 | |
| 				><Icon icon="blocked" /></div>
 | |
| 
 | |
| 				<Icon
 | |
| 					v-show="(!stash || stash.primary) && favorited"
 | |
| 					icon="heart7"
 | |
| 					class="stash stashed"
 | |
| 					@click.prevent.native="unstashMovie"
 | |
| 				/>
 | |
| 
 | |
| 				<Icon
 | |
| 					v-show="(!stash || stash.primary) && favorited === false"
 | |
| 					icon="heart8"
 | |
| 					class="stash unstashed"
 | |
| 					@click.prevent.native="stashMovie"
 | |
| 				/>
 | |
| 
 | |
| 				<Icon
 | |
| 					v-show="stash && !stash.primary"
 | |
| 					icon="cross2"
 | |
| 					class="stash unstash"
 | |
| 					@click.prevent.native="unstashMovie"
 | |
| 				/>
 | |
| 			</RouterLink>
 | |
| 
 | |
| 			<div class="info">
 | |
| 				<RouterLink
 | |
| 					:to="{ name: 'movie', params: { releaseId: movie.id, releaseSlug: movie.slug } }"
 | |
| 					class="title-link"
 | |
| 				>
 | |
| 					<h3 class="title">{{ movie.title }}</h3>
 | |
| 				</RouterLink>
 | |
| 
 | |
| 				<ul
 | |
| 					class="actors nolist"
 | |
| 					:title="movie.actors.map(actor => actor.name).join(', ')"
 | |
| 				>
 | |
| 					<li
 | |
| 						v-for="actor in movie.actors"
 | |
| 						:key="`tag-${movie.id}-${actor.id}`"
 | |
| 						class="actor"
 | |
| 					><RouterLink
 | |
| 						:to="`/actor/${actor.id}/${actor.slug}`"
 | |
| 						class="actor-link"
 | |
| 					>{{ actor.name }}</RouterLink></li>
 | |
| 				</ul>
 | |
| 
 | |
| 				<ul
 | |
| 					class="tags nolist"
 | |
| 					:title="movie.tags.map(tag => tag.name).join(', ')"
 | |
| 				>
 | |
| 					<li
 | |
| 						v-for="tag in movie.tags"
 | |
| 						:key="`tag-${movie.id}-${tag.id}`"
 | |
| 						class="tag"
 | |
| 					><RouterLink
 | |
| 						:to="`/tag/${tag.slug}`"
 | |
| 						class="tag-link"
 | |
| 					>{{ tag.name }}</RouterLink></li>
 | |
| 				</ul>
 | |
| 			</div>
 | |
| 		</div>
 | |
| 	</div>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import Details from './tile-details.vue';
 | |
| 
 | |
| async function stashMovie() {
 | |
| 	this.favorited = true;
 | |
| 
 | |
| 	try {
 | |
| 		await this.$store.dispatch('stashMovie', {
 | |
| 			movieId: this.movie.id,
 | |
| 			stashId: this.$store.getters.favorites.id,
 | |
| 		});
 | |
| 
 | |
| 		this.$emit('stash', true);
 | |
| 	} catch (error) {
 | |
| 		this.favorited = false;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| async function unstashMovie() {
 | |
| 	if (!this.stash || this.stash.primary) {
 | |
| 		this.favorited = false;
 | |
| 	}
 | |
| 
 | |
| 	try {
 | |
| 		await this.$store.dispatch('unstashMovie', {
 | |
| 			movieId: this.movie.id,
 | |
| 			stashId: this.stash?.id || this.$store.getters.favorites.id,
 | |
| 		});
 | |
| 
 | |
| 		this.$emit('stash', false);
 | |
| 	} catch (error) {
 | |
| 		this.favorited = true;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| function sfw() {
 | |
| 	return this.$store.state.ui.sfw;
 | |
| }
 | |
| 
 | |
| export default {
 | |
| 	components: {
 | |
| 		Details,
 | |
| 	},
 | |
| 	props: {
 | |
| 		movie: {
 | |
| 			type: Object,
 | |
| 			default: null,
 | |
| 		},
 | |
| 		stash: {
 | |
| 			type: Object,
 | |
| 			default: null,
 | |
| 		},
 | |
| 	},
 | |
| 	data() {
 | |
| 		return {
 | |
| 			favorited: this.movie.isFavorited,
 | |
| 		};
 | |
| 	},
 | |
| 	computed: {
 | |
| 		sfw,
 | |
| 	},
 | |
| 	methods: {
 | |
| 		stashMovie,
 | |
| 		unstashMovie,
 | |
| 	},
 | |
| };
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
| @import 'breakpoints';
 | |
| 
 | |
| .tile {
 | |
| 	display: flex;
 | |
| 	flex-direction: column;
 | |
| 	background: var(--background);
 | |
| 	box-shadow: 0 0 3px var(--darken-weak);
 | |
| 	font-size: 0;
 | |
| 
 | |
| 	&:hover .unstashed,
 | |
| 	&:hover .unstash {
 | |
| 		fill: var(--lighten);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| .movie {
 | |
| 	display: flex;
 | |
| }
 | |
| 
 | |
| .title-link {
 | |
| 	color: var(--text);
 | |
| 	text-decoration: none;
 | |
| }
 | |
| 
 | |
| .cover {
 | |
| 	height: 16rem;
 | |
| 	width: 11.25rem;
 | |
| 	display: flex;
 | |
| 	align-items: center;
 | |
| 	justify-content: center;
 | |
| 	flex-shrink: 0;
 | |
| 	position: relative;
 | |
| 	box-shadow: 0 0 3px var(--darken-weak);
 | |
|     background-color: var(--shadow-hint);
 | |
| 
 | |
| 	img {
 | |
| 		height: 100%;
 | |
| 		width: 100%;
 | |
| 		background-position: center;
 | |
| 		background-size: cover;
 | |
| 		object-fit: cover;
 | |
| 		object-position: center;
 | |
| 	}
 | |
| 
 | |
| 	.unavailable .icon {
 | |
| 		width: 2rem;
 | |
| 		height: 2rem;
 | |
| 		fill: var(--shadow-hint);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| .info {
 | |
| 	display: flex;
 | |
| 	flex-direction: column;
 | |
| 	flex-grow: 1;
 | |
| 	overflow: hidden;
 | |
| }
 | |
| 
 | |
| .title {
 | |
| 	box-sizing: border-box;
 | |
| 	padding: 1rem;
 | |
| 	margin: 0;
 | |
| 	font-size: 1rem;
 | |
| 	white-space: nowrap;
 | |
| 	text-overflow: ellipsis;
 | |
| 	overflow: hidden;
 | |
| }
 | |
| 
 | |
| .actors {
 | |
| 	height: 0;
 | |
| 	flex-grow: 1;
 | |
| 	padding: 0 1rem;
 | |
| 	line-height: 1.5;
 | |
| 	overflow: hidden;
 | |
| }
 | |
| 
 | |
| .actor:not(:last-child)::after {
 | |
| 	content: ',';
 | |
| 	margin: 0 .25rem 0 0;
 | |
| 	font-size: 1rem;
 | |
| }
 | |
| 
 | |
| .actor-link {
 | |
| 	font-size: 1rem;
 | |
| 	color: var(--link);
 | |
| 	text-decoration: none;
 | |
| 
 | |
| 	&:hover {
 | |
| 		color: var(--primary);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| .tags {
 | |
| 	padding: .25rem 1rem;
 | |
| 	height: 1.75rem;
 | |
| 	line-height: 2;
 | |
| 	overflow: hidden;
 | |
| }
 | |
| 
 | |
| .tag {
 | |
| 	margin: 0 0 .5rem 0;
 | |
| }
 | |
| 
 | |
| .tag-link {
 | |
| 	background: var(--background);
 | |
| 	font-size: .75rem;
 | |
| 	padding: .25rem .5rem;
 | |
| 	color: var(--shadow);
 | |
| 	font-weight: bold;
 | |
| 	text-decoration: none;
 | |
| 	box-shadow: 0 0 3px var(--shadow-weak);
 | |
| 
 | |
| 	&:hover {
 | |
| 		color: var(--primary);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| .stash {
 | |
| 	width: 1.5rem;
 | |
| 	height: 1.5rem;
 | |
| 	padding: .25rem .5rem .5rem .5rem;
 | |
| 	position: absolute;
 | |
| 	top: 0;
 | |
| 	left: 0;
 | |
| 	fill: var(--lighten-weak);
 | |
| 	filter: drop-shadow(0 0 2px var(--darken));
 | |
| 
 | |
| 	&:hover.unstashed,
 | |
| 	&.stashed {
 | |
| 		fill: var(--primary);
 | |
| 	}
 | |
| 
 | |
| 	&:hover.unstash {
 | |
| 		fill: var(--text-light);
 | |
| 		filter: drop-shadow(0 0 2px var(--darken-weak));
 | |
| 	}
 | |
| }
 | |
| 
 | |
| @media(max-width: $breakpoint-kilo) {
 | |
| 	.cover {
 | |
| 		height: 12rem;
 | |
| 		width: 8.25rem;
 | |
| 	}
 | |
| 
 | |
| 	/* ensure no half actor names show */
 | |
| 	.actors {
 | |
| 		margin: 0 0 1rem 0;
 | |
| 	}
 | |
| }
 | |
| </style>
 |