Added actors pagination.
This commit is contained in:
		
							parent
							
								
									424546029d
								
							
						
					
					
						commit
						aad43e865a
					
				|  | @ -182,7 +182,7 @@ | |||
| .filter-label { | ||||
| 	display: flex; | ||||
| 	justify-content: space-between; | ||||
| 	padding: .5rem 0 .25rem .5rem; | ||||
| 	padding: .5rem 0 .25rem .25rem; | ||||
| 	color: var(--shadow); | ||||
| 	font-weight: bold; | ||||
| 	font-size: .9rem; | ||||
|  | @ -209,7 +209,7 @@ | |||
| 	height: 1.25rem; | ||||
| 	appearance: none; | ||||
| 	border-radius: 1rem; | ||||
| 	background-color: var(--shadow-weak-30); | ||||
| 	background-color: var(--shadow-weak-40); | ||||
| 	background-image: radial-gradient(circle, var(--shadow-weak-10) .3rem, transparent calc(.3rem + 1px)); | ||||
| 	cursor: pointer; | ||||
| 
 | ||||
|  |  | |||
|  | @ -57,5 +57,5 @@ | |||
| 	--enabled-background: rgba(0, 255, 0, .1); | ||||
| 	--disabled: #c20; | ||||
| 	--disabled-background: rgba(255, 0, 0, .1); | ||||
| 	--disabled-handle: #aaa; | ||||
| 	--disabled-handle: var(--grey-light-10); | ||||
| } | ||||
|  |  | |||
|  | @ -62,12 +62,13 @@ defineProps({ | |||
| .actor { | ||||
| 	display: flex; | ||||
| 	flex-direction: column; | ||||
| 	width: 10rem; | ||||
| 	height: 15rem; | ||||
| 	width: 100%; | ||||
| 	aspect-ratio: 2/3; | ||||
| 	position: relative; | ||||
| 	border-radius: .25rem; | ||||
| 	margin: .25rem; | ||||
| 	box-shadow: 0 0 3px var(--shadow-weak-30); | ||||
| 	overflow: hidden; | ||||
| 
 | ||||
| 	&:hover { | ||||
| 		box-shadow: 0 0 3px var(--shadow-weak-20); | ||||
|  | @ -82,6 +83,9 @@ defineProps({ | |||
| 	padding: .25rem .5rem; | ||||
| 	font-weight: bold; | ||||
| 	font-size: .9rem; | ||||
| 	white-space: nowrap; | ||||
| 	overflow: hidden; | ||||
| 	text-overflow: ellipsis; | ||||
| 	user-select: all; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -161,8 +161,8 @@ async function setRange(prop, value) { | |||
| 	border-radius: .625rem; | ||||
| 
 | ||||
| 	&.disabled { | ||||
| 		--slider-range: var(--shadow-weak-30); | ||||
| 		--slider-thumb: var(--grey-dark-10); | ||||
| 		--slider-range: var(--shadow-weak-40); | ||||
| 		--slider-thumb: var(--disabled-handle); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,17 +3,19 @@ | |||
| 		<ul class="pages nolist"> | ||||
| 			<li> | ||||
| 				<Link | ||||
| 					:href="`/updates/${routeParams?.scope}/1`" | ||||
| 					:href="getPath(1)" | ||||
| 					:class="{ disabled: !hasPrevPage }" | ||||
| 					class="page first nolink" | ||||
| 					@click="(event) => go(1, event)" | ||||
| 				><Icon icon="first2" /></Link> | ||||
| 			</li> | ||||
| 
 | ||||
| 			<li> | ||||
| 				<Link | ||||
| 					:href="hasPrevPage ? `/updates/${routeParams?.scope}/${currentPage - 1}` : null" | ||||
| 					:href="hasPrevPage ? getPath(currentPage - 1) : null" | ||||
| 					:class="{ disabled: !hasPrevPage }" | ||||
| 					class="page prev nolink" | ||||
| 					@click="(event) => hasPrevPage && go(currentPage - 1, event)" | ||||
| 				><Icon icon="arrow-left" /></Link> | ||||
| 			</li> | ||||
| 		</ul> | ||||
|  | @ -21,14 +23,15 @@ | |||
| 		<div class="index"> | ||||
| 			<ul class="pages before wrap nolist"> | ||||
| 				<li | ||||
| 					v-for="page in prevPages" | ||||
| 					:key="`page-${page}`" | ||||
| 					v-for="prevPage in prevPages" | ||||
| 					:key="`page-${prevPage}`" | ||||
| 				> | ||||
| 					<Link | ||||
| 						:href="`/updates/${routeParams?.scope}/${page}`" | ||||
| 						:href="getPath(prevPage)" | ||||
| 						:class="{ active: prevPage === currentPage }" | ||||
| 						class="page nolink" | ||||
| 						:class="{ active: page === currentPage }" | ||||
| 					>{{ page }}</Link> | ||||
| 						@click="(event) => go(prevPage, event)" | ||||
| 					>{{ prevPage }}</Link> | ||||
| 				</li> | ||||
| 			</ul> | ||||
| 
 | ||||
|  | @ -40,14 +43,15 @@ | |||
| 
 | ||||
| 			<ul class="pages after wrap nolist"> | ||||
| 				<li | ||||
| 					v-for="page in nextPages" | ||||
| 					:key="`page-${page}`" | ||||
| 					v-for="nextPage in nextPages" | ||||
| 					:key="`page-${nextPage}`" | ||||
| 				> | ||||
| 					<Link | ||||
| 						:href="`/updates/${routeParams?.scope}/${page}`" | ||||
| 						:href="getPath(nextPage)" | ||||
| 						:class="{ active: nextPage === currentPage }" | ||||
| 						class="page nolink" | ||||
| 						:class="{ active: page === currentPage }" | ||||
| 					>{{ page }}</Link> | ||||
| 						@click="(event) => go(nextPage, event)" | ||||
| 					>{{ nextPage }}</Link> | ||||
| 				</li> | ||||
| 			</ul> | ||||
| 		</div> | ||||
|  | @ -55,17 +59,19 @@ | |||
| 		<ul class="pages nolist"> | ||||
| 			<li> | ||||
| 				<Link | ||||
| 					:href="hasNextPage ? `/updates/${routeParams?.scope}/${currentPage + 1}` : null" | ||||
| 					:href="hasNextPage ? getPath(currentPage + 1) : null" | ||||
| 					:class="{ disabled: !hasNextPage }" | ||||
| 					class="page next nolink" | ||||
| 					@click="(event) => hasNextPage && go(currentPage + 1, event)" | ||||
| 				><Icon icon="arrow-right" /></Link> | ||||
| 			</li> | ||||
| 
 | ||||
| 			<li> | ||||
| 				<Link | ||||
| 					:href="`/updates/${routeParams?.scope}/${pageTotal}`" | ||||
| 					:href="getPath(pageTotal)" | ||||
| 					:class="{ disabled: !hasNextPage }" | ||||
| 					class="page last nolink" | ||||
| 					@click="(event) => go(pageTotal, event)" | ||||
| 				><Icon icon="last2" /></Link> | ||||
| 			</li> | ||||
| 		</ul> | ||||
|  | @ -73,41 +79,87 @@ | |||
| </template> | ||||
| 
 | ||||
| <script setup> | ||||
| import { inject } from 'vue'; | ||||
| import { computed, inject } from 'vue'; | ||||
| import { parse } from 'path-to-regexp'; | ||||
| 
 | ||||
| const { routeParams, pageProps } = inject('pageContext'); | ||||
| const currentPage = Number(routeParams?.page); | ||||
| const limit = Number(pageProps.limit) || 30; | ||||
| const total = Number(pageProps.total); | ||||
| const pageTotal = Math.ceil(total / limit); | ||||
| const hasNextPage = currentPage + 1 <= pageTotal; | ||||
| const hasPrevPage = currentPage - 1 >= 1; | ||||
| const props = defineProps({ | ||||
| 	page: { | ||||
| 		type: Number, | ||||
| 		default: null, | ||||
| 	}, | ||||
| 	total: { | ||||
| 		type: Number, | ||||
| 		default: null, | ||||
| 	}, | ||||
| 	redirect: { | ||||
| 		type: Boolean, | ||||
| 		default: true, | ||||
| 	}, | ||||
| 	includeQuery: { | ||||
| 		type: Boolean, | ||||
| 		default: true, | ||||
| 	}, | ||||
| }); | ||||
| 
 | ||||
| console.log(routeParams); | ||||
| const emit = defineEmits(['navigation']); | ||||
| 
 | ||||
| const prevPages = Array.from({ length: 4 }, (value, index) => { | ||||
| 	const page = currentPage - index - 1; | ||||
| const pageContext = inject('pageContext'); | ||||
| const { routeParams, urlParsed, pageProps } = pageContext; | ||||
| 
 | ||||
| const currentPage = computed(() => props.page || Number(routeParams?.page)); | ||||
| 
 | ||||
| const limit = computed(() => props.limit || Number(pageProps.limit) || 30); | ||||
| const total = computed(() => props.total || Number(pageProps.total)); | ||||
| const pageTotal = computed(() => Math.ceil(total.value / limit.value)); | ||||
| 
 | ||||
| const hasNextPage = computed(() => currentPage.value + 1 <= pageTotal.value); | ||||
| const hasPrevPage = computed(() => currentPage.value - 1 >= 1); | ||||
| 
 | ||||
| const prevPages = computed(() => Array.from({ length: 4 }, (value, index) => { | ||||
| 	const page = currentPage.value - index - 1; | ||||
| 
 | ||||
| 	if (page < 1) { | ||||
| 		return null; | ||||
| 	} | ||||
| 
 | ||||
| 	return page; | ||||
| }).filter(Boolean); | ||||
| }).filter(Boolean)); | ||||
| 
 | ||||
| const nextPages = Array.from({ length: 4 }, (value, index) => { | ||||
| 	const page = currentPage + index + 1; | ||||
| const nextPages = computed(() => Array.from({ length: 4 }, (value, index) => { | ||||
| 	const page = currentPage.value + index + 1; | ||||
| 
 | ||||
| 	if (page > pageTotal) { | ||||
| 	if (page > pageTotal.value) { | ||||
| 		return null; | ||||
| 	} | ||||
| 
 | ||||
| 	return page; | ||||
| }).filter(Boolean); | ||||
| }).filter(Boolean)); | ||||
| 
 | ||||
| console.log(total, limit, currentPage); | ||||
| console.log(prevPages); | ||||
| console.log(nextPages); | ||||
| function go(page, event) { | ||||
| 	if (!props.redirect) { | ||||
| 		event.preventDefault(); | ||||
| 
 | ||||
| 		history.pushState({}, '', event.target.href); // eslint-disable-line no-restricted-globals | ||||
| 		currentPage.value = page; | ||||
| 	} | ||||
| 
 | ||||
| 	emit('navigation', { | ||||
| 		href: event.target.href, | ||||
| 		page, | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| function getPath(page) { | ||||
| 	const path = parse(routeParams.path) | ||||
| 		.map((segment) => (segment.name === 'page' ? String(page) : routeParams[segment.name] || segment)) | ||||
| 		.join('/'); | ||||
| 
 | ||||
| 	if (props.includeQuery && urlParsed.searchOriginal) { | ||||
| 		return `${path}${urlParsed.searchOriginal}`; | ||||
| 	} | ||||
| 
 | ||||
| 	return path; | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <style scoped> | ||||
|  | @ -115,6 +167,7 @@ console.log(nextPages); | |||
| 	height: 5rem; | ||||
| 	display: flex; | ||||
| 	justify-content: center; | ||||
| 	box-sizing: border-box; | ||||
| 	padding: 1rem; | ||||
| 	font-size: 0; | ||||
| 	overflow: hidden; | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ | |||
| </template> | ||||
| 
 | ||||
| <script setup> | ||||
| import { defineProps, inject } from 'vue'; | ||||
| import { inject } from 'vue'; | ||||
| 
 | ||||
| import Scene from './tile.vue'; | ||||
| import Pagination from '../pagination/pagination.vue'; | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ | |||
|         "manticoresearch": "^4.0.0", | ||||
|         "mitt": "^3.0.1", | ||||
|         "nanoid": "^5.0.4", | ||||
|         "path-to-regexp": "^6.2.1", | ||||
|         "pg": "^8.11.3", | ||||
|         "sirv": "^2.0.3", | ||||
|         "vike": "^0.4.150", | ||||
|  | @ -4381,6 +4382,11 @@ | |||
|       "resolved": "https://registry.npmjs.org/express-query-boolean/-/express-query-boolean-2.0.0.tgz", | ||||
|       "integrity": "sha512-4dU/1HPm8lkTPR12+HFUXqCarcsC19OKOkb4otLOuADfPYrQMaugPJkSmxNsqwmWYjozvT6vdTiqkgeBHkzOow==" | ||||
|     }, | ||||
|     "node_modules/express/node_modules/path-to-regexp": { | ||||
|       "version": "0.1.7", | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", | ||||
|       "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" | ||||
|     }, | ||||
|     "node_modules/express/node_modules/safe-buffer": { | ||||
|       "version": "5.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", | ||||
|  | @ -5840,9 +5846,9 @@ | |||
|       "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" | ||||
|     }, | ||||
|     "node_modules/path-to-regexp": { | ||||
|       "version": "0.1.7", | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", | ||||
|       "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" | ||||
|       "version": "6.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", | ||||
|       "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" | ||||
|     }, | ||||
|     "node_modules/pg": { | ||||
|       "version": "8.11.3", | ||||
|  | @ -10758,6 +10764,11 @@ | |||
|         "vary": "~1.1.2" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "path-to-regexp": { | ||||
|           "version": "0.1.7", | ||||
|           "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", | ||||
|           "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" | ||||
|         }, | ||||
|         "safe-buffer": { | ||||
|           "version": "5.2.1", | ||||
|           "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", | ||||
|  | @ -11806,9 +11817,9 @@ | |||
|       "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" | ||||
|     }, | ||||
|     "path-to-regexp": { | ||||
|       "version": "0.1.7", | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", | ||||
|       "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" | ||||
|       "version": "6.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", | ||||
|       "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" | ||||
|     }, | ||||
|     "pg": { | ||||
|       "version": "8.11.3", | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ | |||
|     "manticoresearch": "^4.0.0", | ||||
|     "mitt": "^3.0.1", | ||||
|     "nanoid": "^5.0.4", | ||||
|     "path-to-regexp": "^6.2.1", | ||||
|     "pg": "^8.11.3", | ||||
|     "sirv": "^2.0.3", | ||||
|     "vike": "^0.4.150", | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| <template> | ||||
| 	<div class="page"> | ||||
| 		<form | ||||
| 			v-show="showFilters" | ||||
| 			class="filters" | ||||
| 			@submit.prevent | ||||
| 		> | ||||
|  | @ -192,7 +193,7 @@ | |||
| 					v-if="!filters.country" | ||||
| 					v-model="countryQuery" | ||||
| 					type="search" | ||||
| 					placeholder="Search country" | ||||
| 					placeholder="Filter country" | ||||
| 					class="input input-inline countries-search" | ||||
| 				> | ||||
| 
 | ||||
|  | @ -221,16 +222,45 @@ | |||
| 			</div> | ||||
| 		</form> | ||||
| 
 | ||||
| 		<ul class="actors nolist"> | ||||
| 			<li | ||||
| 				v-for="actor in actors" | ||||
| 				:key="`actor-${actor.id}`" | ||||
| 		<div class="actors-anchor"> | ||||
| 			<div | ||||
| 				class="sidebar-toggle" | ||||
| 				@click="toggleFilters" | ||||
| 			> | ||||
| 				<ActorTile | ||||
| 					:actor="actor" | ||||
| 				<Icon | ||||
| 					v-show="showFilters" | ||||
| 					icon="arrow-left3" | ||||
| 				/> | ||||
| 			</li> | ||||
| 		</ul> | ||||
| 
 | ||||
| 				<Icon | ||||
| 					v-show="!showFilters" | ||||
| 					icon="arrow-right3" | ||||
| 				/> | ||||
| 			</div> | ||||
| 
 | ||||
| 			<div | ||||
| 				ref="container" | ||||
| 				class="actors-container" | ||||
| 			> | ||||
| 				<ul class="actors nolist"> | ||||
| 					<li | ||||
| 						v-for="actor in actors" | ||||
| 						:key="`actor-${actor.id}`" | ||||
| 					> | ||||
| 						<ActorTile | ||||
| 							:actor="actor" | ||||
| 						/> | ||||
| 					</li> | ||||
| 				</ul> | ||||
| 
 | ||||
| 				<Pagination | ||||
| 					:page="currentPage" | ||||
| 					:total="total" | ||||
| 					:redirect="false" | ||||
| 					@navigation="paginate" | ||||
| 				/> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </template> | ||||
| 
 | ||||
|  | @ -242,16 +272,21 @@ import navigate from '#/src/navigate.js'; | |||
| import { get } from '#/src/api.js'; | ||||
| 
 | ||||
| import ActorTile from '#/components/actors/tile.vue'; | ||||
| import Pagination from '#/components/pagination/pagination.vue'; | ||||
| import Gender from '#/components/actors/gender.vue'; | ||||
| import Checkbox from '#/components/form/checkbox.vue'; | ||||
| import RangeFilter from '#/components/filters/range.vue'; | ||||
| import Countries from '#/components/filters/countries.vue'; | ||||
| 
 | ||||
| const { pageProps, urlParsed } = inject('pageContext'); | ||||
| const pageContext = inject('pageContext'); | ||||
| const { pageProps, urlParsed, routeParams } = pageContext; | ||||
| 
 | ||||
| const q = ref(urlParsed.search.q); | ||||
| const actors = ref([]); | ||||
| 
 | ||||
| const container = ref(null); | ||||
| const showFilters = ref(true); | ||||
| 
 | ||||
| const countries = ref(pageProps.countries); | ||||
| const countryQuery = ref(''); | ||||
| 
 | ||||
|  | @ -266,6 +301,9 @@ actors.value = pageProps.actors; | |||
| const braSizes = 'ABCDEFGHIJKZ'.split(''); | ||||
| const naturalBoobsValues = [true, undefined, false]; | ||||
| 
 | ||||
| const currentPage = ref(Number(routeParams.page)); | ||||
| const total = ref(Number(pageProps.total)); | ||||
| 
 | ||||
| const filters = ref({ | ||||
| 	gender: urlParsed.search.gender, | ||||
| 	ageRequired: !!urlParsed.search.age, | ||||
|  | @ -284,9 +322,11 @@ const filters = ref({ | |||
| 	avatarRequired: !!urlParsed.search.avatar, | ||||
| }); | ||||
| 
 | ||||
| console.log(filters.value.dobType); | ||||
| async function search(resetPage = true) { | ||||
| 	if (resetPage) { | ||||
| 		currentPage.value = 1; | ||||
| 	} | ||||
| 
 | ||||
| async function search() { | ||||
| 	const query = { | ||||
| 		q: q.value || undefined, | ||||
| 		gender: filters.value.gender || undefined, | ||||
|  | @ -301,12 +341,21 @@ async function search() { | |||
| 		avatar: filters.value.avatarRequired || undefined, | ||||
| 	}; | ||||
| 
 | ||||
| 	navigate('/actors', query, { redirect: false }); | ||||
| 
 | ||||
| 	const res = await get('/actors', query); | ||||
| 	const res = await get('/actors', { ...query, page: currentPage.value }); // client uses param rather than query pagination | ||||
| 
 | ||||
| 	actors.value = res.actors; | ||||
| 	total.value = res.total; | ||||
| 
 | ||||
| 	countries.value = res.countries; | ||||
| 
 | ||||
| 	container.value.scrollTop = 0; | ||||
| 
 | ||||
| 	navigate(`/actors/${currentPage.value}`, query, { redirect: false }); | ||||
| } | ||||
| 
 | ||||
| function paginate({ page }) { | ||||
| 	currentPage.value = page; | ||||
| 	search(false); | ||||
| } | ||||
| 
 | ||||
| function updateFilter(prop, value, reload = true) { | ||||
|  | @ -316,6 +365,10 @@ function updateFilter(prop, value, reload = true) { | |||
| 		search(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| function toggleFilters() { | ||||
| 	showFilters.value = !showFilters.value; | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <style> | ||||
|  | @ -355,6 +408,7 @@ function updateFilter(prop, value, reload = true) { | |||
| 
 | ||||
| .filters { | ||||
| 	width: 17rem; | ||||
| 	position: relative; | ||||
| 	flex-shrink: 0; | ||||
| 	border-right: solid 1px var(--shadow-weak-30); | ||||
| 	overflow-y: auto; | ||||
|  | @ -365,17 +419,57 @@ function updateFilter(prop, value, reload = true) { | |||
| } | ||||
| 
 | ||||
| .filter { | ||||
| 	padding: .5rem .25rem; | ||||
| 	border-bottom: solid 1px var(--shadow-weak-30); | ||||
| 	padding: .5rem; | ||||
| 
 | ||||
| 	&:not(:last-child) { | ||||
| 		border-bottom: solid 1px var(--shadow-weak-30); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| .actors-anchor { | ||||
| 	flex-grow: 1; | ||||
| 	position: relative; | ||||
| } | ||||
| 
 | ||||
| .sidebar-toggle { | ||||
| 	width: 1.5rem; | ||||
| 	height: 2rem; | ||||
| 	display: flex; | ||||
| 	justify-content: center; | ||||
| 	align-items: center; | ||||
| 	position: absolute; | ||||
| 	bottom: .5rem; | ||||
| 	left: 0; | ||||
| 	z-index: 10; | ||||
| 	border-radius: 0 .25rem .25rem 0; | ||||
| 	background: var(--background); | ||||
| 	box-shadow: 0 0 3px var(--shadow-weak-30); | ||||
| 
 | ||||
| 	.icon { | ||||
| 		fill: var(--shadow); | ||||
| 	} | ||||
| 
 | ||||
| 	&:hover { | ||||
| 		cursor: pointer; | ||||
| 
 | ||||
| 		.icon { | ||||
| 			fill: var(--primary); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| .actors-container { | ||||
| 	height: 100%; | ||||
| 	box-sizing: border-box; | ||||
| 	padding: 1rem; | ||||
| 	overflow-y: auto; | ||||
| } | ||||
| 
 | ||||
| .actors { | ||||
| 	display: grid; | ||||
| 	flex-grow: 1; | ||||
| 	grid-template-columns: repeat(auto-fill, 10rem); | ||||
| 	grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); | ||||
| 	gap: .25rem; | ||||
| 	padding: 1rem; | ||||
| 	overflow-y: auto; | ||||
| } | ||||
| 
 | ||||
| .genders { | ||||
|  | @ -430,10 +524,17 @@ function updateFilter(prop, value, reload = true) { | |||
| 
 | ||||
| .select { | ||||
| 	flex-grow: 1; | ||||
| 	color: var(--shadow-strong-10); | ||||
| 
 | ||||
| 	option { | ||||
| 		color: var(--text); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| .countries-container { | ||||
| 	border-bottom: solid 1px var(--shadow-weak-30); | ||||
| 	padding: .25rem 0; | ||||
| 	margin-bottom: .5rem; | ||||
| } | ||||
| 
 | ||||
| .countries-search { | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ export async function onBeforeRender(pageContext) { | |||
| 		total, | ||||
| 	} = await fetchActors(curateActorsQuery(pageContext.urlQuery), { | ||||
| 		page: Number(pageContext.routeParams.page) || 1, | ||||
| 		limit: Number(pageContext.urlParsed.search.limit) || 50, | ||||
| 		limit: Number(pageContext.urlParsed.search.limit) || 120, | ||||
| 	}); | ||||
| 
 | ||||
| 	return { | ||||
|  |  | |||
|  | @ -0,0 +1,20 @@ | |||
| import { match } from 'path-to-regexp'; | ||||
| // import { resolveRoute } from 'vike/routing'; // eslint-disable-line import/extensions
 | ||||
| 
 | ||||
| const path = '/actors/:page?'; | ||||
| const urlMatch = match(path, { decode: decodeURIComponent }); | ||||
| 
 | ||||
| export default (pageContext) => { | ||||
| 	const matched = urlMatch(pageContext.urlPathname); | ||||
| 
 | ||||
| 	if (matched) { | ||||
| 		return { | ||||
| 			routeParams: { | ||||
| 				page: matched.params.page || '1', | ||||
| 				path, | ||||
| 			}, | ||||
| 		}; | ||||
| 	} | ||||
| 
 | ||||
| 	return false; | ||||
| }; | ||||
|  | @ -1 +1 @@ | |||
| export default '/actors/@actorId/*'; | ||||
| export default '/actor/@actorId/*'; | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| import { fetchLatest, fetchUpcoming, fetchNew } from '../../src/scenes'; | ||||
| import { fetchLatest, fetchUpcoming, fetchNew } from '#/src/scenes.js'; | ||||
| 
 | ||||
| async function fetchScenes(scope, page, limit) { | ||||
| 	if (scope === 'new') { | ||||
|  |  | |||
|  | @ -1,33 +1,20 @@ | |||
| import { resolveRoute } from 'vike/routing'; | ||||
| import { match } from 'path-to-regexp'; | ||||
| // import { resolveRoute } from 'vike/routing'; // eslint-disable-line import/extensions
 | ||||
| 
 | ||||
| const path = '/updates/:scope?/:page?'; | ||||
| const urlMatch = match(path, { decode: decodeURIComponent }); | ||||
| 
 | ||||
| export default (pageContext) => { | ||||
| 	{ | ||||
| 		const result = resolveRoute('/updates/@scope/@page', pageContext.urlPathname); | ||||
| 	const matched = urlMatch(pageContext.urlPathname); | ||||
| 
 | ||||
| 		if (result.match) { | ||||
| 			return result; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	{ | ||||
| 		const result = resolveRoute('/updates/@scope', pageContext.urlPathname); | ||||
| 
 | ||||
| 		if (result.match) { | ||||
| 			result.routeParams.page = '1'; | ||||
| 
 | ||||
| 			return result; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	{ | ||||
| 		const result = resolveRoute('/updates', pageContext.urlPathname); | ||||
| 
 | ||||
| 		if (result.match) { | ||||
| 			result.routeParams.scope = 'latest'; | ||||
| 			result.routeParams.page = '1'; | ||||
| 
 | ||||
| 			return result; | ||||
| 		} | ||||
| 	if (matched) { | ||||
| 		return { | ||||
| 			routeParams: { | ||||
| 				scope: matched.params.scope || 'latest', | ||||
| 				page: matched.params.page || '1', | ||||
| 				path, | ||||
| 			}, | ||||
| 		}; | ||||
| 	} | ||||
| 
 | ||||
| 	return false; | ||||
|  |  | |||
|  | @ -62,20 +62,23 @@ export async function fetchActorsById(actorIds) { | |||
| 			.groupBy('actors.id', 'avatars.id'), | ||||
| 	]); | ||||
| 
 | ||||
| 	return actorIds.map((actorId) => { | ||||
| 	const curatedActors = actorIds.map((actorId) => { | ||||
| 		const actor = actors.find((actorEntry) => actorEntry.id === actorId); | ||||
| 
 | ||||
| 		if (!actor) { | ||||
| 			console.warn(`Can't find ${actorId}`); | ||||
| 			return null; | ||||
| 		} | ||||
| 
 | ||||
| 		return curateActor(actor); | ||||
| 	}).filter(Boolean); | ||||
| 
 | ||||
| 	return curatedActors; | ||||
| } | ||||
| 
 | ||||
| function curateOptions(options) { | ||||
| 	if (options?.limit > 100) { | ||||
| 		throw new HttpError('Limit must be <= 100', 400); | ||||
| 	if (options?.limit > 120) { | ||||
| 		throw new HttpError('Limit must be <= 120', 400); | ||||
| 	} | ||||
| 
 | ||||
| 	return { | ||||
|  | @ -108,8 +111,6 @@ function buildQuery(filters) { | |||
| 
 | ||||
| 	['gender', 'country'].forEach((attribute) => { | ||||
| 		if (filters[attribute]) { | ||||
| 			console.log(attribute, filters[attribute]); | ||||
| 
 | ||||
| 			query.bool.must.push({ | ||||
| 				equals: { | ||||
| 					[attribute]: filters[attribute], | ||||
|  | @ -197,6 +198,9 @@ export async function fetchActors(filters, rawOptions) { | |||
| 	const options = curateOptions(rawOptions); | ||||
| 	const { query, expressions } = buildQuery(filters); | ||||
| 
 | ||||
| 	console.log(options); | ||||
| 	console.log('offset', (options.page - 1) * options.limit); | ||||
| 
 | ||||
| 	const result = await searchApi.search({ | ||||
| 		index: 'actors', | ||||
| 		query, | ||||
|  |  | |||
|  | @ -24,8 +24,6 @@ function curateScene(rawScene, assets) { | |||
| 		return null; | ||||
| 	} | ||||
| 
 | ||||
| 	console.log(assets.channel); | ||||
| 
 | ||||
| 	return { | ||||
| 		id: rawScene.id, | ||||
| 		title: rawScene.title, | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ export async function fetchActorsApi(req, res) { | |||
| 		total, | ||||
| 	} = await fetchActors(curateActorsQuery(req.query), { | ||||
| 		page: Number(req.query.page) || 1, | ||||
| 		limit: Number(req.query.limit) || 50, | ||||
| 		limit: Number(req.query.limit) || 120, | ||||
| 	}); | ||||
| 
 | ||||
| 	res.send({ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue