Compare commits

..

3 Commits

Author SHA1 Message Date
cedric 9752e4bcdd feat: redesign artist page layout and social icons
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
2026-06-26 22:03:19 +04:00
cedric 719522f665 Merge pull request 'feat: add social networks to artist page' (#3) from feat/improve-artist-page into master
Déploiement FRONT BETA / check (push) Successful in 2m7s
Déploiement FRONT PROD / check (push) Successful in 2m12s
Déploiement FRONT BETA / deploy (push) Successful in 20s
Déploiement FRONT PROD / deploy (push) Successful in 20s
Reviewed-on: #3
2026-06-26 17:37:45 +00:00
cedric 1c86d0b962 fix: use available icon exports in social-buttons
Déploiement FRONT BETA / check (push) Successful in 2m10s
Déploiement FRONT BETA / deploy (push) Successful in 22s
Vérification PR / check (pull_request) Successful in 2m2s
Vérification PR / deploy-beta (pull_request) Successful in 19s
2026-06-26 21:16:57 +04:00
2 changed files with 137 additions and 107 deletions
+91 -79
View File
@@ -12,6 +12,7 @@ import Button from '@mui/material/Button'
import CardActionArea from '@mui/material/CardActionArea' import CardActionArea from '@mui/material/CardActionArea'
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 Divider from '@mui/material/Divider'
import Grid from '@mui/material/Grid' import Grid from '@mui/material/Grid'
import Paper from '@mui/material/Paper' import Paper from '@mui/material/Paper'
import Card from '@mui/material/Card' import Card from '@mui/material/Card'
@@ -20,6 +21,7 @@ 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 MusicNoteIcon from '@mui/icons-material/MusicNote'
import VerifiedIcon from '@mui/icons-material/Verified' import VerifiedIcon from '@mui/icons-material/Verified'
import {formatKuveti} from '../../lib/kuveti' import {formatKuveti} from '../../lib/kuveti'
@@ -51,28 +53,32 @@ export default function AwtisDetay({anAwtis}) {
: null : null
return ( return (
<Container> <Container maxWidth='sm'>
<Box sx={{mt: 8, mb: 2}}> <Box sx={{mt: 2, mb: 1}}>
<Typography sx={{textAlign: 'center'}} variant='h6' component='h1'> <Link passHref href='/awtis'>
{alias} <Button size='small' variant='text' startIcon={<KeyboardBackspaceIcon />} sx={{color: 'text.secondary'}}>
</Typography> Retour aux artistes
</Button>
</Link>
</Box> </Box>
<Box sx={{display: 'flex', justifyContent: 'center', mb: 2}}> {/* Héro */}
<Box sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', pt: 2, pb: 3}}>
<Box sx={{ <Box sx={{
width: 200, height: 200, width: 150, height: 150,
borderRadius: '50%', borderRadius: '50%',
border: `2px solid ${green[500]}`, border: `3px solid ${green[500]}`,
overflow: 'hidden', overflow: 'hidden',
position: 'relative', position: 'relative',
flexShrink: 0, flexShrink: 0,
mb: 2,
}}> }}>
{photoUrl ? ( {photoUrl ? (
<Image <Image
src={photoUrl} src={photoUrl}
alt={`Photo ${alias}`} alt={`Photo ${alias}`}
width={200} width={150}
height={200} height={150}
placeholder='blur' placeholder='blur'
blurDataURL={BLUR_DATA_URL} blurDataURL={BLUR_DATA_URL}
style={{objectFit: 'cover', width: '100%', height: '100%'}} style={{objectFit: 'cover', width: '100%', height: '100%'}}
@@ -81,32 +87,44 @@ export default function AwtisDetay({anAwtis}) {
<Box sx={{width: '100%', height: '100%', bgcolor: 'grey.300'}} /> <Box sx={{width: '100%', height: '100%', bgcolor: 'grey.300'}} />
)} )}
</Box> </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> </Box>
{isExclusiveArtist && ( <Grid container direction='column' spacing={2}>
<Box sx={{display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 0.75, mb: 2}}>
<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'}}>
Certains morceaux sont publiés en exclusivité sur PAWÒL-NU, avant toute sortie sur les plateformes de streaming.
</Typography>
</Box>
)}
<Grid sx={{alignItems: 'center'}} container direction='column' spacing={3}>
{biyo && ( {biyo && (
<Grid size={{xs: 12, md: 6}}> <Grid size={12}>
<Card sx={{minWidth: 300}}> <Card>
<CardActionArea onClick={() => meteEsByografiOuve(true)}> <CardActionArea onClick={() => meteEsByografiOuve(true)}>
<CardContent> <CardContent>
<Typography gutterBottom variant='body1' component='h2'> <Typography gutterBottom variant='body2' sx={{fontWeight: 700, textTransform: 'uppercase', color: 'text.secondary', letterSpacing: 0.5}}>
<strong>Biographie</strong> Biographie
</Typography> </Typography>
<Typography textalign='justify' variant='subtitle1' component='h3'> <Typography variant='body1'>
{biyo} {biyo}
</Typography> </Typography>
</CardContent> </CardContent>
@@ -114,13 +132,21 @@ export default function AwtisDetay({anAwtis}) {
</Card> </Card>
</Grid> </Grid>
)} )}
{hasStreaming && ( {hasStreaming && (
<Grid size={{xs: 12, md: 6}}> <Grid size={12}>
<Card sx={{overflow: 'hidden'}}> <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> <Grid container>
{coverUrl && ( {coverUrl && (
<Grid size={{xs: 12, sm: 4}}> <Grid size={{xs: 12, sm: 4}}>
<Box sx={{position: 'relative', minHeight: 140, height: '100%'}}> <Box sx={{position: 'relative', minHeight: 130, height: '100%'}}>
<Image <Image
src={coverUrl} src={coverUrl}
alt={titrePhare.titre} alt={titrePhare.titre}
@@ -138,7 +164,7 @@ export default function AwtisDetay({anAwtis}) {
<Typography variant='subtitle1' sx={{fontWeight: 700}} gutterBottom> <Typography variant='subtitle1' sx={{fontWeight: 700}} gutterBottom>
{titrePhare.titre} {titrePhare.titre}
</Typography> </Typography>
<Typography variant='caption' sx={{color: 'text.secondary', display: 'block', mb: 1.5}}> <Typography variant='caption' sx={{color: 'text.secondary', display: 'block', mb: 1}}>
Écouter sur Écouter sur
</Typography> </Typography>
<Box sx={{display: 'flex', flexWrap: 'wrap', gap: 1}}> <Box sx={{display: 'flex', flexWrap: 'wrap', gap: 1}}>
@@ -152,56 +178,42 @@ export default function AwtisDetay({anAwtis}) {
</Card> </Card>
</Grid> </Grid>
)} )}
{rezoSosyal?.length > 0 && (
<Grid size={{xs: 12, md: 6}}> <Grid size={12}>
<Box sx={{display: 'flex', flexWrap: 'wrap', gap: 1, justifyContent: 'center'}}> {paroles.length > 1 ? (
{rezoSosyal.map((rezo, i) => ( <Accordion>
<SocialButton key={i} rezo={rezo} /> <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> </Box>
</Grid> )}
)}
<Grid size={{xs: 12, md: 6}}>
<Box marginbottom={3}>
{paroles.length > 1 ? (
<Accordion>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls='panel-teks-content'
id='panel-teks-header'
>
<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' />
</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 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>
<Paper sx={{height: '100%', paddingBlock: 2}}>
<MizikLyen anPawol={paroles[0]} kuveti={paroles[0].couverture?.formats?.thumbnail || formatKuveti(paroles[0].couverture)} />
</Paper>
</Box>
)
)}
</Box>
</Grid> </Grid>
</Grid> </Grid>
<Box sx={{textAlign: 'center', marginBlock: 3}}> <Box sx={{textAlign: 'center', my: 4}}>
<Link passHref href='/awtis'> <Link passHref href='/awtis'>
<Button variant='outlined' startIcon={<KeyboardBackspaceIcon />}> <Button variant='outlined' startIcon={<KeyboardBackspaceIcon />}>
Retour aux artistes Retour aux artistes
+46 -28
View File
@@ -1,20 +1,21 @@
'use client' 'use client'
import Button from '@mui/material/Button' import Chip from '@mui/material/Chip'
import OpenInNewIcon from '@mui/icons-material/OpenInNew' import IconButton from '@mui/material/IconButton'
import Tooltip from '@mui/material/Tooltip'
import { import {
Mastodon, Peertube, Pixelfed, Funkwhale, Mastodon, Peertube,
Bluesky, Instagram, Youtube, Tiktok, Instagram, Youtube, Tiktok,
Spotify, Deezer, Applemusic, Bandcamp, Soundcloud, Spotify, Deezer, Applemusic, Bandcamp, Soundcloud,
Facebook, X, Linktree, Facebook, Twitter,
} from '@icons-pack/react-simple-icons' } from '@icons-pack/react-simple-icons'
const SOCIAL_CONFIG = { const SOCIAL_CONFIG = {
Mastodon: {label: 'Mastodon', bg: '#6364FF', color: '#fff', Icon: Mastodon}, Mastodon: {label: 'Mastodon', bg: '#6364FF', color: '#fff', Icon: Mastodon},
Peertube: {label: 'PeerTube', bg: '#F2690D', color: '#fff', Icon: Peertube}, Peertube: {label: 'PeerTube', bg: '#F2690D', color: '#fff', Icon: Peertube},
Pixelfed: {label: 'Pixelfed', bg: '#11D49D', color: '#fff', Icon: Pixelfed}, Pixelfed: {label: 'Pixelfed', bg: '#11D49D', color: '#fff', Icon: null},
Funkwhale: {label: 'Funkwhale', bg: '#E01B60', color: '#fff', Icon: Funkwhale}, Funkwhale: {label: 'Funkwhale', bg: '#E01B60', color: '#fff', Icon: null},
Bluesky: {label: 'Bluesky', bg: '#0085FF', color: '#fff', Icon: Bluesky}, Bluesky: {label: 'Bluesky', bg: '#0085FF', color: '#fff', Icon: null},
Instagram: {label: 'Instagram', bg: '#E4405F', color: '#fff', Icon: Instagram}, Instagram: {label: 'Instagram', bg: '#E4405F', color: '#fff', Icon: Instagram},
Youtube: {label: 'YouTube', bg: '#FF0000', color: '#fff', Icon: Youtube}, Youtube: {label: 'YouTube', bg: '#FF0000', color: '#fff', Icon: Youtube},
Tiktok: {label: 'TikTok', bg: '#000000', color: '#fff', Icon: Tiktok}, Tiktok: {label: 'TikTok', bg: '#000000', color: '#fff', Icon: Tiktok},
@@ -24,32 +25,49 @@ const SOCIAL_CONFIG = {
Bandcamp: {label: 'Bandcamp', bg: '#1DA0C3', color: '#fff', Icon: Bandcamp}, Bandcamp: {label: 'Bandcamp', bg: '#1DA0C3', color: '#fff', Icon: Bandcamp},
Soundcloud: {label: 'SoundCloud', bg: '#FF5500', color: '#fff', Icon: Soundcloud}, Soundcloud: {label: 'SoundCloud', bg: '#FF5500', color: '#fff', Icon: Soundcloud},
Facebook: {label: 'Facebook', bg: '#1877F2', color: '#fff', Icon: Facebook}, Facebook: {label: 'Facebook', bg: '#1877F2', color: '#fff', Icon: Facebook},
Twitter: {label: 'X / Twitter', bg: '#000000', color: '#fff', Icon: X}, Twitter: {label: 'X / Twitter', bg: '#000000', color: '#fff', Icon: Twitter},
Linktree: {label: 'Linktree', bg: '#43E660', color: '#000', Icon: Linktree}, Linktree: {label: 'Linktree', bg: '#43E660', color: '#000', Icon: null},
SiteWeb: {label: 'Site web', bg: '#555555', color: '#fff', Icon: null}, SiteWeb: {label: 'Site web', bg: '#555555', color: '#fff', Icon: null},
} }
export function SocialButton({rezo}) { export function SocialButton({rezo}) {
const config = SOCIAL_CONFIG[rezo.plateforme] ?? {label: rezo.plateforme, bg: '#555', color: '#fff', Icon: null} const config = SOCIAL_CONFIG[rezo.plateforme] ?? {label: rezo.plateforme, bg: '#555', color: '#fff', Icon: null}
const PlatformIcon = config.Icon const PlatformIcon = config.Icon
if (PlatformIcon) {
return (
<Tooltip title={config.label}>
<IconButton
component='a'
href={rezo.url}
target='_blank'
rel='noopener noreferrer'
size='small'
sx={{
bgcolor: config.bg,
width: 34,
height: 34,
'&:hover': {bgcolor: config.bg, opacity: 0.8},
}}
>
<PlatformIcon size={17} color={config.color} />
</IconButton>
</Tooltip>
)
}
return ( return (
<Button <Tooltip title={rezo.url}>
href={rezo.url} <Chip
target='_blank' label={config.label}
rel='noopener noreferrer' component='a'
size='small' href={rezo.url}
startIcon={PlatformIcon ? <PlatformIcon size={16} color={config.color} /> : null} target='_blank'
endIcon={<OpenInNewIcon sx={{fontSize: 11}} />} rel='noopener noreferrer'
sx={{ clickable
bgcolor: config.bg, size='small'
color: config.color, sx={{bgcolor: config.bg, color: config.color, fontWeight: 600}}
fontWeight: 700, />
fontSize: '0.72rem', </Tooltip>
textTransform: 'none',
'&:hover': {bgcolor: config.bg, opacity: 0.85},
}}
>
{config.label}
</Button>
) )
} }