<template> <div class="page"> <form class="search-container" @submit.prevent="search" > <input v-model="query" type="search" placeholder="Search channels" 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 nolink" > <img v-if="network.hasLogo" :src="network.type === 'network' || network.isIndependent || !network.parent ? `/logos/${network.slug}/thumbs/network.png` : `/logos/${network.parent.slug}/thumbs/${network.slug}.png`" :alt="network.name" class="logo" > <span v-else class="ellipsis" >{{ 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', 'mikeadriano', '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> .page { flex-grow: 1; } .search-container { display: flex; align-items: stretch; padding: 1rem 1rem 0 1rem; .icon { padding: 0 1rem; height: auto; fill: var(--glass); &: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(--glass); } .network { display: flex; justify-content: center; align-items: center; aspect-ratio: 4/1; position: relative; padding: 1rem; border-radius: .5rem; background: var(--shadow-strong-30); color: var(--text-light); font-size: 1.5rem; 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>