fix by musicland ai and new club advantages
This commit is contained in:
@@ -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 }) => {
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
{/*<ClubAdvantagesCard isDev style={styles.clubCardSpacing} />*/}
|
||||
</View>
|
||||
</Page>
|
||||
)
|
||||
|
||||
@@ -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 (
|
||||
<View
|
||||
style={[styles.card, hasActiveSubscription ? styles.cardActive : styles.cardInactive, style]}
|
||||
>
|
||||
{/* {isDev ? (
|
||||
<View style={styles.testSwitches}>
|
||||
<View style={styles.switchRow}>
|
||||
<Text style={styles.switchLabel}>Test layout web</Text>
|
||||
<Switch
|
||||
value={useWebLayout}
|
||||
onValueChange={setUseWebLayout}
|
||||
trackColor={{
|
||||
false: "rgba(255, 255, 255, 0.2)",
|
||||
true: "rgba(52, 199, 89, 0.7)",
|
||||
}}
|
||||
thumbColor={useWebLayout ? Palette.white : Palette.grayMid}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
) : null} */}
|
||||
|
||||
<View style={styles.header}>
|
||||
<View style={styles.titleBlock}>
|
||||
<Text style={styles.title}>{title}</Text>
|
||||
<Text style={styles.subtitle}>{subtitle}</Text>
|
||||
<Text style={styles.title}>
|
||||
{'Les abonnements et les packs permettent le téléchargement de vos créations'}
|
||||
</Text>
|
||||
<Text style={styles.subtitle}>{'Avec un abonnement le téléchargement est gratuit'}</Text>
|
||||
{coinPacks && coinPacks.length > 0 ? (
|
||||
<View style={styles.sectionContainer}>
|
||||
<Text style={styles.sectionTitle}>Recharger vos crédits</Text>
|
||||
<View style={styles.creditsGrid}>
|
||||
{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 (
|
||||
<View key={pack.productId} style={styles.creditCard}>
|
||||
<View style={styles.creditInfoContainer}>
|
||||
<Text style={styles.creditName}>{displayName}</Text>
|
||||
{creditsText ? (
|
||||
<Text style={styles.creditAmountCustom}>{creditsText}</Text>
|
||||
) : (
|
||||
<CreditAmount
|
||||
value={coins}
|
||||
iconSize={24}
|
||||
textStyle={styles.creditAmountText}
|
||||
/>
|
||||
)}
|
||||
{details?.disclaimer ? (
|
||||
<Text style={styles.packDisclaimer}>{details.disclaimer}</Text>
|
||||
) : null}
|
||||
</View>
|
||||
<GradientButton
|
||||
title={
|
||||
processingPriceId === pack.productId
|
||||
? '...'
|
||||
: price || `${rawAmount / 100}€`
|
||||
}
|
||||
onPress={() => handleBuyCredits(pack)}
|
||||
disabled={Boolean(processingPriceId)}
|
||||
style={styles.creditButton}
|
||||
textStyle={styles.creditButtonText}
|
||||
gradientStyle={{ paddingVertical: 8, paddingHorizontal: 16 }}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
})}
|
||||
</View>
|
||||
{errorMessage ? <Text style={styles.errorText}>{errorMessage}</Text> : null}
|
||||
</View>
|
||||
) : null}
|
||||
<GradientButton title="Voir les abonnements" onPress={handleOpenPlans} />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={[
|
||||
styles.advantagesList,
|
||||
useWebLayout ? styles.advantagesListWeb : styles.advantagesListMobile,
|
||||
]}
|
||||
>
|
||||
{advantages.map((advantage) => {
|
||||
const accent = advantage.accent || Palette.white
|
||||
const iconType = advantage.iconType || 'image'
|
||||
|
||||
return (
|
||||
<View
|
||||
key={advantage.title}
|
||||
style={[
|
||||
styles.advantageCard,
|
||||
useWebLayout ? styles.advantageCardWeb : styles.advantageCardMobile,
|
||||
]}
|
||||
>
|
||||
{hasActiveSubscription ? (
|
||||
<MaterialCommunityIcons
|
||||
name="check"
|
||||
size={useWebLayout ? 22 : 20}
|
||||
color={Palette.green}
|
||||
style={[
|
||||
styles.advantageCheck,
|
||||
useWebLayout ? styles.advantageCheckWeb : styles.advantageCheckMobile,
|
||||
]}
|
||||
/>
|
||||
) : null}
|
||||
<View
|
||||
style={[
|
||||
styles.advantageIcon,
|
||||
useWebLayout && styles.advantageIconWeb,
|
||||
{
|
||||
backgroundColor: `${ICON_BASE_ACCENT}1F`,
|
||||
borderColor: `${ICON_BASE_ACCENT}55`,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{iconType === 'vector' ? (
|
||||
<MaterialCommunityIcons name={advantage.iconName} size={24} color={accent} />
|
||||
) : (
|
||||
<ExpoImage
|
||||
source={advantage.icon}
|
||||
contentFit="contain"
|
||||
style={[styles.advantageIconImage, { tintColor: accent }]}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<View
|
||||
style={[
|
||||
styles.advantageContent,
|
||||
useWebLayout && styles.advantageContentWeb,
|
||||
hasActiveSubscription && !useWebLayout && { paddingRight: 10 },
|
||||
]}
|
||||
>
|
||||
<Text style={[styles.advantageTitle, useWebLayout && styles.advantageTextCenter]}>
|
||||
{advantage.title}
|
||||
</Text>
|
||||
<Text style={[styles.advantageText, useWebLayout && styles.advantageTextCenter]}>
|
||||
{advantage.description}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
})}
|
||||
</View>
|
||||
|
||||
<ClubCard
|
||||
image={icons.clubIcon}
|
||||
onPress={handleOpenPlans}
|
||||
hasActiveSubscription={hasActiveSubscription}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -549,22 +549,7 @@ const SongDownload = ({ route }) => {
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{showSubscriptionCta ? (
|
||||
<View style={styles.subscriptionCta}>
|
||||
<Text style={styles.subscriptionNote}>
|
||||
Avec un abonnement, le téléchargement est gratuit.
|
||||
</Text>
|
||||
<GradientButton
|
||||
title="Voir les abonnements"
|
||||
onPress={() => navigate(Routes.Payments)}
|
||||
containerStyle={styles.subscriptionButton}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<Text style={styles.subscriptionNote}>
|
||||
Avec ton abonnement, le téléchargement est gratuit.
|
||||
</Text>
|
||||
)}
|
||||
|
||||
|
||||
<ClubAdvantagesCard style={styles.clubCardSpacing} />
|
||||
</ScrollView>
|
||||
|
||||
Reference in New Issue
Block a user