70 lines
1.8 KiB
TypeScript
70 lines
1.8 KiB
TypeScript
import { useMemo, useState } from 'react'
|
|
import type { CSSProperties } from 'react'
|
|
import { useGameInput } from '../../input/useGameInput'
|
|
import { ARHud } from './ARHud'
|
|
import { SONGS } from './song-data'
|
|
import { SongCarousel } from './SongCarousel'
|
|
import { SongInfoBar } from './SongInfoBar'
|
|
import { lighten, withAlpha } from './color-utils'
|
|
import './SongSelectScreen.css'
|
|
|
|
function wrapIndex(index: number, length: number): number {
|
|
return (index + length) % length
|
|
}
|
|
|
|
export function SongSelectScreen() {
|
|
const [currentIndex, setCurrentIndex] = useState(0)
|
|
const activeSong = SONGS[currentIndex]
|
|
const handleConfirm = () => {}
|
|
|
|
useGameInput((action) => {
|
|
if (action === 'LEFT') {
|
|
setCurrentIndex((prev) => wrapIndex(prev - 1, SONGS.length))
|
|
}
|
|
|
|
if (action === 'RIGHT') {
|
|
setCurrentIndex((prev) => wrapIndex(prev + 1, SONGS.length))
|
|
}
|
|
|
|
if (action === 'BUTTON_A') {
|
|
handleConfirm()
|
|
}
|
|
})
|
|
|
|
const cssVars = useMemo(
|
|
() =>
|
|
({
|
|
'--song-color': activeSong.color,
|
|
'--song-color-soft': withAlpha(activeSong.color, 0.24),
|
|
'--song-color-highlight': lighten(activeSong.color, 0.42),
|
|
}) as CSSProperties,
|
|
[activeSong.color],
|
|
)
|
|
|
|
return (
|
|
<main className="song-select-screen" style={cssVars}>
|
|
<ARHud
|
|
currentTrack={currentIndex + 1}
|
|
totalTracks={SONGS.length}
|
|
genre={activeSong.genre}
|
|
difficulty={activeSong.difficulty}
|
|
/>
|
|
|
|
<div className="song-select-screen__content">
|
|
<h1 className="song-select-screen__title font-title">SONG SELECT</h1>
|
|
|
|
<SongCarousel
|
|
songs={SONGS}
|
|
currentIndex={currentIndex}
|
|
onSelectIndex={setCurrentIndex}
|
|
/>
|
|
|
|
<SongInfoBar
|
|
song={activeSong}
|
|
onConfirm={handleConfirm}
|
|
/>
|
|
</div>
|
|
</main>
|
|
)
|
|
}
|