Split MizikList and add GroupedVirtuoso

This commit is contained in:
2023-07-22 13:45:08 +04:00
parent 164e0d621b
commit ffe3421fa9
3 changed files with 161 additions and 101 deletions
+25 -20
View File
@@ -21,19 +21,19 @@ import {green} from '@mui/material/colors'
import ExpandMoreIcon from '@mui/icons-material/ExpandMore' import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import KeyboardBackspaceIcon from '@mui/icons-material/KeyboardBackspace' import KeyboardBackspaceIcon from '@mui/icons-material/KeyboardBackspace'
import {formatKuveti} from '../../lib/kuveti'
import AwtisBiyografi from './awtis-biyografi' import AwtisBiyografi from './awtis-biyografi'
import MizikLis from './mizik-lis' import MizikLyen from './mizik-lyen'
const IMAGE_URL = process.env.NEXT_PUBLIC_API_URL_ROOT || 'http://localhost:1337' const IMAGE_URL = process.env.NEXT_PUBLIC_API_URL_ROOT || 'http://localhost:1337'
const noImageUrl = 'https://place-hold.it/140x140?text=Indisponible' const noImageUrl = 'https://place-hold.it/140x140?text=Indisponible'
const sortTeks = paroles => paroles.sort((a, b) => b.id - a.id) const sortTeks = paroles => paroles.sort((a, b) => a.attributes.titre.localeCompare(b.attributes.titre, 'fr', {sensitivity: 'base'}))
export default function AwtisDetay({anAwtis}) { export default function AwtisDetay({anAwtis}) {
const router = useRouter()
const [esByografiOuve, meteEsByografiOuve] = useState(false) const [esByografiOuve, meteEsByografiOuve] = useState(false)
const {alias, biographie, paroles, photo} = anAwtis const {alias, biographie, paroles, photo} = anAwtis
const sortedTeks = sortTeks(paroles.data) const sortedTeks = sortTeks(paroles?.data)
const gwanBiyo = biographie && biographie.length > 100 const gwanBiyo = biographie && biographie.length > 100
const biyo = gwanBiyo ? `${biographie.slice(0, 100)}...` : biographie const biyo = gwanBiyo ? `${biographie.slice(0, 100)}...` : biographie
@@ -42,12 +42,6 @@ export default function AwtisDetay({anAwtis}) {
meteEsByografiOuve(true) meteEsByografiOuve(true)
} }
const handleBack = () => {
const href = '/awtis?paj&paj=1'
const as = '/awtis/paj/1'
router.push(href, as)
}
return ( return (
<Container> <Container>
<Box sx={{marginBlock: 2}}> <Box sx={{marginBlock: 2}}>
@@ -64,7 +58,7 @@ export default function AwtisDetay({anAwtis}) {
</Box> </Box>
<Grid container direction='column' justifyContent='center' alignItems='center' spacing={3}> <Grid container direction='column' justifyContent='center' alignItems='center' spacing={3}>
{biyo && ( {biyo && (
<Grid item xs={12} md={6}> <Grid xs={12} md={6}>
<Card sx={{minWidth: 300}}> <Card sx={{minWidth: 300}}>
<CardActionArea onClick={handleClick}> <CardActionArea onClick={handleClick}>
<CardContent> <CardContent>
@@ -79,7 +73,7 @@ export default function AwtisDetay({anAwtis}) {
</Card> </Card>
</Grid> </Grid>
)} )}
<Grid item xs={12} md={6}> <Grid xs={12} md={6}>
<Box marginBottom={3}> <Box marginBottom={3}>
{paroles.data.length > 1 ? ( {paroles.data.length > 1 ? (
<Accordion> <Accordion>
@@ -91,29 +85,40 @@ export default function AwtisDetay({anAwtis}) {
<Typography marginRight={2} textAlign='center' variant='body1' component='h2'><strong>Liste des paroles</strong></Typography> <Typography marginRight={2} textAlign='center' variant='body1' component='h2'><strong>Liste des paroles</strong></Typography>
<Chip color='primary' label={paroles.data.length} size='small' variant='contained' /> <Chip color='primary' label={paroles.data.length} size='small' variant='contained' />
</AccordionSummary> </AccordionSummary>
<AccordionDetails> <AccordionDetails sx={{paddingInline: 0}}>
<MizikLis paroles={sortedTeks} /> {sortedTeks.map(anPawol => {
const {couverture} = anPawol.attributes
const kuvetiFormat = formatKuveti(couverture)
return (
<Box key={anPawol.id} sx={{paddingBlock: 0.5}}>
<MizikLyen anPawol={anPawol} kuveti={kuvetiFormat} />
</Box>
)
})}
</AccordionDetails> </AccordionDetails>
</Accordion> </Accordion>
) : ( ) : (
paroles.data.length === 0 ? ( paroles.data.length === 0 ? (
<Typography gutterBottom textAlign='center' variant='body1' component='h2'><strong>Aucune parole pour le moment</strong></Typography> <Typography gutterBottom textAlign='center' variant='body1' component='h2'><strong>Aucune parole pour le moment</strong></Typography>
) : ( ) : (
<> <Box>
<Typography gutterBottom textAlign='center' variant='body1' component='h2'><strong>Parole</strong></Typography> <Typography gutterBottom textAlign='center' variant='body1' component='h2'><strong>Parole</strong></Typography>
<Paper> <Paper sx={{height: '100%', paddingBlock: 2}}>
<MizikLis paroles={paroles.data} /> <MizikLyen anPawol={paroles.data[0]} kuveti={formatKuveti(paroles.data[0].attributes.couverture)} />
</Paper> </Paper>
</> </Box>
) )
)} )}
</Box> </Box>
</Grid> </Grid>
</Grid> </Grid>
<Box sx={{textAlign: 'center', marginBottom: 2}} > <Box sx={{textAlign: 'center', marginBlock: 3}} >
<Button variant='outlined' startIcon={<KeyboardBackspaceIcon />} onClick={handleBack}> <Link passHref href='/awtis'>
<Button variant='outlined' startIcon={<KeyboardBackspaceIcon />}>
Retour aux artistes Retour aux artistes
</Button> </Button>
</Link>
</Box> </Box>
{esByografiOuve && ( {esByografiOuve && (
<AwtisBiyografi <AwtisBiyografi
+77 -78
View File
@@ -1,95 +1,94 @@
'use client'
import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import {useRouter} from 'next/router' import {useParams} from 'next/navigation'
import {GroupedVirtuoso} from 'react-virtuoso'
import List from '@mui/material/List'
import ListItem from '@mui/material/ListItem'
import ListSubheader from '@mui/material/ListSubheader'
import {styled} from '@mui/material/styles' import {groupBy} from 'lodash'
import {List, ListItem, ListItemText} from '@mui/material' import {formatKuveti} from '../../lib/kuveti'
import FiberNewOutlinedIcon from '@mui/icons-material/FiberNewOutlined' import MizikLyen from './mizik-lyen'
import LibraryMusicIcon from '@mui/icons-material/LibraryMusic'
import ExplicitIcon from '@mui/icons-material/Explicit'
import {Peertube} from '@icons-pack/react-simple-icons'
import {esBrandNew} from '../../lib/date' function grupPawol(pawol) {
import {getAlias} from '../../lib/utils/format' const pawolTrie = pawol.sort((a, b) => a.attributes.titre.localeCompare(b.attributes.titre, 'fr', {sensitivity: 'base'}))
const grupPawol = groupBy(pawol, anPawol => anPawol.attributes.titre[0].toUpperCase())
const grupCounts = Object.values(grupPawol).map(anPawol => anPawol.length)
const grup = Object.keys(grupPawol)
grup.sort((a, b) => a[0].localeCompare(b[0], 'fr', {sensitivity: 'base'}))
const PREFIX = 'mizik-lis' return {pawol: pawolTrie, grupCounts, grup}
const classes = {
root: `${PREFIX}-root`
} }
const StyledList = styled(List)(( export default function MizikLis({niAwtis, paroles}) {
{ const params = useParams()
theme const {pawol, grupCounts, grup} = grupPawol(paroles)
}
) => ({
[`&.${classes.root}`]: {
width: '100%',
maxWidth: 360,
backgroundColor: theme.palette.background.paper
}
}))
export default function MizikLis({meteEsMobilOuve, niAwtis, paroles, slugTeksChwazi, meteSlugTeksChwazi}) {
const router = useRouter()
const handleClick = slug => {
if (meteSlugTeksChwazi) {
meteSlugTeksChwazi(slug)
}
if (slug !== slugTeksChwazi) {
if (niAwtis) {
router.push(`/paroles/${slug}`).then(() => window.scrollTo(0, 0))
} else {
router.push(`/paroles/${slug}#${slug}`).then(() => window.scrollTo(0, 0))
}
}
if (meteEsMobilOuve) {
meteEsMobilOuve(false)
}
}
return ( return (
<StyledList component='nav' className={classes.root} aria-label='mizik'> <GroupedVirtuoso
{paroles.map(({id, attributes}) => ( groupCounts={grupCounts}
<ListItem components={MUIComponents}
key={id} groupContent={index => <div>{grup[index]}</div>}
button itemContent={index => {
id={attributes.slug} const anPawol = pawol[index]
selected={slugTeksChwazi === attributes.slug} const {couverture} = anPawol.attributes
onClick={() => handleClick(attributes.slug)} const kuvetiFormat = formatKuveti(couverture)
>
<ListItemText primary={<strong>{attributes.titre}</strong>} secondary={niAwtis ? getAlias(attributes.artistes, attributes.prioriteArtistes) : null} /> return (
{attributes.gadeEmbed && !attributes.okiMizikID && ( <MizikLyen niAwtis={niAwtis} anPawol={anPawol} kuveti={kuvetiFormat} slug={params.slug} />
<Peertube style={{marginRight: 5}} /> )
)} }}
{attributes.explicitLyrics && ( />
<ExplicitIcon style={{marginRight: 5}} color='secondary' /> )
)} }
{attributes.okiMizikID && (
<LibraryMusicIcon style={{fontSize: 40}} color='primary' /> const MUIComponents = {
)} List: React.forwardRef(({style, children}, listRef) => (
{esBrandNew(attributes.publishedAt) && ( <List ref={listRef} style={{padding: 0, ...style, margin: 0}} component='div'>
<FiberNewOutlinedIcon style={{fontSize: 40}} color='primary' /> {children}
)} </List>
)),
Item: ({children, ...props}) => (
<ListItem component='div' {...props} style={{margin: 0, paddingInline: 0}}>
{children}
</ListItem> </ListItem>
))} ),
</StyledList>
Group: ({children, style, ...props}) => (
<ListSubheader
component='div'
{...props}
style={{
...style,
backgroundColor: 'transparent',
margin: 0,
paddingLeft: 5,
fontWeight: 'bold'
}}
>
{children}
</ListSubheader>
) )
} }
MizikLis.propTypes = { MizikLis.propTypes = {
meteEsMobilOuve: PropTypes.func,
niAwtis: PropTypes.bool, niAwtis: PropTypes.bool,
paroles: PropTypes.array.isRequired, paroles: PropTypes.array.isRequired
slugTeksChwazi: PropTypes.string,
meteSlugTeksChwazi: PropTypes.func
} }
MizikLis.defaultProps = { MUIComponents.List.propTypes = {
meteEsMobilOuve: null, style: PropTypes.object,
niAwtis: false, children: PropTypes.node.isRequired,
slugTeksChwazi: null, }
meteSlugTeksChwazi: null
MUIComponents.Item.propTypes = {
children: PropTypes.node.isRequired,
}
MUIComponents.Group.propTypes = {
children: PropTypes.node.isRequired,
style: PropTypes.object,
} }
+56
View File
@@ -0,0 +1,56 @@
import PropTypes from 'prop-types'
import Link from 'next/link'
import ListItemButton from '@mui/material/ListItemButton'
import ListItemText from '@mui/material/ListItemText'
import Typography from '@mui/material/Typography'
import ListItemAvatar from '@mui/material/ListItemAvatar'
import Avatar from '@mui/material/Avatar'
import FiberNewOutlinedIcon from '@mui/icons-material/FiberNewOutlined'
import LibraryMusicIcon from '@mui/icons-material/LibraryMusic'
import ExplicitIcon from '@mui/icons-material/Explicit'
import {esBrandNew} from '../../lib/date'
import {getAlias} from '../../lib/utils/format'
const apiUrl = process.env.NEXT_PUBLIC_API_URL_ROOT || 'http://localhost:1337'
export default function MizikLyen({niAwtis, anPawol, kuveti, slug}) {
return (
<Link
passHref
href={`/paroles/${anPawol.attributes.slug}#${anPawol.attributes.slug}`}
style={{textDecoration: 'none', width: '100%', display: 'flex', alignItems: 'center'}}
>
<ListItemButton
sx={{padding: 0}}
id={anPawol.attributes.slug}
selected={slug === anPawol.attributes.slug}
>
<ListItemAvatar sx={{ml: 2.5}}>
<Avatar alt={anPawol.attributes.titre} src={`${apiUrl}${kuveti?.url}`} />
</ListItemAvatar>
<ListItemText
primary={<Typography sx={{fontWeight: 'bold'}} color='info.main'>{anPawol.attributes.titre}</Typography>}
secondary={niAwtis ? getAlias(anPawol.attributes.artistes, anPawol.attributes.prioriteArtistes) : null} />
{esBrandNew(anPawol.attributes.publishedAt) && (
<FiberNewOutlinedIcon style={{fontSize: 30, marginRight: 5}} color='primary' />
)}
{anPawol.attributes.explicitLyrics && (
<ExplicitIcon style={{marginRight: 5}} color='secondary' />
)}
{anPawol.attributes.okiMizikID && (
<LibraryMusicIcon style={{fontSize: 30, marginRight: 5}} color='primary' />
)}
</ListItemButton>
</Link>
)
}
MizikLyen.propTypes = {
niAwtis: PropTypes.bool,
anPawol: PropTypes.object,
kuveti: PropTypes.object,
slug: PropTypes.string
}