mirror of
https://github.com/jorgev259/soc_site-astro.git
synced 2025-06-29 07:57:41 +00:00
Implement sidebar Comment Carousel
This commit is contained in:
parent
56c56c9877
commit
fd696a59b4
4 changed files with 98 additions and 0 deletions
|
|
@ -11,6 +11,7 @@ import SidebarSection from './sidebar/SidebarSection.astro'
|
|||
import Highlight from './sidebar/Highlight.astro'
|
||||
import AlbumBox from './AlbumBox.astro'
|
||||
import AlbumCount from './sidebar/AlbumCount.astro'
|
||||
import CommentCarousel from './sidebar/CommentCarousel.astro'
|
||||
|
||||
const listClass =
|
||||
'uppercase text-3xl font-semibold w-full text-center py-3 hover:bg-dark-hover hover:text-cyan-400 hover:underline'
|
||||
|
|
@ -48,6 +49,9 @@ const listClass =
|
|||
<AlbumBox loading />
|
||||
</SidebarSection>
|
||||
</Highlight>
|
||||
<CommentCarousel>
|
||||
<SidebarSection slot='fallback' class='h-24 animate-pulse' />
|
||||
</CommentCarousel>
|
||||
<AlbumCount server:defer>
|
||||
<SidebarSection slot='fallback' class='h-32 animate-pulse' />
|
||||
</AlbumCount>
|
||||
|
|
|
|||
27
src/components/sidebar/CommentCarousel.astro
Normal file
27
src/components/sidebar/CommentCarousel.astro
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
import prismaClient from 'utils/prisma-client'
|
||||
import { Icon } from 'astro-icon/components'
|
||||
|
||||
import SidebarSection from './SidebarSection.astro'
|
||||
import Looper from './CommentCarousel/Looper'
|
||||
|
||||
const comments = await prismaClient.comments.findMany({
|
||||
select: { text: true, albums: { select: { id: true, title: true } } },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 5
|
||||
})
|
||||
---
|
||||
|
||||
<SidebarSection>
|
||||
<Looper comments={comments} client:only='react'>
|
||||
<Icon name='arrow-right' slot='arrowRight' class='group-hover:fill-black' height={30} width={15} fill='white' />
|
||||
<Icon
|
||||
name='arrow-right'
|
||||
slot='arrowLeft'
|
||||
class='group-hover:fill-black scale-x-[-1]'
|
||||
height={30}
|
||||
width={15}
|
||||
fill='white'
|
||||
/>
|
||||
</Looper>
|
||||
</SidebarSection>
|
||||
58
src/components/sidebar/CommentCarousel/Looper.tsx
Normal file
58
src/components/sidebar/CommentCarousel/Looper.tsx
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import clsx from 'clsx'
|
||||
import { useEffect, useRef, useState, type ButtonHTMLAttributes, type ReactNode } from 'react'
|
||||
|
||||
interface Props {
|
||||
comments: {
|
||||
text: string | null
|
||||
albums: {
|
||||
id: number
|
||||
title: string | null
|
||||
} | null
|
||||
}[]
|
||||
}
|
||||
|
||||
function ArrowButton(props: ButtonHTMLAttributes<HTMLButtonElement>) {
|
||||
const { className, ...rest } = props
|
||||
|
||||
return <button className={clsx('flex-0 px-2 py-2 border rounded-md hover:bg-white group', className)} {...rest} />
|
||||
}
|
||||
|
||||
export default function Looper(props: Props) {
|
||||
//@ts-ignore
|
||||
const { comments, arrowRight, arrowLeft } = props
|
||||
const [index, setIndex] = useState(0)
|
||||
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
|
||||
const nextIndex = index === comments.length - 1 ? 0 : index + 1
|
||||
const pastIndex = index === 0 ? comments.length - 1 : index - 1
|
||||
const isMultiple = comments.length >= 2
|
||||
const comment = comments[index]
|
||||
|
||||
useEffect(() => {
|
||||
if (timeoutRef.current) clearTimeout(timeoutRef.current)
|
||||
timeoutRef.current = setTimeout(() => setIndex(nextIndex), 10 * 1000)
|
||||
}, [index])
|
||||
|
||||
return (
|
||||
<div className='text-md/6 font-extralight'>
|
||||
<div>{comment.text}</div>
|
||||
<div className='mt-1'>
|
||||
-{' '}
|
||||
<a href={`/album/${comment.albums?.id}`} className='hover:text-hover-link hover:underline'>
|
||||
{comment.albums?.title}
|
||||
</a>
|
||||
</div>
|
||||
{isMultiple ? (
|
||||
<div className='flex mt-2.5'>
|
||||
<ArrowButton onClick={() => setIndex(pastIndex)}>{arrowLeft}</ArrowButton>
|
||||
<div className='flex-1 text-center content-center'>
|
||||
{index + 1} / {comments.length}
|
||||
</div>
|
||||
<ArrowButton onClick={() => setIndex(nextIndex)}>{arrowRight}</ArrowButton>
|
||||
</div>
|
||||
) : (
|
||||
false
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
9
src/img/icons/arrow-right.svg
Normal file
9
src/img/icons/arrow-right.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 330 330" xml:space="preserve">
|
||||
<path id="XMLID_222_" d="M250.606,154.389l-150-149.996c-5.857-5.858-15.355-5.858-21.213,0.001
|
||||
c-5.857,5.858-5.857,15.355,0.001,21.213l139.393,139.39L79.393,304.394c-5.857,5.858-5.857,15.355,0.001,21.213
|
||||
C82.322,328.536,86.161,330,90,330s7.678-1.464,10.607-4.394l149.999-150.004c2.814-2.813,4.394-6.628,4.394-10.606
|
||||
C255,161.018,253.42,157.202,250.606,154.389z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 698 B |
Loading…
Add table
Add a link
Reference in a new issue