From 0618afa3a4e96e9a19e0a2e966aa7f032a982d6d Mon Sep 17 00:00:00 2001 From: Leon Date: Wed, 25 Feb 2026 11:36:28 +0100 Subject: [PATCH] fix by musicland ai and new club advantages --- functions/src/cover.js | 4 +- src/screens/Profile/ManageSubscription.js | 2 - .../Profile/components/ClubAdvantagesCard.js | 427 ++++++++---------- src/screens/cover/SongDownload.js | 17 +- 4 files changed, 193 insertions(+), 257 deletions(-) diff --git a/functions/src/cover.js b/functions/src/cover.js index 5c927f1..dbc82eb 100644 --- a/functions/src/cover.js +++ b/functions/src/cover.js @@ -42,7 +42,8 @@ const buildBrandSvg = ({ width = 1024, height = 1024, text = BRAND_TEXT } = {}) const rectX = Math.max(0, Math.round(safeWidth - margin - rectWidth)) const rectY = Math.max(0, Math.round(safeHeight - margin - rectHeight)) const textX = rectX + rectWidth / 2 - const textY = rectY + rectHeight / 2 + const baselineShift = Math.round(fontSize * 0.3) + const textY = rectY + rectHeight / 2 + baselineShift const rectRadius = Math.max(6, Math.round(rectHeight * 0.35)) return Buffer.from(` @@ -65,7 +66,6 @@ const buildBrandSvg = ({ width = 1024, height = 1024, text = BRAND_TEXT } = {}) x="${textX}" y="${textY}" text-anchor="middle" - dominant-baseline="middle" font-family="${BRAND_FONT_FAMILY}" font-size="${fontSize}" font-style="italic" diff --git a/src/screens/Profile/ManageSubscription.js b/src/screens/Profile/ManageSubscription.js index d3a9890..d20ea19 100644 --- a/src/screens/Profile/ManageSubscription.js +++ b/src/screens/Profile/ManageSubscription.js @@ -13,7 +13,6 @@ import { FONT_FAMILY } from '../../styles/Fonts' import { formatDate, toDate } from '../../utils/dateFormatting' import { Image as ExpoImage } from 'expo-image' import { isWeb } from '../../hooks/useLayoutType' -import ClubAdvantagesCard from './components/ClubAdvantagesCard' const FUNCTIONS_REGION = 'europe-west1' @@ -654,7 +653,6 @@ const ManageSubscription = ({ navigation }) => { /> )} - {/**/} ) diff --git a/src/screens/Profile/components/ClubAdvantagesCard.js b/src/screens/Profile/components/ClubAdvantagesCard.js index 3dbdbc7..28b84b5 100644 --- a/src/screens/Profile/components/ClubAdvantagesCard.js +++ b/src/screens/Profile/components/ClubAdvantagesCard.js @@ -1,160 +1,152 @@ import React from 'react' -import { StyleSheet, Switch, Text, View } from 'react-native' -import { MaterialCommunityIcons } from '@expo/vector-icons' -import { Image as ExpoImage } from 'expo-image' +import { StyleSheet, Text, View } from 'react-native' import { useNavigation } from '@react-navigation/native' -import ClubCard from '../../Home/components/ClubCard' import { gutters, Palette } from '../../../styles' import { FONT_FAMILY } from '../../../styles/Fonts' import { Routes } from '../../../navigation/Routes' import { useUserData } from '../../../providers/UserDataProvider' -import { icons } from '../../../assets' +import GradientButton from '../../../components/GradientButton' +import CreditAmount from '../../../components/CreditAmount' +import { useStripe } from '../../../providers/StripeProvider' import { isWeb } from '../../../hooks/useLayoutType' -const ICON_BASE_ACCENT = '#A96BFF' +const formatCurrency = (amount, currency = 'eur') => { + if (typeof amount !== 'number') { + return null + } + const normalized = amount / 100 + const upperCurrency = + typeof currency === 'string' && currency.trim() ? currency.trim().toUpperCase() : 'EUR' -const CLUB_ADVANTAGES = [ - { - title: 'Gagne des crédits avec ton abonnement', - description: 'Des crédits premium tous les mois pour créer plus.', - iconType: 'image', - icon: icons.coin, - accent: ICON_BASE_ACCENT, - }, - { - title: 'Gagne le double de cashprice grace à ton adésion au club', - description: 'Cashprice doublé pour les membres du Club Musicland.', - iconType: 'vector', - iconName: 'chart-line', - accent: '#F8C24D', - }, -] + if (typeof Intl !== 'undefined' && Intl.NumberFormat) { + try { + return new Intl.NumberFormat('fr-FR', { + style: 'currency', + currency: upperCurrency, + minimumFractionDigits: 2, + }).format(normalized) + } catch (_error) { + // Ignore + } + } + return `${normalized.toFixed(2)} ${upperCurrency}` +} -const ClubAdvantagesCard = ({ style, isDev = false }) => { +const COIN_PACK_DETAILS = { + starter: { + label: 'Pack starter', + creditsDisplay: '50 Crédits', + disclaimer: '*Non-Eligible au concours Chanson/Vidéo', + }, + medium: { + label: 'Pack Medium', + creditsDisplay: '100 Crédits + 50 offerts', + disclaimer: '*Non-Eligible au concours Chanson/Vidéo', + }, + premium: { + label: 'Pack Premium', + creditsDisplay: '150 Crédits + 100 offerts', + disclaimer: '*Non-Eligible au concours Chanson/Vidéo', + }, +} + +const getCoinPackKey = (pack) => { + const name = (pack?.name || '').toLowerCase() + if (name.includes('starter')) return 'starter' + if (name.includes('medium')) return 'medium' + if (name.includes('premium') || name.includes('prenium') || name.includes('creator')) + return 'premium' + return null +} + +const ClubAdvantagesCard = ({ style }) => { const navigation = useNavigation() const { hasActiveSubscription } = useUserData() || {} - const [useWebLayout, setUseWebLayout] = React.useState(isDev ? isWeb : false) - const advantages = CLUB_ADVANTAGES - - React.useEffect(() => { - if (!isDev) { - setUseWebLayout(false) - } - }, [isDev]) - - const title = hasActiveSubscription - ? 'Tu profites déjà du Club Musicland' - : 'Rejoins le Club Musicland' - const subtitle = hasActiveSubscription - ? 'Grâce à ton abonnement, tu bénéficies de tous ces avantages.' - : 'Découvre ce que tu gagnes en passant au club premium.' + const { coinPacks, createCoinPackCheckout } = useStripe() + const [processingPriceId, setProcessingPriceId] = React.useState(null) + const [errorMessage, setErrorMessage] = React.useState(null) const handleOpenPlans = () => { navigation.navigate(Routes.Payments) } + const handleBuyCredits = async (pack) => { + const targetId = pack?.productId + if (!targetId) return + setProcessingPriceId(targetId) + setErrorMessage(null) + try { + await createCoinPackCheckout(targetId) + } catch (error) { + setErrorMessage(error?.message || "Erreur lors de l'achat de crédits.") + } finally { + setProcessingPriceId(null) + } + } + return ( - {/* {isDev ? ( - - - Test layout web - - - - ) : null} */} - - {title} - {subtitle} + + {'Les abonnements et les packs permettent le téléchargement de vos créations'} + + {'Avec un abonnement le téléchargement est gratuit'} + {coinPacks && coinPacks.length > 0 ? ( + + Recharger vos crédits + + {coinPacks.map((pack) => { + const rawAmount = pack.unitAmount ?? pack.amount ?? pack.price ?? 0 + const price = formatCurrency(rawAmount, pack.currency) + const coins = Number(pack.metadata?.coins || 0) + const packKey = getCoinPackKey(pack) + const details = packKey ? COIN_PACK_DETAILS[packKey] : null + const displayName = details?.label || pack.name + const creditsText = details?.creditsDisplay + + return ( + + + {displayName} + {creditsText ? ( + {creditsText} + ) : ( + + )} + {details?.disclaimer ? ( + {details.disclaimer} + ) : null} + + handleBuyCredits(pack)} + disabled={Boolean(processingPriceId)} + style={styles.creditButton} + textStyle={styles.creditButtonText} + gradientStyle={{ paddingVertical: 8, paddingHorizontal: 16 }} + /> + + ) + })} + + {errorMessage ? {errorMessage} : null} + + ) : null} + - - - {advantages.map((advantage) => { - const accent = advantage.accent || Palette.white - const iconType = advantage.iconType || 'image' - - return ( - - {hasActiveSubscription ? ( - - ) : null} - - {iconType === 'vector' ? ( - - ) : ( - - )} - - - - {advantage.title} - - - {advantage.description} - - - - ) - })} - - - ) } @@ -166,7 +158,6 @@ const styles = StyleSheet.create({ borderRadius: 24, backgroundColor: '#252438', borderWidth: 1, - gap: gutters, borderColor: 'white', }, cardInactive: { @@ -179,28 +170,6 @@ const styles = StyleSheet.create({ flexDirection: 'row', alignItems: 'center', justifyContent: 'center', - gap: gutters, - }, - testSwitches: { - gap: gutters * 0.75, - // backgroundColor: "rgba(255, 255, 255, 0.08)", - padding: gutters * 0.9, - borderRadius: 14, - borderWidth: 1, - borderColor: 'rgba(255, 255, 255, 0.12)', - }, - switchRow: { - flexDirection: 'row', - alignItems: 'center', - gap: gutters * 0.5, - justifyContent: 'space-between', - }, - switchLabel: { - fontFamily: FONT_FAMILY.InterMedium, - fontSize: 11, - color: Palette.grayMid, - textTransform: 'uppercase', - letterSpacing: 0.6, }, titleBlock: { flex: 1, @@ -211,7 +180,7 @@ const styles = StyleSheet.create({ fontFamily: FONT_FAMILY.InterSemiBold, fontSize: 18, color: Palette.white, - textAlign: 'center', + textAlign: "center", }, subtitle: { fontFamily: FONT_FAMILY.InterRegular, @@ -220,96 +189,80 @@ const styles = StyleSheet.create({ lineHeight: 18, textAlign: 'center', }, - advantagesList: { - gap: gutters * 0.75, - }, - advantagesListWeb: { - flexDirection: 'row', - flexWrap: 'wrap', - justifyContent: 'space-between', - }, - advantagesListMobile: { - flexDirection: 'column', - }, - advantageCard: { - flexDirection: 'row', - alignItems: 'flex-start', - gap: gutters * 0.65, - backgroundColor: 'rgba(255, 255, 255, 0.08)', - borderRadius: 16, - borderWidth: 0, - padding: gutters, - shadowColor: '#000', - shadowOffset: { width: 0, height: 6 }, - shadowOpacity: 0.2, - shadowRadius: 10, - elevation: 2, - }, - advantageCardWeb: { - flexBasis: '31%', - maxWidth: '32%', - minWidth: 200, - flexGrow: 1, - flexShrink: 1, - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'flex-start', - gap: gutters * 0.5, - position: 'relative', - }, - advantageCardMobile: { + sectionContainer: { + gap: 16, width: '100%', - position: 'relative', - }, - advantageIcon: { - width: 42, - height: 42, - borderRadius: 12, alignItems: 'center', - justifyContent: 'center', - borderWidth: 1, + borderTopWidth: 1, + borderTopColor: 'rgba(255, 255, 255, 0.08)', + paddingTop: gutters, + marginTop: gutters * 0.6, }, - advantageIconWeb: { - alignSelf: 'center', - marginBottom: gutters * 0.15, - }, - advantageIconImage: { - width: 24, - height: 24, - }, - advantageContent: { - flex: 1, - gap: gutters * 0.2, - }, - advantageContentWeb: { - alignItems: 'center', - gap: gutters * 0.4, - }, - advantageTitle: { - fontFamily: FONT_FAMILY.InterSemiBold, - fontSize: 15, + sectionTitle: { + fontFamily: FONT_FAMILY.InterBold, + fontSize: 20, color: Palette.white, - }, - advantageText: { - fontFamily: FONT_FAMILY.InterRegular, - fontSize: 13, - lineHeight: 18, - color: 'rgba(255, 255, 255, 0.85)', - }, - advantageTextCenter: { textAlign: 'center', }, - advantageCheck: { - position: 'absolute', + creditsGrid: { + flexDirection: 'row', + flexWrap: 'wrap', + gap: 16, + justifyContent: 'center', + width: '100%', }, - advantageCheckWeb: { - top: 10, - right: 10, + creditCard: { + backgroundColor: 'rgba(255, 255, 255, 0.05)', + borderRadius: 16, + padding: 16, + alignItems: 'center', + justifyContent: 'space-between', + width: isWeb ? 220 : '100%', + minHeight: 160, + gap: 12, + borderWidth: 1, + borderColor: 'rgba(255, 255, 255, 0.1)', }, - advantageCheckMobile: { - top: '50%', - right: 12, - transform: [{ translateY: -10 }], + creditInfoContainer: { + alignItems: 'center', + gap: 4, + }, + creditName: { + fontFamily: FONT_FAMILY.InterSemiBold, + fontSize: 14, + color: Palette.white, + textAlign: 'center', + marginBottom: 4, + }, + creditAmountCustom: { + fontFamily: FONT_FAMILY.InterBold, + fontSize: 16, + color: Palette.white, + textAlign: 'center', + }, + creditAmountText: { + fontSize: 20, + }, + packDisclaimer: { + fontFamily: FONT_FAMILY.InterRegular, + fontSize: 10, + color: 'rgba(255, 255, 255, 0.6)', + fontStyle: 'italic', + textAlign: 'center', + marginTop: 4, + }, + creditButton: { + width: '100%', + height: 36, + minHeight: 36, + }, + creditButtonText: { + fontSize: 13, + }, + errorText: { + color: Palette.red, + textAlign: 'center', + marginTop: 10, }, }) diff --git a/src/screens/cover/SongDownload.js b/src/screens/cover/SongDownload.js index 27b14d0..5c5793b 100644 --- a/src/screens/cover/SongDownload.js +++ b/src/screens/cover/SongDownload.js @@ -549,22 +549,7 @@ const SongDownload = ({ route }) => { - {showSubscriptionCta ? ( - - - Avec un abonnement, le téléchargement est gratuit. - - navigate(Routes.Payments)} - containerStyle={styles.subscriptionButton} - /> - - ) : ( - - Avec ton abonnement, le téléchargement est gratuit. - - )} +