Implement header component

This commit is contained in:
Jorge Vargas 2024-08-26 13:16:15 -06:00
parent 1928366081
commit d2431c41c6
28 changed files with 951 additions and 11268 deletions

View file

@ -0,0 +1,12 @@
---
const { class: className } = Astro.props
---
<button
class:list={[
'bg-blue-600 hover:bg-blue-700 py-2 px-3.5 rounded-lg',
className
]}
>
<slot />
</button>

103
src/components/Header.astro Normal file
View file

@ -0,0 +1,103 @@
---
import { gql } from '@/graphql/__generated__/client'
import { getApolloClient } from '@/graphql/apolloClient.mjs'
import { Image } from 'astro:assets'
import { getSession } from 'auth-astro/server'
import * as m from '../paraglide/messages.js'
import logo from '@/img/logos/winter.png'
// import logoEs from '@/img/logos/default_es.png'
import Button from './Button.astro'
import Dropdown from './header/Dropdown.astro'
import DropdownItem from './header/DropdownItem.astro'
import Toggler from './header/Toggler.astro'
import NavButton from './header/NavButton.astro'
const headerQuery = gql(`
query HeaderInfo {
config(name: "banner") {
value
}
}
`)
const client = await getApolloClient()
const { data: headerInfo } = await client.query({ query: headerQuery })
const session = await getSession(Astro.request)
---
<header class='relative'>
<div
class='h-[150px] bg-top bg-no-repeat bg-cover'
style={{
backgroundImage: `url(https://cdn.sittingonclouds.net/live/${headerInfo.config.value}.png)`
}}
>
<div class='relative px-20 size-full'>
<a href='/'>
<Image
src={logo}
class='h-full py-0.5 w-auto'
alt='logo'
height={150}
width={265}
/>
</a>
<div class='absolute top-0 right-0 space-x-2 mr-10'>
{
session === null ? (
<Button class='rounded-t-none'>{m.login()}</Button>
) : (
<Button class='rounded-t-none'>{m.logout()}</Button>
)
}
<Button class='rounded-t-none'>{m.register()}</Button>
</div>
</div>
</div>
<nav class='w-full md:h-[55px] bg-dark'>
<Toggler>
<a href='/'><NavButton>{m.home()}</NavButton></a>
<a href='/last-added'><NavButton>{m.lastaddednav()}</NavButton></a>
<a href='/album/list'><NavButton>{m.albumlist()}</NavButton></a>
<Dropdown>
{m.games()}
<Fragment slot='items'>
<DropdownItem href='/game'>{m.albums()}</DropdownItem>
<DropdownItem href='/series'>{m.series()}</DropdownItem>
<DropdownItem href='/publisher/list'>{m.publishers()}</DropdownItem>
<DropdownItem href='/platforms/list'>{m.platforms()}</DropdownItem>
<DropdownItem href='/game/list'>{m.gamelist()}</DropdownItem>
</Fragment>
</Dropdown>
<Dropdown>
{m.animation()}
<Fragment slot='items'>
<DropdownItem href='/anim'>{m.albums()}</DropdownItem>
<DropdownItem href='/anim/list'>{m.animationlist()}</DropdownItem>
<DropdownItem href='/studio/list'>{m.studios()}</DropdownItem>
</Fragment>
</Dropdown>
<!-- <a href='/requests'><NavButton>{m.requests()}</NavButton></a>
<a href='#'><NavButton>{m.submitalbum()}</NavButton></a> -->
<!-- <Dropdown>
{m.admingrounds()}
<Fragment slot='items'>
<DropdownItem href='/admin'>{m.managealbums()}</DropdownItem>
<DropdownItem href='/admin/user'>{m.manageusers()}</DropdownItem>
<DropdownItem href='/admin/request'>{m.managerequests()}</DropdownItem>
<DropdownItem href='/admin/submission'
>{m.managesubmissions()}</DropdownItem
>
</Fragment>
</Dropdown> -->
</Toggler>
</nav>
</header>

View file

@ -0,0 +1,33 @@
---
import NavButton from './NavButton.astro'
---
<nav-dropdown>
<NavButton class='dropdown-btn group relative'>
<div class='after:content-["▼"] after:text-xs'><slot /></div>
<div
class='dropdown-items md:absolute flex-col bg-gray hidden md:group-hover:flex top-full left-0 py-1 min-w-36 rounded-md md:rounded-t-none mt-1.5 md:mt-0'
>
<slot name='items' />
</div>
</NavButton>
</nav-dropdown>
<script>
class Dropdown extends HTMLElement {
constructor() {
super()
const button = this.querySelector('.dropdown-btn')
const items = this.querySelector('.dropdown-items')
button.addEventListener('click', () => {
console.log('click')
items.classList.toggle('hidden')
items.classList.toggle('flex')
})
}
}
customElements.define('nav-dropdown', Dropdown)
</script>

