update
Some checks failed
/ build (push) Failing after 4m39s

This commit is contained in:
Jorge Vargas 2025-03-15 11:17:33 -06:00
parent 2575d45f0b
commit 0ec019f959
16 changed files with 209 additions and 34 deletions

View file

@ -11,6 +11,8 @@ import Toggler from './header/Toggler.astro'
import NavButton from './header/NavButton.astro'
import LoginNav from './header/LoginNav.astro'
import prismaClient from 'utils/prisma-client.js'
import { Icon } from 'astro-icon/components'
import SearchBar from './search/SearchBar.astro'
const { value: bannerId } = (await prismaClient.config.findUnique({ where: { name: 'banner' } })) ?? {}
const { value: bannerPosition } = (await prismaClient.config.findUnique({ where: { name: 'banner-position' } })) ?? {}
@ -42,7 +44,7 @@ const { session } = Astro.locals
<LoginNav />
</div>
</div>
<nav class='relative w-full md:h-[55px] bg-dark z-40'>
<div class='relative w-full md:h-[55px] bg-dark z-40'>
<Toggler>
<a href='/'><NavButton>{m.home()}</NavButton></a>
<a href='/last-added'><NavButton>{m.lastaddednav()}</NavButton></a>
@ -95,6 +97,8 @@ const { session } = Astro.locals
</>
) : null
}
<SearchBar />
</Toggler>
</nav>
</div>
</header>

View file

@ -33,13 +33,13 @@ export default function TrackList(props: Props) {
</div>
<div className=''>
<div className='col'>
<div className={clsx('border p-3 border-t-0', { 'border-t-2': discs.length === 1 })}>
<div className={clsx('border rounded-sm p-3 border-t-0', { 'border-t-2': discs.length === 1 })}>
<table className='gap-y-4' cellPadding='6'>
<tbody>
{discs.length > 0 &&
discs[current].body?.split('\n').map((track, i) => (
<tr key={i}>
<td>{i + 1} </td>
<td className='pr-1'>{(i + 1).toString().padStart(2, '0')}.</td>
<td>{track}</td>
</tr>
))}
@ -50,4 +50,4 @@ export default function TrackList(props: Props) {
</div>
</div>
)
}
}

View file

@ -1,8 +1,5 @@
---
import Button from '../Button'
import clsx from 'clsx'
const { class: className } = Astro.props
const { class: className, ...rest } = Astro.props
---
<button
@ -10,6 +7,7 @@ const { class: className } = Astro.props
'w-full md:w-fit md:h-full bg-dark hover:bg-gray py-3.5 md:py-1 px-2 rounded-none text-left md:text-center',
className
]}
{...rest}
>
<slot />
</button>

View file

@ -2,17 +2,11 @@
import { Icon } from 'astro-icon/components'
---
<nav-toggler
class='flex flex-col md:flex-row max-[990px]:justify-center min-[990px]:ps-20 size-full'
>
<nav-toggler class='flex flex-col md:flex-row max-[990px]:justify-center min-[990px]:px-12 size-full'>
<div class='md:hidden h-[52px]'>
<Icon
id='nav-toggler'
class='py-3.5 px-3.5 h-full w-auto fill-white cursor-pointer'
name='hamburger'
/>
<Icon id='nav-toggler' class='py-3.5 px-3.5 h-full w-auto fill-white cursor-pointer' name='hamburger' />
</div>
<div class='nav-items hidden md:block'>
<div class='nav-items hidden md:flex w-full'>
<slot />
</div>
</nav-toggler>

View file

@ -0,0 +1,72 @@
---
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'
interface Props {
query: string
}
const take = 20
const { query } = Astro.props
const findQuery: Prisma.albumsFindManyArgs = {
select: { title: true, releaseDate: true, id: true },
where: {
OR: [
{
title: {
search: query
.toLowerCase()
.split('_')
.map((w) => `+${w}`)
.join(' ')
}
},
{
subTitle: {
search: query
.toLowerCase()
.split('_')
.map((w) => `+${w}`)
.join(' ')
}
}
]
},
orderBy: { publishedAt: 'desc' }
}
const countQuery: Prisma.albumsCountArgs<DefaultArgs> = {
where: findQuery.where
}
const [count, search] = await Promise.all([
prismaClient.albums.count(countQuery),
prismaClient.albums.findMany({ ...findQuery, take })
])
---
<div class='text-xl'>Albums ({count}) {count > take ? `/ Showing first ${take} results` : null}</div>
<div class='grid sm:grid-cols-1 md:grid-cols-3 mt-1.5 gap-4'>
{
search.map((album) => (
<a class='flex bg-gray h-40 group hover:no-underline' href={`/album/${album.id}`}>
<div class='h-full w-40 shrink-0'>
<Image
class='object-cover'
src={`https://cdn.sittingonclouds.net/album/${album.id}.png`}
alt={`${album.title} cover`}
quality='low'
height={160}
width={160}
/>
</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>
</a>
))
}
</div>

