forked from polka_billy/porridger
104 lines
3.6 KiB
TypeScript
104 lines
3.6 KiB
TypeScript
import { Link } from 'react-router-dom'
|
||
import { useEffect, useLayoutEffect, useRef, useState } from 'react'
|
||
import { Button } from 'react-bootstrap'
|
||
|
||
import { UserCategory, composeUserCategoriesFilters, userCategoriesInfos } from '../assets/userCategories'
|
||
import { Announcement } from '../api/announcement/types'
|
||
import { categoryGraphics, categoryNames } from '../assets/category'
|
||
import { URLEncodeFilters } from '../utils/filters'
|
||
|
||
import rightAngleIcon from '../assets/rightAngle.svg'
|
||
|
||
import styles from '../styles/StoriesPreview.module.css'
|
||
|
||
type StoriesPreviewProps = {
|
||
announcements: Announcement[],
|
||
category: UserCategory,
|
||
}
|
||
|
||
const StoriesPreview = ({ announcements, category }: StoriesPreviewProps) => (
|
||
announcements.map((ann, i) => (
|
||
<li key={`${category}${i}`}>
|
||
<Link to={'/?' + new URLSearchParams({
|
||
...URLEncodeFilters(composeUserCategoriesFilters[category]()),
|
||
storyIndex: i.toString(),
|
||
}).toString()} className={styles.link}>
|
||
{ann.src?.endsWith('mp4') ? (
|
||
<video src={ann.src} className={styles.image} />
|
||
) : (
|
||
<img
|
||
src={ann.src || categoryGraphics[ann.category]}
|
||
alt={'Изображение' + (ann.src ? 'предмета' : categoryNames[ann.category])}
|
||
className={styles.image}
|
||
/>
|
||
)}
|
||
<p className={styles.title}>{ann.name}</p>
|
||
<p className={styles.title}>{userCategoriesInfos[category](ann)}</p>
|
||
</Link>
|
||
</li>
|
||
))
|
||
)
|
||
|
||
function StoriesPreviewCarousel({ announcements, category }: StoriesPreviewProps) {
|
||
const ulElement = useRef<HTMLUListElement | null>(null)
|
||
const [showScrollButtons, setShowScrollButtons] = useState({ left: false, right: false })
|
||
|
||
const determineShowScrollButtons = (ul: HTMLUListElement) => (
|
||
setShowScrollButtons({
|
||
left: ul.scrollLeft > 0,
|
||
right: ul.scrollLeft < (ul.scrollWidth - ul.clientWidth),
|
||
})
|
||
)
|
||
|
||
useEffect(() => {
|
||
const ul = ulElement.current
|
||
if (ul) {
|
||
determineShowScrollButtons(ul)
|
||
|
||
const f = () => determineShowScrollButtons(ul)
|
||
|
||
ul.addEventListener('scroll', f)
|
||
|
||
return () => ul.removeEventListener('scroll', f)
|
||
}
|
||
}, [])
|
||
|
||
useLayoutEffect(() => {
|
||
const ul = ulElement.current
|
||
|
||
if (ul) {
|
||
determineShowScrollButtons(ul)
|
||
}
|
||
}, [announcements])
|
||
|
||
const doScroll = (forward: boolean) => () => {
|
||
const ul = ulElement.current
|
||
if (ul) {
|
||
const storyWidth = window.innerHeight * 0.25 * 9 / 16 + 10
|
||
ul.scrollLeft += forward ? storyWidth : -storyWidth
|
||
}
|
||
}
|
||
|
||
return <div className={styles.container}>
|
||
{showScrollButtons.left &&
|
||
<Button onClick={doScroll(false)} className={`${styles.scrollButton} ${styles.leftScrollButton}`}>
|
||
<img src={rightAngleIcon} alt='Показать ещё' />
|
||
</Button>
|
||
}
|
||
|
||
{announcements.length > 0 ? (
|
||
<ul className={styles.list} ref={ulElement}>
|
||
<StoriesPreview announcements={announcements} category={category} />
|
||
</ul>
|
||
) : (
|
||
<p>Здесь пока пусто</p>
|
||
)}
|
||
{showScrollButtons.right &&
|
||
<Button onClick={doScroll(true)} className={`${styles.scrollButton} ${styles.rightScrollButton}`}>
|
||
<img src={rightAngleIcon} alt='Показать ещё' />
|
||
</Button>
|
||
}
|
||
</div>
|
||
}
|
||
|
||
export default StoriesPreviewCarousel |