<template> <div class="actors"> <nav class="filter"> <ul class="genders nolist"> <li class="gender"> <router-link :to="{ name: 'actors', params: { gender: 'all', letter, pageNumber: 1 } }" :class="{ selected: gender === 'all' }" class="gender-link all" >all</router-link> </li> <li class="gender"> <router-link :to="{ name: 'actors', params: { gender: 'female', letter, pageNumber: 1 } }" :class="{ selected: gender === 'female' }" class="gender-link female" ><Gender gender="female" /></router-link> </li> <li class="gender"> <router-link :to="{ name: 'actors', params: { gender: 'male', letter, pageNumber: 1 } }" :class="{ selected: gender === 'male' }" class="gender-link male" replace ><Gender gender="male" /></router-link> </li> <li class="gender"> <router-link :to="{ name: 'actors', params: { gender: 'trans', letter, pageNumber: 1 } }" :class="{ selected: gender === 'trans' }" class="gender-link transsexual" replace ><Gender gender="transsexual" /></router-link> </li> <li class="gender"> <router-link :to="{ name: 'actors', params: { gender: 'other', letter, pageNumber: 1 } }" :class="{ selected: gender === 'other' }" class="gender-link other" replace ><Icon icon="question5" /></router-link> </li> </ul> <ul class="letters nolist"> <li v-for="letterX in letters" :key="letterX" class="letter" > <router-link :to="{ name: 'actors', params: { gender, letter: letterX, pageNumber: 1 } }" :class="{ selected: letterX === letter }" class="letter-link" replace >{{ letterX || 'All' }}</router-link> </li> </ul> </nav> <Pagination :items-total="totalCount" :items-per-page="limit" /> <div v-lazy-container="{ selector: '.lazy' }" class="tiles" > <Actor v-for="actor in actors" :key="`actor-${actor.id}`" :actor="actor" /> </div> <Pagination v-if="totalCount > 0" :items-total="totalCount" :items-per-page="limit" class="pagination-top" /> <Footer /> </div> </template> <script> import Actor from './tile.vue'; import Gender from './gender.vue'; import Pagination from '../pagination/pagination.vue'; async function fetchActors() { const curatedGender = this.gender.replace('trans', 'transsexual'); const { actors, totalCount } = await this.$store.dispatch('fetchActors', { limit: this.limit, pageNumber: Number(this.$route.params.pageNumber) || 1, letter: this.letter.replace('all', ''), gender: curatedGender === 'other' ? null : curatedGender, }); this.actors = actors; this.totalCount = totalCount; } function letter() { return this.$route.params.letter || 'all'; } function gender() { return this.$route.params.gender || 'all'; } async function route() { await this.fetchActors(); } async function mounted() { this.pageTitle = 'Actors'; await this.fetchActors(); } export default { components: { Actor, Gender, Pagination, }, data() { return { actors: [], pageTitle: null, totalCount: 0, limit: 30, letters: ['all'].concat(Array.from({ length: 26 }, (value, index) => String.fromCharCode(index + 97).toUpperCase())), }; }, computed: { letter, gender, }, watch: { $route: route, }, mounted, methods: { fetchActors, }, }; </script> <style lang="scss"> .gender-link { &.selected .gender .icon { fill: var(--text-light); filter: none; } &:hover:not(.selected) { .gender .icon { fill: var(--text-light); } .male .icon { filter: drop-shadow(0 0 1px var(--male)); } .female .icon { filter: drop-shadow(0 0 1px var(--female)); } } &:hover:not(.selected) .transsexual .icon { fill: var(--female); filter: drop-shadow(1px 0 0 var(--text-light)) drop-shadow(-1px 0 0 var(--text-light)) drop-shadow(0 1px 0 var(--text-light)) drop-shadow(0 -1px 0 var(--text-light)) drop-shadow(1px 0 0 var(--male)) drop-shadow(-1px 0 0 var(--male)) drop-shadow(0 1px 0 var(--male)) drop-shadow(0 -1px 0 var(--male)) drop-shadow(0 0 1px rgba(0, 0, 0, 0.5)); } } </style> <style lang="scss" scoped> @import 'breakpoints'; .actors { display: flex; flex-direction: column; } .tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); grid-gap: .5rem; padding: 1rem; flex-grow: 1; } .filter { display: flex; justify-content: center; align-items: center; padding: 0 1rem; margin: 1rem 0; } .genders { display: flex; flex-shrink: 0; padding: 0 .5rem 0 0; border-right: solid 1px var(--shadow-hint); margin: 0 1rem 0 0; } .letter, .gender { display: inline-block; } .letter-link, .gender-link { width: 2.5rem; height: 2.5rem; display: flex; align-items: center; justify-content: center; box-sizing: border-box; margin: .25rem .5rem .25rem 0; color: var(--shadow); background: var(--background); font-weight: bold; text-decoration: none; box-shadow: 0 0 3px var(--darken-weak); .male, .female, .transsexual { padding: .2rem 0 0 0; } .icon { fill: var(--shadow); } &:hover { color: var(--text); cursor: pointer; .icon { fill: var(--text); } } &.selected { background: var(--primary); color: var(--text-light); &.other .icon { fill: var(--text-light); } } } @media(max-width: $breakpoint) { .genders { flex-direction: column; } } @media(max-width: $breakpoint-micro) { .tiles { grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr)); } } </style>