Compare commits

...

5 commits

Author SHA1 Message Date
1cd11fea2b Improve multiple word search
Some checks failed
/ build (push) Has been cancelled
2025-05-01 20:44:20 -06:00
87b2fc0796 More strict search query parsing 2025-05-01 20:21:57 -06:00
d4423f465d
Merge pull request #9 from jorgev259/search-update
search update
2025-05-01 20:09:20 -06:00
4485529545 Add localization for search page 2025-05-01 20:08:31 -06:00
felipe
7005eec4c1 search update 2025-05-01 20:08:22 -06:00
5 changed files with 62 additions and 30 deletions

View file

@ -87,5 +87,8 @@
"latestReleases": "Latest releases",
"firstRelease": "First Release",
"newestRelease": "Newest Release",
"variousGames": "Various Games"
"variousGames": "Various Games",
"searchResultsFor": "Search results for",
"firstResults": "Showing first {take} results",
"moreResults": "Showing {start}-{end} results"
}

View file

@ -1,9 +1,11 @@
---
import * as m from 'paraglide/messages'
import type { Prisma } from '@prisma/client'
import type { DefaultArgs } from '@prisma/client/runtime/library'
import { Image } from 'astro:assets'
import prismaClient from 'utils/prisma-client'
import SearchNav from './SearchNav.astro'
interface Props {
query: string
@ -17,17 +19,17 @@ let { page } = Astro.props
if (page < 1) page = 1
const queryString = query
.toLowerCase()
.split('_')
.map((w) => `+${w}`)
.trim()
.split(/[\s_\-:]+/)
.join(' ')
const findQuery: Prisma.albumsFindManyArgs = {
select: { title: true, releaseDate: true, id: true },
where: {
OR: [{ title: { search: queryString } }, { subTitle: { search: queryString } }]
},
orderBy: {
_relevance: { fields: ['title', 'subTitle'], sort: 'desc', search: query.toLowerCase() }
_relevance: { fields: ['title', 'subTitle'], sort: 'desc', search: queryString }
}
}
const countQuery: Prisma.albumsCountArgs<DefaultArgs> = {
@ -38,26 +40,18 @@ const [count, search] = await Promise.all([
prismaClient.albums.count(countQuery),
prismaClient.albums.findMany({ ...findQuery, take, skip: (page - 1) * take })
])
const start = (page - 1) * take
const end = Math.min(page * take, count)
---
<div class='text-xl flex gap-x-4'>
<div>
Albums ({count}) {
count > take ? (
<span>
{' '}
/ Showing {page === 1 ? `first ${take}` : `${(page - 1) * take}-${Math.min(page * take, count)}`} results
</span>
) : null
}
</div>
<div class='flex gap-x-2'>
{
Array.from({ length: Math.ceil(count / take) }, (_, i) =>
page === i + 1 ? <span>{i + 1}</span> : <a href={`/search?q=${query}&page=${i + 1}`}>{i + 1}</a>
)
}
</div>
<div class='text-xl'>
{m.albums()} ({count}) {
count > take ? <span> / {page === 1 ? m.firstResults({ take }) : m.moreResults({ start, end })}</span> : null
}
</div>
<div class='flex gap-x-2'>
<SearchNav query={query} count={count} take={take} page={page} />
</div>
<div class='grid grid-cols-1 md:grid-cols-3 mt-1.5 gap-4'>
{
@ -75,9 +69,13 @@ const [count, search] = await Promise.all([
</div>
<div class='flex flex-col p-2.5 justify-center text-left'>
<div class=' text-link group-hover:underline'>{album.title}</div>
<div class='mt-0.5'>{album.releaseDate?.toISOString().split('T')[0]}</div>
<div class='text-sm text-slate-100 mt-0.5'>{album.releaseDate?.toISOString().split('T')[0]}</div>
</div>
</a>
))
}
</div>
<div class='flex gap-x-2'>
<SearchNav query={query} count={count} take={take} page={page} />
</div>

View file

@ -44,8 +44,12 @@ const placeholder = getRandom(placeholders)
searchForm?.addEventListener('submit', (ev: Event) => {
ev.preventDefault()
const formData = new FormData(searchForm)
const query = (formData.get('query') as string).trim()
if (!query || query.length < 1) return
const url = new URL('/search', window.location.origin)
url.searchParams.append('q', formData.get('query') as string)
url.searchParams.append('q', query)
window.location.href = url.toString()
})

View file

@ -0,0 +1,25 @@
---
interface Props {
count: number
take: number
page: number
query: string
}
const { count, take, page, query } = Astro.props
const pageCount = Math.ceil(count / take)
---
{
pageCount > 1
? Array.from({ length: pageCount }, (_, i) =>
page === i + 1 ? (
<span class='text-xl bg-gray rounded px-2 cursor-pointer'>{i + 1}</span>
) : (
<a class='text-xl bg-gray/50 rounded px-2' href={`/search?q=${query}&page=${i + 1}`}>
{i + 1}
</a>
)
)
: null
}

View file

@ -1,18 +1,20 @@
---
import * as m from 'paraglide/messages'
import AlbumSearch from 'components/search/AlbumSearch.astro'
import BaseLayout from 'layouts/base.astro'
const query = Astro.url.searchParams.get('q')
const page = Astro.url.searchParams.get('page') || "1"
const query = (Astro.url.searchParams.get('q') ?? '').trim()
const page = Astro.url.searchParams.get('page') || '1'
if (!query) return Astro.redirect(404)
if (!query || query.length < 1) return Astro.redirect(404)
---
<BaseLayout>
<div class='w-full bg-dark'>
<div class='flex max-w-[1200px] mx-auto justify-center px-8 py-3 flex-col'>
<div class='py-4 px-4 bg-gray text-3xl text- w-full font-normal mt-2'>Search results for: {query}</div>
<div class='mt-5'>
<div class='py-4 px-4 bg-gray text-3xl text- w-full font-normal mt-2'>{m.searchResultsFor()}: {query}</div>
<div class='mt-5 flex flex-col gap-y-2'>
<AlbumSearch query={query} page={parseInt(page)} />
</div>
</div>