traxxx-web/pages/entities/@entitySlug/+Page.vue

346 lines
6.0 KiB
Vue

<template>
<div class="page">
<div class="header">
<a
:href="entityUrl"
target="_blank"
rel="noopener"
class="link-child nolink"
:data-umami-event="entity.affiliate ? 'entity-click-aff' : 'entity-click'"
:data-umami-event-aff-id="entity.affiliate?.id"
:data-umami-event-entity="entity.slug"
>
<template v-if="entity.hasLogo">
<img
v-if="entity.type === 'network'"
class="logo logo-child"
:src="`/logos/${entity.slug}/thumbs/network.png`"
>
<img
v-else-if="entity.parent && !entity.isIndependent"
class="logo logo-child"
:src="`/logos/${entity.parent.slug}/thumbs/${entity.slug}.png`"
>
<img
v-else
class="logo logo-child"
:src="`/logos/${entity.slug}/thumbs/${entity.slug}.png`"
>
</template>
<h2
v-else
class="name"
>{{ entity.name }}</h2>
</a>
<Domains
:domain="domain"
:path="`/${entity.type}/${entity.slug}`"
:domains="['scenes', 'movies']"
class="domains-header"
/>
<a
v-if="entity.parent"
:href="`/${entity.parent.type}/${entity.parent.slug}`"
class="link-parent nolink"
>
<img
v-if="entity.parent.hasLogo"
class="logo logo-parent"
:src="`/logos/${entity.parent.slug}/thumbs/network.png`"
>
<img
v-if="entity.parent.hasLogo"
class="favicon"
:src="`/logos/${entity.parent.slug}/favicon.png`"
>
<h3
v-else
class="name parent-name"
>{{ entity.parent.name }}</h3>
</a>
</div>
<div class="content">
<Domains
:domain="domain"
:path="`/${entity.type}/${entity.slug}`"
:domains="['scenes', 'movies']"
class="domains-bar"
/>
<div class="children-container">
<div
v-show="expanded"
class="expand-container expand-top"
>
<button
class="expand"
@click="expanded = !expanded"
>
<span class="expand-text">Collapse channels</span>
<Icon icon="arrow-up3" />
</button>
</div>
<ul
v-if="entity.children.length > 0"
ref="children"
class="children nolist"
:class="{ expanded }"
>
<li
v-for="channel in entity.children"
:key="`channel-${channel.id}`"
:title="channel.name"
>
<EntityTile :entity="channel" />
</li>
</ul>
<div class="expand-container">
<button
v-show="scrollable && !expanded"
class="expand"
@click="expanded = !expanded"
>
<span class="expand-text">Expand channels</span>
<Icon icon="arrow-down3" />
</button>
<button
v-show="expanded"
class="expand"
@click="expanded = !expanded"
>
<span class="expand-text">Collapse channels</span>
<Icon icon="arrow-up3" />
</button>
</div>
</div>
<Scenes v-if="domain === 'scenes'" />
<Movies v-if="domain === 'movies'" />
</div>
</div>
</template>
<script setup>
import { ref, computed, inject } from 'vue';
import EntityTile from '#/components/entities/tile.vue';
import Scenes from '#/components/scenes/scenes.vue';
import Movies from '#/components/movies/movies.vue';
import Domains from '#/components/domains/domains.vue';
const { pageProps, routeParams } = inject('pageContext');
const { entity } = pageProps;
const children = ref(null);
const expanded = ref(false);
const scrollable = computed(() => children.value?.scrollWidth > children.value?.clientWidth);
const domain = routeParams.domain;
const entityUrl = (() => {
if (!entity.url) {
return null;
}
if (!entity.affiliate?.parameters) {
return entity.url;
}
const newParams = new URLSearchParams({
...Object.fromEntries(new URL(entity.url).searchParams),
...Object.fromEntries(new URLSearchParams(entity.affiliate.parameters)),
});
return `${entity.url}?${newParams}`;
})();
</script>
<style scoped>
.page {
display: flex;
flex-direction: column;
flex-grow: 1;
}
.content {
display: flex;
flex-direction: column;
flex-grow: 1;
}
.header {
display: flex;
justify-content: space-between;
align-items: stretch;
position: sticky;
top: 0;
z-index: 11; /* ensure it's about expand tab */
color: var(--text-light);
background: var(--grey-dark-50);
.link {
display: flex;
align-items: center;
}
}
.name {
display: block;
padding: 1rem;
margin: 0;
}
.logo {
height: 2rem;
max-width: 15rem;
padding: .5rem 1rem;
object-fit: contain;
}
.link-parent {
display: flex;
align-items: center;
}
.favicon {
display: none;
padding: .5rem 1rem;
height: 1.5rem;
}
.children-container {
position: relative;
}
.children {
background: var(--grey-dark-50);
display: flex;
/*
display: grid;
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
*/
gap: .5rem;
padding: .5rem;
overflow-x: auto;
flex-shrink: 0;
&.expanded {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
overflow-x: hidden;
.entity {
width: 100%;
}
}
}
.children::-webkit-scrollbar {
display: none;
}
.expand-container {
width: 100%;
display: flex;
justify-content: center;
position: absolute;
left: 0;
bottom: -.75rem;
z-index: 10;
}
.expand {
display: flex;
align-items: center;
padding: .5rem;
border: none;
background: var(--grey-dark-40);
color: var(--highlight-strong-30);
font-size: .9rem;
font-weight: bold;
border-radius: .5rem;
box-shadow: 0 0 3px var(--shadow);
.icon {
fill: var(--highlight-strong-30);
margin-left: 1rem;
}
&:hover {
color: var(--text-light);
cursor: pointer;
.icon {
fill: var(--text-light);
}
}
}
.expand-top {
height: 0;
top: 3.5rem;
bottom: auto;
position: sticky;
.expand {
height: 2rem;
}
}
.domains-bar {
display: none;
}
@media(--small-20) {
.logo {
padding: .5rem 1rem;
}
.favicon {
height: 1rem;
padding: .5rem 1rem;
}
.domains-header {
display: none;
}
.domains-bar {
display: flex;
}
}
@media(--compact) {
.logo {
height: 1.25rem;
}
.logo-parent {
display: none;
}
.favicon {
display: inline-block;
}
.expand-text {
display: none;
}
.expand .icon {
margin-right: 1rem;
}
}
</style>