<template> <div v-if="actor" class="content actor" > <FilterBar :fetch-releases="fetchReleases" /> <div class="actor-inner"> <div class="profile"> <a v-if="actor.avatar" :href="`/media/${actor.avatar.path}`" target="_blank" rel="noopener noreferrer" class="avatar-link" > <img :src="`/media/${actor.avatar.thumbnail}`" class="avatar" > </a> <ul class="bio nolist"> <li class="bio-header"> <h2 class="bio-name">{{ actor.name }}</h2> <span v-if="actor.gender" class="bio-gender" :class="{ male: actor.gender === 'male', female: actor.gender === 'female' }" ><Icon :icon="actor.gender" /></span> </li> <li v-if="actor.aliases.length" class="bio-item" > <dfn class="bio-label">Also known as</dfn> <span>{{ actor.aliases.join(', ') }}</span> </li> <li v-if="actor.birthdate" class="bio-item" > <dfn class="bio-label"><Icon icon="cake" />Birthdate</dfn> <span v-if="actor.birthdate" class="birthdate" >{{ formatDate(actor.birthdate, 'MMMM D, YYYY') }}<span class="age">{{ actor.age }}</span></span> </li> <li v-if="actor.origin" class="bio-item birth" > <dfn class="bio-label"><Icon icon="home2" />Born in</dfn> <span> <span v-if="actor.origin.city" class="city" >{{ actor.origin.city }}</span><span v-if="actor.origin.state && (!actor.origin.city || (actor.origin.country && actor.origin.country.alpha2 === 'US'))" class="state" >{{ actor.origin.city ? `, ${actor.origin.state}` : actor.origin.state }}</span> <span v-if="actor.origin.country" class="country birthcountry" > <img class="flag" :src="`/img/flags/${actor.origin.country.alpha2.toLowerCase()}.png`" >{{ actor.origin.country.alias || actor.origin.country.name }} </span> </span> </li> <li v-if="actor.residence" class="bio-item residence" > <dfn class="bio-label"><Icon icon="location" />Lives in</dfn> <span> <span v-if="actor.residence.city" class="city" >{{ actor.residence.city }}</span><span v-if="actor.residence.state && actor.residence.country && actor.residence.country.alpha2 === 'US'" class="state" >{{ actor.residence.city ? `, ${actor.residence.state}` : actor.residence.state }}</span> <span v-if="actor.residence.country" class="country" > <img class="flag" :src="`/img/flags/${actor.residence.country.alpha2.toLowerCase()}.png`" >{{ actor.residence.country.alias || actor.residence.country.name }} </span> </span> </li> </ul> <ul class="bio nolist"> <li v-if="actor.ethnicity" class="bio-item ethnicity" > <dfn class="bio-label"><Icon icon="earth2" />Ethnicity</dfn> <span>{{ actor.ethnicity }}</span> </li> <li v-if="actor.bust || actor.waist || actor.hip" title="bust-waist-hip" class="bio-item" > <dfn class="bio-label"><Icon icon="ruler" />Sizes</dfn> <span> <Icon v-if="actor.naturalBoobs === false" v-tooltip="'Boobs enhanced'" icon="magic-wand" class="enhanced" />{{ actor.bust || '??' }}-{{ actor.waist || '??' }}-{{ actor.hip || '??' }} </span> </li> <li v-if="actor.height" class="bio-item height" > <dfn class="bio-label"><Icon icon="height" />Height</dfn> <span> <span class="height-metric">{{ actor.height }} cm</span> <span class="height-imperial">{{ imperialHeight.feet }}' {{ imperialHeight.inches }}"</span> </span> </li> <li v-if="actor.weight" class="bio-item weight" > <dfn class="bio-label"><Icon icon="scale" />Weight</dfn> <span> <span class="weight-metric">{{ actor.weight }} kg</span> <span class="weight-imperial">{{ imperialWeight }} lbs</span> </span> </li> <li v-if="actor.hasTattoos" class="bio-item tattoos" > <dfn class="bio-label"><Icon icon="flower" />Tattoos</dfn> <span v-if="actor.tattoos" v-tooltip="actor.tattoos" class="bio-value" >{{ actor.tattoos }}</span> <span v-else>Yes</span> </li> <li v-if="actor.hasPiercings" class="bio-item piercings" > <dfn class="bio-label"><Icon icon="trophy4" />Piercings</dfn> <span v-if="actor.piercings" v-tooltip="actor.piercings" class="bio-value" >{{ actor.piercings }}</span> <span v-else>Yes</span> </li> <span class="scraped">Updated on {{ formatDate(actor.scrapedAt, 'YYYY-MM-DD HH:mm') }}</span> </ul> <div class="extra"> <p v-if="actor.description" class="description" >{{ actor.description }}</p> <li v-if="actor.social && actor.social.length > 0" class="social" > <a v-for="social in actor.social" :key="`social-${social.id}`" v-tooltip.bottom="social.url" :href="social.url" target="_blank" rel="noopener noreferrer" class="social-link" > <Icon v-if="social.platform" :icon="social.platform" /> <Icon v-else icon="link" /> </a> </li> </div> </div> <div class="actor-content"> <div v-if="actor.photos && actor.photos.length > 0" class="photos-container" > <Photos :actor="actor" /> <Photos :actor="actor" class="compact" @wheel.native.prevent="scrollPhotos" /> </div> <Releases :releases="releases" /> </div> </div> </div> </template> <script> import { cmToFeetInches, kgToLbs } from '../../../src/utils/convert'; import Photos from './photos.vue'; import FilterBar from '../header/filter-bar.vue'; import Releases from '../releases/releases.vue'; async function fetchReleases() { this.releases = await this.$store.dispatch('fetchActorReleases', this.$route.params.actorSlug); } function imperialHeight() { return cmToFeetInches(this.actor.height); } function imperialWeight() { return kgToLbs(this.actor.weight); } function scrollPhotos(event) { event.currentTarget.scrollLeft += event.deltaY; // eslint-disable-line no-param-reassign } async function mounted() { [this.actor] = await Promise.all([ this.$store.dispatch('fetchActors', { actorId: this.$route.params.actorSlug }), this.fetchReleases(), ]); if (this.actor) { this.pageTitle = this.actor.name; } } export default { components: { FilterBar, Photos, Releases, }, data() { return { actor: null, releases: null, pageTitle: null, expanded: false, }; }, computed: { imperialHeight, imperialWeight, }, mounted, methods: { fetchReleases, scrollPhotos, }, }; </script> <style lang="scss" scoped> @import 'theme'; .actor-inner { height: 100%; display: flex; flex-direction: column; padding: 0; overflow-x: auto; } .profile { background: $profile; color: $highlight-extreme; width: 100%; display: flex; flex-direction: row; flex-shrink: 0; .avatar-link { font-size: 0; padding: 1rem 0 1rem 1rem; } .avatar { height: 15rem; width: 12rem; flex-shrink: 0; margin: 0 1rem 0 0; object-fit: cover; object-position: 50% 0; } } .bio { flex-grow: 1; min-width: 20rem; box-sizing: border-box; padding: 1rem; margin: 0 2rem 0 0; } .bio-header { display: flex; justify-content: space-between; align-items: center; margin: 0 0 1rem 0; } .bio-item { display: flex; justify-content: space-between; padding: 0 0 .25rem 0; margin: 0 0 .25rem 0; line-height: 1.75; text-align: right; font-size: .9rem; font-weight: 600; &:not(:last-of-type) { border-bottom: solid 1px $highlight-hint; } } .bio-label { color: $highlight; margin: 0 1rem 0 0; flex-shrink: 0; font-style: normal; font-weight: 400; .icon { fill: $highlight; margin: 0 .5rem 0 0; } } .bio-value { white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } .flag { margin: 0 .25rem 0 0; } .bio-name { display: inline-block; padding: 0; margin: 0; } .bio-gender { display: inline-block; font-weight: bold; text-transform: capitalize; font-weight: normal; .icon { width: 1.25rem; height: 1.25rem; } &.female .icon { fill: $female; } &.male .icon { fill: $male; } } .birthdate { display: block; } .age { font-weight: bold; padding: 0 0 0 .5rem; border-left: solid 1px $highlight-weak; margin: 0 0 0 .5rem; } .country { display: block; } .height-imperial, .weight-imperial { padding: 0 0 0 .5rem; border-left: solid 1px $highlight-weak; margin: 0 0 0 .5rem; } .enhanced.icon { fill: $primary; padding: 0 .5rem; } .scraped { color: $highlight-weak; margin: 1rem 0 0 0; font-size: .8rem; } .extra { flex-grow: 1; } .description { max-height: 12rem; position: relative; display: block; box-sizing: border-box; padding: 1rem 0 0 0; margin: 0 2rem 0 0; line-height: 1.5; text-overflow: ellipsis; font-size: .9rem; overflow: auto; scrollbar-width: none; &::-webkit-scrollbar { display: none; } } .social { display: block; margin: 1rem 0; } .social-link { display: inline-block; padding: 0 1rem 0 0; .icon { color: $highlight; fill: $highlight; width: 1.5rem; height: 1.5rem; } &:hover .icon { fill: $primary; } } .actor-content { display: flex; flex-grow: 1; flex-direction: row; } .heading { padding: 0; margin: 0 0 1rem 0; } .photos-container { min-width: 15rem; box-sizing: border-box; border-right: solid 1px $shadow-hint; padding: 1rem 1.5rem 1rem 1rem; margin: 0 .5rem 0 0; } .photos.compact { display: none; } .releases { flex-grow: 1; padding: 1rem; } @media(max-width: $breakpoint4) { .description { display: none; } } @media(max-width: $breakpoint3) { .profile .avatar-link, .extra { display: none; } .actor-content { flex-direction: column; } .photos-container { border: none; border-bottom: solid 1px $shadow-hint; padding: 1rem 1rem 1.5rem 1rem; margin: 0 0 .5rem 0; } .photos { display: none; } .photos.compact { display: flex; } } @media(max-width: $breakpoint) { .profile { flex-direction: column; padding: 0 0 .5rem 0; } .bio { width: 100%; padding: 0 1rem; margin: 0; } .bio-header { margin: 1rem 0; } .city, .state, .ethnicity, .residence, .weight, .tattoos, .piercings, .scraped { display: none; } .social { padding: 0 1rem; } } </style>