last tickets

This commit is contained in:
Thomas Demirdjian
2025-11-24 15:35:14 +01:00
parent 471a3177e8
commit 72852ad92b
40 changed files with 1749 additions and 667 deletions
+12 -4
View File
@@ -1,7 +1,6 @@
import { useFocusEffect } from "@react-navigation/native";
import React, { useCallback, useMemo, useState } from "react";
import { Alert, Platform, StyleSheet, Text, View } from "react-native";
import BorderGradientButton from "../../components/BorderGradientButton";
import CreditAmount from "../../components/CreditAmount";
import { background } from "../../assets";
@@ -14,6 +13,7 @@ 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";
@@ -46,7 +46,7 @@ const PERIOD_LABELS = {
annual: "Annuel",
};
const PAGE_BACKGROUND_COLOR = "#303438";
const PAGE_BACKGROUND_COLOR = "#252438";
const getStatusColors = (status) => {
switch (status) {
@@ -263,7 +263,9 @@ const ManageSubscription = ({ navigation }) => {
const statusSource =
pickString(currentUserData?.stripeSubscriptionStatus) ||
pickString(pickFromSources((source) => source?.status)) ||
pickString(pickFromSources((source) => source?.stripeSubscriptionStatus)) ||
pickString(
pickFromSources((source) => source?.stripeSubscriptionStatus),
) ||
pickString(pickFromSources((source) => source?.metadata?.status)) ||
null;
@@ -291,7 +293,9 @@ const ManageSubscription = ({ navigation }) => {
const candidates = [
pickString(pickFromSources((source) => source?.billingPeriod)),
pickString(currentUserData?.premiumBillingPeriod),
pickString(pickFromSources((source) => source?.metadata?.billingPeriod)),
pickString(
pickFromSources((source) => source?.metadata?.billingPeriod),
),
pickString(
pickFromSources(
(source) => source?.metadata?.subscriptionBillingPeriod,
@@ -716,6 +720,7 @@ const ManageSubscription = ({ navigation }) => {
/>
</View>
)}
<ClubAdvantagesCard isDev style={styles.clubCardSpacing} />
</View>
</Page>
);
@@ -808,6 +813,9 @@ const styles = StyleSheet.create({
emptyButton: {
marginTop: gutters * 1.5,
},
clubCardSpacing: {
marginTop: gutters,
},
});
export default ManageSubscription;
@@ -0,0 +1,344 @@
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 { 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 { isWeb } from "../../../hooks/useLayoutType";
const ICON_BASE_ACCENT = "#A96BFF";
const CLUB_ADVANTAGES = [
{
title: "Revenus partagés",
description: "Gagne sur tes écoutes et ta popularité.",
iconType: "vector",
iconName: "currency-usd",
accent: "#F8C24D",
},
{
title: "Concours hit du mois",
description: "Vise le podium du mois et empoche la récompense.",
iconType: "vector",
iconName: "chart-line",
accent: "#7AE0FF",
},
{
title: "Crédits mensuels",
description: "Des crédits premium tous les mois pour créer plus.",
iconType: "image",
icon: icons.coin,
accent: ICON_BASE_ACCENT,
},
];
const ClubAdvantagesCard = ({ style, isDev = false }) => {
const navigation = useNavigation();
const { hasActiveSubscription } = useUserData() || {};
const [useWebLayout, setUseWebLayout] = React.useState(isWeb);
const advantages = CLUB_ADVANTAGES;
React.useEffect(() => {
if (!isDev) {
setUseWebLayout(isWeb);
}
}, [isDev, isWeb]);
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 handleOpenPlans = () => {
navigation.navigate(Routes.Payments);
};
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>
</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,
]}
>
<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>
);
};
const styles = StyleSheet.create({
card: {
paddingHorizontal: gutters * 1.25,
paddingVertical: gutters,
borderRadius: 24,
backgroundColor: "#252438",
borderWidth: 1,
gap: gutters,
borderColor: "white",
},
cardInactive: {
borderColor: "rgba(255, 255, 255, 0.08)",
},
cardActive: {
borderColor: Palette.green,
},
header: {
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,
gap: gutters * 0.3,
alignItems: "center",
},
title: {
fontFamily: FONT_FAMILY.InterSemiBold,
fontSize: 18,
color: Palette.white,
textAlign: "center",
},
subtitle: {
fontFamily: FONT_FAMILY.InterRegular,
fontSize: 13,
color: "rgba(255, 255, 255, 0.82)",
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: {
width: "100%",
position: "relative",
},
advantageIcon: {
width: 42,
height: 42,
borderRadius: 12,
alignItems: "center",
justifyContent: "center",
borderWidth: 1,
},
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,
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",
},
advantageCheckWeb: {
top: 10,
right: 10,
},
advantageCheckMobile: {
top: "50%",
right: 12,
transform: [{ translateY: -10 }],
},
});
export default ClubAdvantagesCard;