View file

@ -0,0 +1,52 @@
---
import { Icon } from 'astro-icon/components'
import NavButton from 'components/header/NavButton.astro'
import { getRandom } from 'utils/form'
const placeholders = ['Tekken', 'Kingdom Hearts', 'The World Ends with You', 'Persona', 'Splatoon']
const placeholder = getRandom(placeholders)
---
<NavButton id='search-open' class='px-3.5 ml-auto' style={{ width: '55px', height: '55px' }}>
<Icon name='search' class='size-full' />
</NavButton>
<div id='search-bar' class='absolute bg-gray-hover/90 left-0 w-full h-full hidden text-white px-12 text-xl'>
<form id='search-form' class='grow pe-4'>
<input class='h-full w-full' type='text' placeholder={placeholder} required name='query' />
</form>
<NavButton id='search-close' class='shrink-0' style={{ width: '55px', height: '55px', backgroundColor: 'unset' }}>
<Icon name='close' class='size-full stroke-white' />
</NavButton>
</div>
<script>
const openButton = document.getElementById('search-open')
const searchBar = document.getElementById('search-bar')
const searchForm = document.getElementById('search-form') as HTMLFormElement
const closeButton = document.getElementById('search-close')
openButton?.addEventListener('click', () => {
searchBar?.classList.add('flex')
searchBar?.classList.remove('hidden')
openButton?.classList.add('hidden')
openButton?.classList.remove('block')
})
closeButton?.addEventListener('click', () => {
searchBar?.classList.add('hidden')
searchBar?.classList.remove('flex')
openButton?.classList.add('block')
openButton?.classList.remove('hidden')
})
searchForm?.addEventListener('submit', (ev: Event) => {
ev.preventDefault()
const formData = new FormData(searchForm)
const url = new URL('/search', window.location.origin)
url.searchParams.append('q', formData.get('query') as string)
window.location.href = url.toString()
})
</script>

13
src/img/icons/close.svg Normal file
View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_429_11083)">
<path d="M7 7.00006L17 17.0001M7 17.0001L17 7.00006" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_429_11083">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 496 B

4
src/img/icons/search.svg Normal file
View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11 6C13.7614 6 16 8.23858 16 11M16.6588 16.6549L21 21M19 11C19 15.4183 15.4183 19 11 19C6.58172 19 3 15.4183 3 11C3 6.58172 6.58172 3 11 3C15.4183 3 19 6.58172 19 11Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 488 B

View file

