161 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Vue
		
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Vue
		
	
	
	
| <template>
 | |
| 	<div class="networks">
 | |
| 		<form
 | |
| 			class="search"
 | |
| 			@submit.prevent="searchEntities"
 | |
| 		>
 | |
| 			<input
 | |
| 				v-model="query"
 | |
| 				:placeholder="`Find ${channelCount} channels in ${entities.length} networks`"
 | |
| 				class="query"
 | |
| 				@input="searchEntities"
 | |
| 			>
 | |
| 
 | |
| 			<button
 | |
| 				type="submit"
 | |
| 				class="search-button"
 | |
| 			><Icon icon="search" /></button>
 | |
| 		</form>
 | |
| 
 | |
| 		<div
 | |
| 			v-if="query.length > 0"
 | |
| 			class="entity-tiles"
 | |
| 		>
 | |
| 			<Entity
 | |
| 				v-for="entity in searchResults"
 | |
| 				:key="`${entity.type}-tile-${entity.slug}`"
 | |
| 				:entity="entity"
 | |
| 			/>
 | |
| 
 | |
| 			<span v-if="searchResults.length === 0">No results for "{{ query }}"</span>
 | |
| 		</div>
 | |
| 
 | |
| 		<div
 | |
| 			v-else
 | |
| 			class="entity-tiles"
 | |
| 		>
 | |
| 			<Entity
 | |
| 				v-for="entity in entities"
 | |
| 				:key="`entity-tile-${entity.slug}`"
 | |
| 				:entity="entity"
 | |
| 			/>
 | |
| 		</div>
 | |
| 
 | |
| 		<Footer />
 | |
| 	</div>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import Entity from '../entities/tile.vue';
 | |
| 
 | |
| async function searchEntities() {
 | |
| 	this.searchResults = await this.$store.dispatch('searchEntities', {
 | |
| 		query: this.query,
 | |
| 		limit: 50,
 | |
| 	});
 | |
| }
 | |
| 
 | |
| async function mounted() {
 | |
| 	this.entities = await this.$store.dispatch('fetchEntities', {
 | |
| 		type: 'network',
 | |
| 		entitySlugs: [],
 | |
| 	});
 | |
| 
 | |
| 	this.pageTitle = 'Networks';
 | |
| }
 | |
| 
 | |
| function channelCount() {
 | |
| 	return this.entities.reduce((acc, entity) => acc + entity.childrenTotal, 0);
 | |
| }
 | |
| 
 | |
| export default {
 | |
| 	components: {
 | |
| 		Entity,
 | |
| 	},
 | |
| 	data() {
 | |
| 		return {
 | |
| 			query: '',
 | |
| 			pageTitle: null,
 | |
| 			entities: [],
 | |
| 			searchResults: [],
 | |
| 		};
 | |
| 	},
 | |
| 	computed: {
 | |
| 		channelCount,
 | |
| 	},
 | |
| 	mounted,
 | |
| 	methods: {
 | |
| 		searchEntities,
 | |
| 	},
 | |
| };
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
| @import 'theme';
 | |
| 
 | |
| .networks {
 | |
|     padding: 0 1rem;
 | |
| }
 | |
| 
 | |
| .search {
 | |
|     display: flex;
 | |
|     width: 100%;
 | |
|     max-width: 40rem;
 | |
| }
 | |
| 
 | |
| .query {
 | |
|     color: var(--text);
 | |
|     background: var(--background);
 | |
|     flex-grow: 1;
 | |
|     box-sizing: border-box;
 | |
|     padding: 1rem;
 | |
|     border: none;
 | |
|     box-sizing: border-box;
 | |
|     box-shadow: 0 0 3px var(--darken-weak);
 | |
|     margin: 1rem 0;
 | |
|     font-size: 1rem;
 | |
|     outline: none;
 | |
| 
 | |
|     &:focus {
 | |
|         box-shadow: 0 0 3px var(--primary);
 | |
|     }
 | |
| }
 | |
| 
 | |
| .search-button {
 | |
|     padding: 1rem;
 | |
|     background: none;
 | |
|     border: none;
 | |
| 
 | |
|     .icon {
 | |
|         fill: var(--shadow);
 | |
|     }
 | |
| 
 | |
|     &:hover {
 | |
|         cursor: pointer;
 | |
| 
 | |
|         .icon {
 | |
|             fill: var(--primary);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| .entity-tiles {
 | |
|     display: grid;
 | |
|     grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
 | |
|     grid-gap: .5rem;
 | |
|     padding: 1rem 0;
 | |
| }
 | |
| 
 | |
| @media(max-width: $breakpoint2) {
 | |
|     .entity-tiles {
 | |
|         grid-gap: .5rem;
 | |
|     }
 | |
| }
 | |
| 
 | |
| @media(max-width: $breakpoint0) {
 | |
|     .entity-tiles {
 | |
|         grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
 | |
|     }
 | |
| }
 | |
| </style>
 |