Files
pawol.nu/components/awtis/awtis-detay.js
T
cedric 9752e4bcdd
Déploiement FRONT BETA / check (push) Successful in 2m13s
Déploiement FRONT PROD / check (push) Successful in 2m15s
Déploiement FRONT BETA / deploy (push) Successful in 22s
Déploiement FRONT PROD / deploy (push) Successful in 21s
feat: redesign artist page layout and social icons
2026-06-26 22:03:19 +04:00

240 lines
9.4 KiB
JavaScript

'use client'
import {useState} from 'react'
import Image from 'next/image'
import Link from 'next/link'
import PropTypes from 'prop-types'
import Accordion from '@mui/material/Accordion'
import AccordionDetails from '@mui/material/AccordionDetails'
import AccordionSummary from '@mui/material/AccordionSummary'
import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
import CardActionArea from '@mui/material/CardActionArea'
import Chip from '@mui/material/Chip'
import Container from '@mui/material/Container'
import Divider from '@mui/material/Divider'
import Grid from '@mui/material/Grid'
import Paper from '@mui/material/Paper'
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import Typography from '@mui/material/Typography'
import {green} from '@mui/material/colors'
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import KeyboardBackspaceIcon from '@mui/icons-material/KeyboardBackspace'
import MusicNoteIcon from '@mui/icons-material/MusicNote'
import VerifiedIcon from '@mui/icons-material/Verified'
import {formatKuveti} from '../../lib/kuveti'
import {StreamButton} from '../streaming-buttons'
import {SocialButton} from './social-buttons'
import AwtisBiyografi from './awtis-biyografi'
import MizikLyen from './mizik-lyen'
const IMAGE_URL = process.env.NEXT_PUBLIC_API_URL_ROOT || 'http://localhost:1337'
const EXCLUSIVE_LABEL = process.env.NEXT_PUBLIC_EXCLUSIVE_ARTIST_LABEL || 'OKI Exclusif'
const BLUR_DATA_URL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNsYAAAAAYAAjCB0C8AAAAASUVORK5CYII='
const sortTeks = paroles => paroles.sort((a, b) => a.titre.localeCompare(b.titre, 'fr', {sensitivity: 'base'}))
export default function AwtisDetay({anAwtis}) {
const [esByografiOuve, meteEsByografiOuve] = useState(false)
const {alias, biographie, paroles, photo, isExclusiveArtist, titrePhare, rezoSosyal} = anAwtis
const sortedTeks = sortTeks(paroles)
const gwanBiyo = biographie && biographie.length > 100
const biyo = gwanBiyo ? `${biographie.slice(0, 100)}...` : biographie
const hasStreaming = isExclusiveArtist && titrePhare?.streamAudio?.length > 0
const coverUrl = titrePhare?.couverture
? `${IMAGE_URL}${titrePhare.couverture.formats?.small?.url || titrePhare.couverture.formats?.thumbnail?.url || titrePhare.couverture.url}`
: null
const photoUrl = photo?.url
? `${IMAGE_URL}${photo.formats?.small?.url || photo.formats?.thumbnail?.url || photo.url}`
: null
return (
<Container maxWidth='sm'>
<Box sx={{mt: 2, mb: 1}}>
<Link passHref href='/awtis'>
<Button size='small' variant='text' startIcon={<KeyboardBackspaceIcon />} sx={{color: 'text.secondary'}}>
Retour aux artistes
</Button>
</Link>
</Box>
{/* Héro */}
<Box sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', pt: 2, pb: 3}}>
<Box sx={{
width: 150, height: 150,
borderRadius: '50%',
border: `3px solid ${green[500]}`,
overflow: 'hidden',
position: 'relative',
flexShrink: 0,
mb: 2,
}}>
{photoUrl ? (
<Image
src={photoUrl}
alt={`Photo ${alias}`}
width={150}
height={150}
placeholder='blur'
blurDataURL={BLUR_DATA_URL}
style={{objectFit: 'cover', width: '100%', height: '100%'}}
/>
) : (
<Box sx={{width: '100%', height: '100%', bgcolor: 'grey.300'}} />
)}
</Box>
<Typography variant='h5' component='h1' sx={{fontWeight: 700, mb: 1, textAlign: 'center'}}>
{alias}
</Typography>
{rezoSosyal?.length > 0 && (
<Box sx={{display: 'flex', gap: 0.75, flexWrap: 'wrap', justifyContent: 'center', mb: 1.5}}>
{rezoSosyal.map((rezo, i) => (
<SocialButton key={i} rezo={rezo} />
))}
</Box>
)}
{isExclusiveArtist && (
<Box sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 0.5}}>
<Chip
icon={<VerifiedIcon sx={{fontSize: 16}} />}
label={`Artiste ${EXCLUSIVE_LABEL}`}
size='small'
sx={{bgcolor: '#FFD700', color: '#000', fontWeight: 700, '& .MuiChip-icon': {color: '#000'}}}
/>
<Typography variant='caption' sx={{color: 'text.secondary', textAlign: 'center', maxWidth: 340}}>
Certains morceaux sont publiés en exclusivité sur PAWÒL-NU, avant toute sortie sur les plateformes de streaming.
</Typography>
</Box>
)}
</Box>
<Grid container direction='column' spacing={2}>
{biyo && (
<Grid size={12}>
<Card>
<CardActionArea onClick={() => meteEsByografiOuve(true)}>
<CardContent>
<Typography gutterBottom variant='body2' sx={{fontWeight: 700, textTransform: 'uppercase', color: 'text.secondary', letterSpacing: 0.5}}>
Biographie
</Typography>
<Typography variant='body1'>
{biyo}
</Typography>
</CardContent>
</CardActionArea>
</Card>
</Grid>
)}
{hasStreaming && (
<Grid size={12}>
<Card sx={{overflow: 'hidden'}}>
<Box sx={{px: 2, pt: 1.5, pb: 0.5, display: 'flex', alignItems: 'center', gap: 0.75}}>
<MusicNoteIcon sx={{fontSize: 14, color: 'text.secondary'}} />
<Typography variant='caption' sx={{fontWeight: 700, textTransform: 'uppercase', color: 'text.secondary', letterSpacing: 0.5}}>
Titre phare
</Typography>
</Box>
<Divider />
<Grid container>
{coverUrl && (
<Grid size={{xs: 12, sm: 4}}>
<Box sx={{position: 'relative', minHeight: 130, height: '100%'}}>
<Image
src={coverUrl}
alt={titrePhare.titre}
fill
placeholder='blur'
blurDataURL={BLUR_DATA_URL}
sizes='200px'
style={{objectFit: 'cover'}}
/>
</Box>
</Grid>
)}
<Grid size={{xs: 12, sm: coverUrl ? 8 : 12}}>
<CardContent>
<Typography variant='subtitle1' sx={{fontWeight: 700}} gutterBottom>
{titrePhare.titre}
</Typography>
<Typography variant='caption' sx={{color: 'text.secondary', display: 'block', mb: 1}}>
Écouter sur
</Typography>
<Box sx={{display: 'flex', flexWrap: 'wrap', gap: 1}}>
{titrePhare.streamAudio.map((lyen, i) => (
<StreamButton key={i} lyen={lyen} />
))}
</Box>
</CardContent>
</Grid>
</Grid>
</Card>
</Grid>
)}
<Grid size={12}>
{paroles.length > 1 ? (
<Accordion>
<AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls='panel-teks-content' id='panel-teks-header'>
<Typography sx={{marginRight: 2}} variant='body1'><strong>Liste des paroles</strong></Typography>
<Chip color='primary' label={paroles.length} size='small' variant='contained' />
</AccordionSummary>
<AccordionDetails sx={{paddingInline: 0}}>
{sortedTeks.map(anPawol => {
const {couverture} = anPawol
const kuvetiFormat = couverture?.formats?.thumbnail || formatKuveti(couverture)
return (
<Box key={anPawol.id} sx={{paddingBlock: 0.5}}>
<MizikLyen anPawol={anPawol} kuveti={kuvetiFormat} />
</Box>
)
})}
</AccordionDetails>
</Accordion>
) : paroles.length === 0 ? (
<Typography textAlign='center' variant='body1' color='text.secondary'>
Aucune parole pour le moment
</Typography>
) : (
<Box>
<Typography gutterBottom variant='body1'><strong>Parole</strong></Typography>
<Paper sx={{paddingBlock: 2}}>
<MizikLyen anPawol={paroles[0]} kuveti={paroles[0].couverture?.formats?.thumbnail || formatKuveti(paroles[0].couverture)} />
</Paper>
</Box>
)}
</Grid>
</Grid>
<Box sx={{textAlign: 'center', my: 4}}>
<Link passHref href='/awtis'>
<Button variant='outlined' startIcon={<KeyboardBackspaceIcon />}>
Retour aux artistes
</Button>
</Link>
</Box>
{esByografiOuve && (
<AwtisBiyografi
alias={alias}
paroles={paroles}
biographie={biographie}
esByografiOuve={esByografiOuve}
meteEsByografiOuve={meteEsByografiOuve}
/>
)}
</Container>
)
}
AwtisDetay.propTypes = {
anAwtis: PropTypes.object.isRequired
}