@ -73,10 +73,10 @@ const { currentLocale } = Astro
<Image
src={`https://cdn.sittingonclouds.net/album/${album?.id}.png`}
alt={`${album?.title} cover`}
class='rounded-sm size-full object-contain h-96'
class='rounded-sm size-full object-contain h-fit min-h-96 px-10'
quality='mid'
width={384}
height={384}
width={500}
height={500}
/>
</div>
</div>
@ -102,18 +102,20 @@ const { currentLocale } = Astro
{
(album?.artists.length ?? 0) > 0 && (
<tr>
<th>{m.artists()}</th>
<th class='mr-2'>{m.artists()}</th>
<td>{album?.artists.map(({ artist }) => artist.name).join(', ')}</td>
</tr>
)
}
<tr>
<th>{m.classification()}</th>
<th class='mr-2'>{m.classification()}</th>
<td>
{
[
album?.categories.map(({ categoryName }) => (m as any)[`${categoryName}Osts`]()).join(' & '),
album?.categories
.map(({ categoryName }) => m[`${categoryName}Osts` as keyof typeof m]())
.join(' & '),
album?.classifications.map(({ classificationName }) => classificationName).join(', ')
]
.filter((f) => f !== '')
@ -124,7 +126,7 @@ const { currentLocale } = Astro
{
album?.label && (
<tr>
<th>{m.publishedBy()}</th>
<th class='mr-2'>{m.publishedBy()}</th>
<td>
<a class='btn btn-link p-0' href={`/publisher/${album?.label}`}>
{album?.label}
@ -136,7 +138,7 @@ const { currentLocale } = Astro
{
(album?.platforms.length ?? 0) > 0 && (
<tr>
<th>{m.platforms()}</th>
<th class='mr-2'>{m.platforms()}</th>
<td>
{album?.platforms.map(({ platform }, i) => (
<Fragment key={platform.id}>
@ -159,7 +161,7 @@ const { currentLocale } = Astro
{
(album?.games.length ?? 0) > 0 && (
<tr>
<th>{m.games()}</th>
<th class='mr-2'>{m.games()}</th>
<td>
{album?.games.map(({ game }, i) => (
<Fragment key={game.slug}>
@ -176,7 +178,7 @@ const { currentLocale } = Astro
{
(album?.animations.length ?? 0) > 0 && (
<tr>
<th>{m.animations()}</th>
<th class='mr-2'>{m.animations()}</th>
<td>
{album?.animations.map(({ animation }, i) => (
<Fragment key={id}>
@ -192,13 +194,23 @@ const { currentLocale } = Astro
}
<tr>
<th>{m.avgRating()}</th>
<th class='mr-2'>{m.avgRating()}</th>
<td>
<!-- <StarCounter album?.Id={album?.id} /> -->
</td>
</tr>
</tbody>
</table>
{
album?.vgmdb && (
<div class='mt-2 mb-3 ml-2 flex'>
<span class='text-lg'>{m.checkVGMDB()}:</span>
<a href={album?.vgmdb} class='ml-2' target='_blank' rel='noopener noreferrer'>
<Image width={100} height={30} alt={'VGMdb'} src={vgmdbLogo} />
</a>
</div>
)
}
<!-- <UserButtons id={album?.id} /> -->
</div>
</div>

View file

@ -27,7 +27,7 @@ const lastAlbums = await prismaClient.albums.findMany({
<h1 class='uppercase font-medium tracking-wide text-5xl drop-shadow-2xl mt-5 mb-2 text-center'>
{m.recentReleases()}
</h1>
<div class='grid grid-cols-4 gap-x-1.5'>
<div class='grid grid-cols-2 md:grid-cols-4 gap-x-1.5'>
{
recentAlbums.map((album) => (
<AlbumBox title={album.title} href={`/album/${album.id}`} image={`/album/${album.id}.png`} />
@ -42,7 +42,7 @@ const lastAlbums = await prismaClient.albums.findMany({
<h1 class='uppercase font-medium tracking-wide text-5xl drop-shadow-2xl mt-5 mb-2 text-center'>
{m.lastAdded()}
</h1>
<div class='grid grid-cols-4 gap-x-1.5'>
<div class='grid grid-cols-2 md:grid-cols-4 gap-x-1.5'>
{
lastAlbums.map((album) => (
<AlbumBox title={album.title} href={`/album/${album.id}`} image={`/album/${album.id}.png`} />

View file

@ -39,7 +39,7 @@ const listProps = { fullPageList, page }
<h1 class='uppercase font-medium tracking-wide text-5xl drop-shadow-2xl mt-5 mb-2 text-center'>
{m.lastAdded()}
</h1>
<div class='grid grid-cols-4 gap-x-1.5'>
<div class='grid grid-cols-2 md:grid-cols-4 gap-x-1.5'>
{
lastAlbums.map((album) => (
<AlbumBox title={album.title} href={`/album/${album.id}`} image={`/album/${album.id}.png`} />

18
src/pages/search.astro Normal file
View file

@ -0,0 +1,18 @@
---
import AlbumSearch from 'components/search/AlbumSearch.astro'
import BaseLayout from 'layouts/base.astro'
const query = Astro.url.searchParams.get('q')
if (!query) 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'>
<AlbumSearch query={query} />
</div>
</div>
</div>
</BaseLayout>

View file

@ -21,3 +21,8 @@ export async function parseForm(request: Request) {
const data = JSON.parse(dataInput)
return { ...data, ...rest }
}
export function getRandom<T>(array: T[]): T {
const randomIndex = Math.floor(Math.random() * array.length)
return array[randomIndex]
}