continue subscriptions and coins
This commit is contained in:
@@ -18,12 +18,7 @@ const ORDER_TYPE_LABELS = {
|
||||
GIFT: "Crédit offert",
|
||||
COINS: "Achat de coins",
|
||||
SONG: "Génération de musique",
|
||||
};
|
||||
|
||||
const STATUS_LABELS = {
|
||||
PENDING: "En cours",
|
||||
APPLIED: "Confirmée",
|
||||
REJECTED: "Refusée",
|
||||
SUBSCRIPTION: "Abonnement",
|
||||
};
|
||||
|
||||
const formatCoins = (amount) => {
|
||||
@@ -39,26 +34,39 @@ const formatCoins = (amount) => {
|
||||
}
|
||||
};
|
||||
|
||||
const formatDate = (date) => {
|
||||
const formatDateParts = (date) => {
|
||||
if (!date) {
|
||||
return "En attente de confirmation";
|
||||
return {
|
||||
dateLabel: "En attente de confirmation",
|
||||
timeLabel: "",
|
||||
};
|
||||
}
|
||||
try {
|
||||
return date.toLocaleString("fr-FR", {
|
||||
const dateLabel = date.toLocaleDateString("fr-FR", {
|
||||
day: "2-digit",
|
||||
month: "short",
|
||||
year: "numeric",
|
||||
});
|
||||
const timeLabel = date.toLocaleTimeString("fr-FR", {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
return { dateLabel, timeLabel };
|
||||
} catch (_error) {
|
||||
return date.toString();
|
||||
return {
|
||||
dateLabel: date.toString(),
|
||||
timeLabel: "",
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const mapOrderType = (type) => ORDER_TYPE_LABELS[type] || "Opération";
|
||||
|
||||
const mapStatus = (status) => STATUS_LABELS[status] || "Inconnue";
|
||||
const shortenIdentifier = (value, visible = 6) => {
|
||||
if (typeof value !== "string") return null;
|
||||
if (value.length <= visible + 2) return value;
|
||||
return `${value.slice(0, visible)}…`;
|
||||
};
|
||||
|
||||
const OrderHistory = () => {
|
||||
const { currentUID } = useUser() || {};
|
||||
@@ -126,64 +134,64 @@ const OrderHistory = () => {
|
||||
: 0;
|
||||
const isPositive = amountValue > 0;
|
||||
const amountLabel = `${isPositive ? "+" : ""}${formatCoins(amountValue)} ${
|
||||
amountValue === 1 ? "coin" : "coins"
|
||||
Math.abs(amountValue) === 1 ? "coin" : "coins"
|
||||
}`;
|
||||
|
||||
const status = item.status || "PENDING";
|
||||
const { dateLabel } = formatDateParts(item.createdAt);
|
||||
|
||||
const details = (() => {
|
||||
if (item.type === "GIFT" && item.metadata?.reason) {
|
||||
switch (item.metadata.reason) {
|
||||
case "WELCOME_BONUS":
|
||||
return "Crédit de bienvenue";
|
||||
default:
|
||||
return item.metadata.reason;
|
||||
}
|
||||
let reasonLabel = mapOrderType(item.type);
|
||||
|
||||
if (item.type === "GIFT") {
|
||||
const reason = item.metadata?.reason;
|
||||
if (reason === "WELCOME_BONUS") {
|
||||
reasonLabel = "Crédit de bienvenue";
|
||||
} else if (typeof reason === "string" && reason.trim()) {
|
||||
reasonLabel = reason.trim();
|
||||
}
|
||||
if (item.type === "SONG" && item.songId) {
|
||||
return `Musique ${item.songId}`;
|
||||
} else if (item.type === "SONG") {
|
||||
reasonLabel = "Génération de musique";
|
||||
} else if (item.type === "COINS") {
|
||||
if (item.metadata?.coinPackKey) {
|
||||
const shortenedPack = shortenIdentifier(
|
||||
item.metadata.coinPackKey,
|
||||
10,
|
||||
);
|
||||
reasonLabel = `Pack ${shortenedPack || item.metadata.coinPackKey}`;
|
||||
} else if (
|
||||
typeof item.metadata?.source === "string" &&
|
||||
item.metadata.source.trim()
|
||||
) {
|
||||
const source = item.metadata.source.trim();
|
||||
reasonLabel =
|
||||
source === "STRIPE_CHECKOUT" ? "Recharge Stripe" : source;
|
||||
} else {
|
||||
reasonLabel = "Rechargement de coins";
|
||||
}
|
||||
if (item.type === "COINS" && item.metadata?.paymentId) {
|
||||
return `Paiement ${item.metadata.paymentId}`;
|
||||
}
|
||||
return null;
|
||||
})();
|
||||
} else if (item.type === "SUBSCRIPTION") {
|
||||
const rawPeriod =
|
||||
typeof item.metadata?.billingPeriod === "string"
|
||||
? item.metadata.billingPeriod.toLowerCase()
|
||||
: null;
|
||||
reasonLabel =
|
||||
rawPeriod === "annual"
|
||||
? "Abonnement annuel"
|
||||
: rawPeriod === "monthly"
|
||||
? "Abonnement mensuel"
|
||||
: "Abonnement";
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.orderCard}>
|
||||
<View style={styles.orderHeader}>
|
||||
<Text style={styles.orderTitle}>{mapOrderType(item.type)}</Text>
|
||||
<Text
|
||||
style={[
|
||||
styles.orderAmount,
|
||||
isPositive ? styles.amountPositive : styles.amountNegative,
|
||||
]}
|
||||
>
|
||||
{amountLabel}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.orderMetaRow}>
|
||||
<Text style={styles.orderDate}>{formatDate(item.createdAt)}</Text>
|
||||
<View
|
||||
style={[
|
||||
styles.statusBadge,
|
||||
status === "APPLIED"
|
||||
? styles.statusApplied
|
||||
: status === "REJECTED"
|
||||
? styles.statusRejected
|
||||
: styles.statusPending,
|
||||
]}
|
||||
>
|
||||
<Text style={styles.statusText}>{mapStatus(status)}</Text>
|
||||
</View>
|
||||
</View>
|
||||
{details ? <Text style={styles.orderDetails}>{details}</Text> : null}
|
||||
{typeof item.balanceAfter === "number" &&
|
||||
Number.isFinite(item.balanceAfter) ? (
|
||||
<Text style={styles.orderBalance}>
|
||||
Solde après opération: {formatCoins(item.balanceAfter)} coins
|
||||
</Text>
|
||||
) : null}
|
||||
<Text
|
||||
style={[
|
||||
styles.orderAmount,
|
||||
isPositive ? styles.amountPositive : styles.amountNegative,
|
||||
]}
|
||||
>
|
||||
{amountLabel}
|
||||
</Text>
|
||||
<Text style={styles.orderReason}>{reasonLabel}</Text>
|
||||
<Text style={styles.orderTimestamp}>{dateLabel}</Text>
|
||||
</View>
|
||||
);
|
||||
}, []);
|
||||
@@ -268,19 +276,7 @@ const styles = StyleSheet.create({
|
||||
backgroundColor: Palette.ultraLightWhite,
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255, 255, 255, 0.08)",
|
||||
},
|
||||
orderHeader: {
|
||||
flexDirection: "row",
|
||||
alignItems: "flex-start",
|
||||
justifyContent: "space-between",
|
||||
marginBottom: 8,
|
||||
gap: 12,
|
||||
},
|
||||
orderTitle: {
|
||||
flex: 1,
|
||||
fontSize: 16,
|
||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||||
color: Palette.white,
|
||||
gap: 6,
|
||||
},
|
||||
orderAmount: {
|
||||
fontSize: 16,
|
||||
@@ -292,47 +288,15 @@ const styles = StyleSheet.create({
|
||||
amountNegative: {
|
||||
color: Palette.red,
|
||||
},
|
||||
orderMetaRow: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
marginBottom: 6,
|
||||
gap: 12,
|
||||
},
|
||||
orderDate: {
|
||||
fontSize: 13,
|
||||
color: Palette.grayMid,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
},
|
||||
statusBadge: {
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 4,
|
||||
borderRadius: 999,
|
||||
},
|
||||
statusApplied: {
|
||||
backgroundColor: Palette.transparentGreen,
|
||||
},
|
||||
statusPending: {
|
||||
backgroundColor: Palette.transparentOrange,
|
||||
},
|
||||
statusRejected: {
|
||||
backgroundColor: Palette.transparentRed,
|
||||
},
|
||||
statusText: {
|
||||
fontSize: 12,
|
||||
fontFamily: FONT_FAMILY.InterMedium,
|
||||
color: Palette.white,
|
||||
},
|
||||
orderDetails: {
|
||||
marginBottom: 6,
|
||||
orderReason: {
|
||||
fontSize: 14,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
color: Palette.white,
|
||||
},
|
||||
orderBalance: {
|
||||
fontSize: 13,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
orderTimestamp: {
|
||||
fontSize: 12,
|
||||
color: Palette.grayMid,
|
||||
fontFamily: FONT_FAMILY.InterMedium,
|
||||
},
|
||||
emptyText: {
|
||||
textAlign: "center",
|
||||
|
||||
Reference in New Issue
Block a user