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

202 lines
3.5 KiB
Vue

<template>
<div class="page">
<form
class="search-container"
@submit.prevent="search"
>
<input
v-model="query"
type="search"
placeholder="Search channel"
class="search input"
@search="search"
>
<Icon
icon="search"
@click="search"
/>
</form>
<div
v-for="(section, index) in sections"
:key="`section-${index}`"
>
<h2 class="section-label">{{ section.label }}</h2>
<ul class="networks nolist">
<li
v-for="network in section.networks"
:key="`network-${network.id}`"
:title="network.name"
>
<a
:href="`/${network.type}/${network.slug}`"
class="network"
>
<img
v-if="network.hasLogo"
:src="network.type === 'network' || network.isIndependent || !network.parent ? `/logos/${network.slug}/network.png` : `/logos/${network.parent.slug}/${network.slug}.png`"
:alt="network.name"
class="logo"
>
<span v-else>{{ network.name }}</span>
<Icon
v-if="pageContext.urlParsed.search.q && network.type === 'network'"
icon="device_hub"
/>
</a>
</li>
</ul>
</div>
</div>
</template>
<script setup>
import { ref, inject } from 'vue';
import navigate from '#/src/navigate.js';
const pageContext = inject('pageContext');
const { pageProps } = pageContext;
const { networks } = pageProps;
const networksBySlug = Object.fromEntries(networks.map((network) => [network.slug, network]));
const popularNetworks = [
'21sextury',
'adulttime',
'amateurallure',
'analvids',
'bamvisions',
'bang',
'bangbros',
'blowpass',
'brazzers',
'burningangel',
'digitalplayground',
'dogfartnetwork',
'dorcel',
'elegantangel',
'evilangel',
'fakehub',
'hookuphotshot',
'hussiepass',
'julesjordan',
'kink',
'mofos',
'naughtyamerica',
'newsensations',
'pervcity',
'pornpros',
'private',
'realitykings',
'teamskeet',
'vixen',
'xempire',
].map((slug) => networksBySlug[slug]).filter(Boolean);
const query = ref(pageContext.urlParsed.search.q || null);
const sections = [
!query.value && {
label: 'Popular',
networks: popularNetworks,
},
{
label: query.value ? 'Results' : 'All networks',
networks,
},
].filter(Boolean);
async function search() {
navigate('/channels', { q: query.value || undefined }, { redirect: true });
}
</script>
<style scoped>
.search-container {
display: flex;
align-items: stretch;
padding: 1rem 1rem 0 1rem;
.icon {
padding: 0 1rem;
height: auto;
fill: var(--shadow);
&:hover {
cursor: pointer;
fill: var(--primary);
}
}
}
.search {
font-size: 1.1rem;
}
.networks {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
gap: .5rem;
padding: .5rem 1rem;
}
.section-label {
padding: 0 1rem;
margin-bottom: .5rem;
color: var(--shadow);
}
.network {
display: flex;
justify-content: center;
align-items: center;
aspect-ratio: 4/1;
position: relative;
padding: 1rem;
border-radius: .5rem;
background: var(--grey-dark-40);
color: var(--text-light);
font-size: 1.25rem;
font-weight: bold;
overflow: hidden;
.icon {
position: absolute;
top: -.25rem;
right: -.25rem;
padding: .4rem .55rem .25rem .25rem;
border-radius: .25rem;
background: var(--highlight-weak-30);
fill: var(--text-light);
}
&:hover {
box-shadow: 0 0 3px var(--shadow);
}
}
.logo {
height: 100%;
width: 100%;
object-fit: contain;
}
@media(--small-30) {
.networks {
grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
}
}
@media(--small-50) {
.networks {
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
}
}
</style>