View file

@ -0,0 +1,10 @@
---
const { class: className, href } = Astro.props
---
<a
href={href}
class:list={['hover:bg-gray-hover py-1 text-left ps-4', className]}
>
<slot />
</a>

View file

@ -0,0 +1,14 @@
---
import Button from '../Button.astro'
const { class: className } = Astro.props
---
<Button
class:list={[
'w-full md:w-fit md:h-full bg-dark hover:bg-dark-hover py-3.5 md:py-1 px-2 rounded-none text-left md:text-center',
className
]}
>
<slot />
</Button>

View file

@ -0,0 +1,35 @@
---
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'
>
<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'
/>
</div>
<div class='nav-items hidden md:block'>
<slot />
</div>
</nav-toggler>
<script>
class Toggler extends HTMLElement {
constructor() {
super()
const items = this.querySelector('.nav-items')
const btn = document.getElementById('nav-toggler')
btn.addEventListener('click', () => {
items.classList.toggle('hidden')
})
}
}
customElements.define('nav-toggler', Toggler)
</script>

1
src/env.d.ts vendored
View file

@ -1 +1,2 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />

View file

@ -1,15 +1,16 @@
import merge from 'lodash/merge'
import search from './search'
import site from './site'
/*
import album from './album'
import requests from './requests'
import site from './site'
import user from './user'
import vgmdb from './vgmdb'
*/
const queries = merge(search/*album, requests, search, site, user, vgmdb*/)
const queries = merge(search, site)
export default queries

View file

@ -1,12 +1,18 @@
import fg from 'fast-glob'
// import fg from 'fast-glob'
import type { Resolvers } from '@/graphql/__generated__/types.generated'
import { composeResolvers } from '@graphql-tools/resolvers-composition'
import { hasRole } from '@/server/utils/resolvers'
// import { hasRole } from '@/server/utils/resolvers'
const resolversComposition = { 'Query.banners': hasRole('UPDATE') }
const resolvers = {
const resolversComposition = {
/* 'Query.banners': hasRole('UPDATE') */
}
const resolvers: Resolvers = {
Query: {
config: (parent, { name }, { db }, info) => {
config: (_, args, context) => {
const { name } = args
const { db } = context
return db.models.config
.findOrCreate({ where: { name } })
.then(() => db.models.config.findByPk(name))
@ -17,12 +23,12 @@ const resolvers = {
return db.models.album.findByPk(value)
},
banners: async (parent, args) => {
const filePaths = await fg(['/var/www/soc_img/img/live/**/*.png'])
const images = filePaths.map((f) => f.split('/').pop())
/* banners: async (parent, args) => {
const filePaths = await fg(['/var/www/soc_img/img/live/**/ /**.png'])
const images = filePaths.map((f) => f.split('/').pop())
return images
},
return images
}, */
recentComments: async (parent, { limit = 5 }, { db }) => {
return db.models.comment.findAll({

View file

@ -0,0 +1,6 @@
<?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.5 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 12.32H22" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2 18.32H22" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2 6.32001H22" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 553 B

BIN
src/img/logos/default.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
src/img/logos/winter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

36
src/layouts/base.astro Normal file
View file

@ -0,0 +1,36 @@
---
import { languageTag } from '../paraglide/runtime'
import Header from '@/components/Header.astro'
import '@/styles/global.css'
---
<html lang={languageTag()} dir={Astro.locals.paraglide.dir} class='h-full'>
<head>
<title>Sitting on Clouds</title>
<meta property='og:type' content='website' />
<meta property='og:site_name' content='Sitting on Clouds' />
<meta name='theme-color' content='#ffffff' />
<meta property='og:url' content='/' />
<meta
property='og:title'
content='Sitting on Clouds — High Quality soundtrack library'
/>
<meta
property='og:description'
content='Largest Video Game & Animation Soundtrack サウンドトラック Archive'
/>
<meta property='og:image' content='/img/assets/clouds_thumb.png' />
<meta name='generator' content={Astro.generator} />
<meta charset='utf-8' />
</head>
<body class='flex flex-col min-h-full m-0 color-'>
<Header />
<main class='flex-1'>
<slot />
</main>
<footer>This is the footer</footer>
</body>
</html>

View file

@ -1,16 +1,7 @@
---
import { languageTag } from '../paraglide/runtime'
import BaseLayout from '@/layouts/base.astro'
---
<html lang={languageTag()} dir={Astro.locals.paraglide.dir}>
<head>
<meta charset='utf-8' />
<link rel='icon' type='image/svg+xml' href='/favicon.svg' />
<meta name='viewport' content='width=device-width' />
<meta name='generator' content={Astro.generator} />
<title>Astro</title>
</head>
<body>
<h1>Astro</h1>
</body>
</html>
<BaseLayout />

3
src/styles/global.css Normal file
View file

@ -0,0 +1,3 @@
* {
color: white;
}