feat: display titrePhare on OKI artist
Déploiement FRONT PROD / check (push) Successful in 2m1s
Déploiement FRONT PROD / deploy (push) Successful in 21s

This commit is contained in:
2026-06-20 18:37:43 +04:00
parent 45d1891df6
commit 4d751482c2
2 changed files with 89 additions and 14 deletions
+88 -13
View File
@@ -9,6 +9,7 @@ import AccordionSummary from '@mui/material/AccordionSummary'
import Box from '@mui/material/Box' import Box from '@mui/material/Box'
import Button from '@mui/material/Button' import Button from '@mui/material/Button'
import CardActionArea from '@mui/material/CardActionArea' import CardActionArea from '@mui/material/CardActionArea'
import CardMedia from '@mui/material/CardMedia'
import Chip from '@mui/material/Chip' import Chip from '@mui/material/Chip'
import Container from '@mui/material/Container' import Container from '@mui/material/Container'
import Grid from '@mui/material/Grid' import Grid from '@mui/material/Grid'
@@ -20,44 +21,83 @@ import Typography from '@mui/material/Typography'
import {green} from '@mui/material/colors' 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 OpenInNewIcon from '@mui/icons-material/OpenInNew'
import VerifiedIcon from '@mui/icons-material/Verified' import VerifiedIcon from '@mui/icons-material/Verified'
import {Spotify, Applemusic, Deezer, Tidal, Youtubemusic, Amazon, Soundcloud} from '@icons-pack/react-simple-icons'
import {formatKuveti} from '../../lib/kuveti' import {formatKuveti} from '../../lib/kuveti'
import AwtisBiyografi from './awtis-biyografi' import AwtisBiyografi from './awtis-biyografi'
import MizikLyen from './mizik-lyen' import MizikLyen from './mizik-lyen'
const PLATFORM_CONFIG = {
Spotify: {label: 'Spotify', bg: '#1DB954', color: '#fff', Icon: Spotify},
Applemusic: {label: 'Apple Music', bg: '#FC3C44', color: '#fff', Icon: Applemusic},
Deezer: {label: 'Deezer', bg: '#EF5466', color: '#fff', Icon: Deezer},
Tidal: {label: 'Tidal', bg: '#000000', color: '#fff', Icon: Tidal},
Qobuz: {label: 'Qobuz', bg: '#00245B', color: '#fff', Icon: null},
Youtubemusic: {label: 'YouTube Music', bg: '#FF0000', color: '#fff', Icon: Youtubemusic},
Amazon: {label: 'Amazon Music', bg: '#00A8E1', color: '#fff', Icon: Amazon},
Soundcloud: {label: 'SoundCloud', bg: '#FF5500', color: '#fff', Icon: Soundcloud},
}
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) => a.titre.localeCompare(b.titre, 'fr', {sensitivity: 'base'})) const sortTeks = paroles => paroles.sort((a, b) => a.titre.localeCompare(b.titre, 'fr', {sensitivity: 'base'}))
function StreamButton({lyen}) {
const config = PLATFORM_CONFIG[lyen.plateforme] || {label: lyen.plateforme, bg: '#555', color: '#fff', Icon: null}
const PlatformIcon = config.Icon
return (
<Button
href={lyen.url}
target='_blank'
rel='noopener noreferrer'
size='small'
startIcon={PlatformIcon ? <PlatformIcon size={16} color={config.color} /> : null}
endIcon={<OpenInNewIcon sx={{fontSize: 11}} />}
sx={{
bgcolor: config.bg,
color: config.color,
fontWeight: 700,
fontSize: '0.72rem',
textTransform: 'none',
'&:hover': {bgcolor: config.bg, opacity: 0.85},
}}
>
{config.label}
</Button>
)
}
export default function AwtisDetay({anAwtis}) { export default function AwtisDetay({anAwtis}) {
const [esByografiOuve, meteEsByografiOuve] = useState(false) const [esByografiOuve, meteEsByografiOuve] = useState(false)
const {alias, biographie, paroles, photo, isOKIAwtis} = anAwtis const {alias, biographie, paroles, photo, isOKIAwtis, titrePhare} = anAwtis
const sortedTeks = sortTeks(paroles) const sortedTeks = sortTeks(paroles)
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
const handleClick = () => { const hasStreaming = isOKIAwtis && titrePhare?.streamAudio?.length > 0
meteEsByografiOuve(true) const coverUrl = titrePhare?.couverture
} ? `${IMAGE_URL}${titrePhare.couverture.formats?.small?.url || titrePhare.couverture.formats?.thumbnail?.url || titrePhare.couverture.url}`
: null
return ( return (
<Container> <Container>
<Box sx={{marginTop: 8, marginBottom: 2}}> <Box sx={{mt: 8, mb: 2}}>
<Typography sx={{textAlign: 'center'}} variant='h6' component='h1'> <Typography sx={{textAlign: 'center'}} variant='h6' component='h1'>
{alias} {alias}
</Typography> </Typography>
</Box> </Box>
<Box sx={{justifyContent: 'center', display: 'flex', marginBottom: 2}}>
<Box sx={{display: 'flex', justifyContent: 'center', mb: 2}}>
<Avatar <Avatar
src={photo?.url ? `${IMAGE_URL}${photo?.formats?.small?.url || photo?.formats?.thumbnail?.url || photo?.url}` : noImageUrl} src={photo?.url ? `${IMAGE_URL}${photo?.formats?.small?.url || photo?.formats?.thumbnail?.url || photo?.url}` : noImageUrl}
alt={`Photo ${alias}`} alt={`Photo ${alias}`}
sx={{width: 200, height: 200, border: `2px solid ${green[500]}`}} sx={{width: 200, height: 200, border: `2px solid ${green[500]}`}}
/> />
</Box> </Box>
{isOKIAwtis && ( {isOKIAwtis && (
<Box sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 0.75, mb: 2}}> <Box sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 0.75, mb: 2}}>
<Chip <Chip
@@ -71,11 +111,12 @@ export default function AwtisDetay({anAwtis}) {
</Typography> </Typography>
</Box> </Box>
)} )}
<Grid sx={{alignItems:'center'}} container direction='column' spacing={3}>
<Grid sx={{alignItems: 'center'}} container direction='column' spacing={3}>
{biyo && ( {biyo && (
<Grid size={{xs: 12, md: 6}}> <Grid size={{xs: 12, md: 6}}>
<Card sx={{minWidth: 300}}> <Card sx={{minWidth: 300}}>
<CardActionArea onClick={handleClick}> <CardActionArea onClick={() => meteEsByografiOuve(true)}>
<CardContent> <CardContent>
<Typography gutterBottom variant='body1' component='h2'> <Typography gutterBottom variant='body1' component='h2'>
<strong>Biographie</strong> <strong>Biographie</strong>
@@ -88,6 +129,39 @@ export default function AwtisDetay({anAwtis}) {
</Card> </Card>
</Grid> </Grid>
)} )}
{hasStreaming && (
<Grid size={{xs: 12, md: 6}}>
<Card sx={{overflow: 'hidden'}}>
<Grid container>
{coverUrl && (
<Grid size={{xs: 12, sm: 4}}>
<CardMedia
component='img'
image={coverUrl}
alt={titrePhare.titre}
sx={{height: '100%', minHeight: 140, objectFit: 'cover'}}
/>
</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.5}}>
É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={{xs: 12, md: 6}}> <Grid size={{xs: 12, md: 6}}>
<Box marginbottom={3}> <Box marginbottom={3}>
{paroles.length > 1 ? ( {paroles.length > 1 ? (
@@ -97,14 +171,13 @@ export default function AwtisDetay({anAwtis}) {
aria-controls='panel-teks-content' aria-controls='panel-teks-content'
id='panel-teks-header' id='panel-teks-header'
> >
<Typography sx={{marginRight: 2, textAlign:'center' }} variant='body1' component='h2'><strong>Liste des paroles</strong></Typography> <Typography sx={{marginRight: 2, textAlign: 'center'}} variant='body1' component='h2'><strong>Liste des paroles</strong></Typography>
<Chip color='primary' label={paroles.length} size='small' variant='contained' /> <Chip color='primary' label={paroles.length} size='small' variant='contained' />
</AccordionSummary> </AccordionSummary>
<AccordionDetails sx={{paddingInline: 0}}> <AccordionDetails sx={{paddingInline: 0}}>
{sortedTeks.map(anPawol => { {sortedTeks.map(anPawol => {
const {couverture} = anPawol const {couverture} = anPawol
const kuvetiFormat = couverture?.formats?.thumbnail || formatKuveti(couverture) const kuvetiFormat = couverture?.formats?.thumbnail || formatKuveti(couverture)
return ( return (
<Box key={anPawol.id} sx={{paddingBlock: 0.5}}> <Box key={anPawol.id} sx={{paddingBlock: 0.5}}>
<MizikLyen anPawol={anPawol} kuveti={kuvetiFormat} /> <MizikLyen anPawol={anPawol} kuveti={kuvetiFormat} />
@@ -128,13 +201,15 @@ export default function AwtisDetay({anAwtis}) {
</Box> </Box>
</Grid> </Grid>
</Grid> </Grid>
<Box sx={{textAlign: 'center', marginBlock: 3}} >
<Box sx={{textAlign: 'center', marginBlock: 3}}>
<Link passHref href='/awtis'> <Link passHref href='/awtis'>
<Button variant='outlined' startIcon={<KeyboardBackspaceIcon />}> <Button variant='outlined' startIcon={<KeyboardBackspaceIcon />}>
Retour aux artistes Retour aux artistes
</Button> </Button>
</Link> </Link>
</Box> </Box>
{esByografiOuve && ( {esByografiOuve && (
<AwtisBiyografi <AwtisBiyografi
alias={alias} alias={alias}
+1 -1
View File
@@ -92,7 +92,7 @@ export async function jwennTeksEpiSlug(slug) {
export async function jwennAwtisEpiSlug(slug) { export async function jwennAwtisEpiSlug(slug) {
const query = qs.stringify({ const query = qs.stringify({
populate: ['paroles', 'photo', 'paroles.couverture'], populate: ['paroles', 'photo', 'paroles.couverture', 'titrePhare', 'titrePhare.streamAudio', 'titrePhare.streamVideo', 'titrePhare.couverture'],
filters: { filters: {
slug: { slug: {
$eq: slug $eq: slug