feat: fixes and formatter
This commit is contained in:
+112
-141
@@ -1,210 +1,181 @@
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import {
|
||||
ActivityIndicator,
|
||||
FlatList,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from "react-native";
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { ActivityIndicator, FlatList, StyleSheet, Text, View } from 'react-native'
|
||||
|
||||
import firebase from "../../config/firebase";
|
||||
import { background } from "../../assets";
|
||||
import Page from "../../layouts/Page";
|
||||
import { useUser } from "../../providers/UserDataProvider";
|
||||
import { gutters, Palette } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import CreditAmount from "../../components/CreditAmount";
|
||||
import firebase from '../../config/firebase'
|
||||
import { background } from '../../assets'
|
||||
import Page from '../../layouts/Page'
|
||||
import { useUser } from '../../providers/UserDataProvider'
|
||||
import { gutters, Palette } from '../../styles'
|
||||
import { FONT_FAMILY } from '../../styles/Fonts'
|
||||
import CreditAmount from '../../components/CreditAmount'
|
||||
|
||||
const ORDER_TYPE_LABELS = {
|
||||
GIFT: "Crédit offert",
|
||||
COINS: "Achat de coins",
|
||||
SONG: "Génération de musique",
|
||||
SUBSCRIPTION: "Abonnement",
|
||||
};
|
||||
GIFT: 'Crédit offert',
|
||||
COINS: 'Achat de coins',
|
||||
SONG: 'Génération de musique',
|
||||
SUBSCRIPTION: 'Abonnement',
|
||||
}
|
||||
|
||||
const formatDateParts = (date) => {
|
||||
if (!date) {
|
||||
return {
|
||||
dateLabel: "En attente de confirmation",
|
||||
timeLabel: "",
|
||||
};
|
||||
dateLabel: 'En attente de confirmation',
|
||||
timeLabel: '',
|
||||
}
|
||||
}
|
||||
try {
|
||||
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 };
|
||||
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 {
|
||||
dateLabel: date.toString(),
|
||||
timeLabel: "",
|
||||
};
|
||||
timeLabel: '',
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const mapOrderType = (type) => ORDER_TYPE_LABELS[type] || "Opération";
|
||||
const mapOrderType = (type) => ORDER_TYPE_LABELS[type] || 'Opération'
|
||||
|
||||
const shortenIdentifier = (value, visible = 6) => {
|
||||
if (typeof value !== "string") return null;
|
||||
if (value.length <= visible + 2) return value;
|
||||
return `${value.slice(0, visible)}…`;
|
||||
};
|
||||
if (typeof value !== 'string') return null
|
||||
if (value.length <= visible + 2) return value
|
||||
return `${value.slice(0, visible)}…`
|
||||
}
|
||||
|
||||
const OrderHistory = () => {
|
||||
const { currentUID } = useUser() || {};
|
||||
const [orders, setOrders] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
const { currentUID } = useUser() || {}
|
||||
const [orders, setOrders] = useState([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (!currentUID) {
|
||||
setOrders([]);
|
||||
setLoading(false);
|
||||
return;
|
||||
setOrders([])
|
||||
setLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
|
||||
const unsubscribe = firebase
|
||||
.firestore()
|
||||
.collection("orders")
|
||||
.where("userId", "==", currentUID)
|
||||
.orderBy("createdAt", "desc")
|
||||
.collection('orders')
|
||||
.where('userId', '==', currentUID)
|
||||
.orderBy('createdAt', 'desc')
|
||||
.onSnapshot(
|
||||
(snapshot) => {
|
||||
const nextOrders = snapshot.docs.map((doc) => {
|
||||
const rawData = doc.data() || {};
|
||||
const rawData = doc.data() || {}
|
||||
const createdAt =
|
||||
typeof rawData.createdAt?.toDate === "function"
|
||||
? rawData.createdAt.toDate()
|
||||
: null;
|
||||
typeof rawData.createdAt?.toDate === 'function' ? rawData.createdAt.toDate() : null
|
||||
return {
|
||||
id: doc.id,
|
||||
...rawData,
|
||||
createdAt,
|
||||
};
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
setOrders(nextOrders);
|
||||
setLoading(false);
|
||||
setOrders(nextOrders)
|
||||
setLoading(false)
|
||||
},
|
||||
(firestoreError) => {
|
||||
console.warn(
|
||||
"[OrderHistory] Unable to load orders",
|
||||
firestoreError?.message || firestoreError,
|
||||
);
|
||||
setError(
|
||||
firestoreError?.message ||
|
||||
"Impossible de récupérer l'historique des commandes.",
|
||||
);
|
||||
setLoading(false);
|
||||
},
|
||||
);
|
||||
'[OrderHistory] Unable to load orders',
|
||||
firestoreError?.message || firestoreError
|
||||
)
|
||||
setError(firestoreError?.message || "Impossible de récupérer l'historique des commandes.")
|
||||
setLoading(false)
|
||||
}
|
||||
)
|
||||
|
||||
return () => {
|
||||
if (typeof unsubscribe === "function") {
|
||||
unsubscribe();
|
||||
if (typeof unsubscribe === 'function') {
|
||||
unsubscribe()
|
||||
}
|
||||
};
|
||||
}, [currentUID]);
|
||||
}
|
||||
}, [currentUID])
|
||||
|
||||
const renderOrder = useCallback(({ item }) => {
|
||||
const amountValue =
|
||||
typeof item.amount === "number" && Number.isFinite(item.amount)
|
||||
? item.amount
|
||||
: 0;
|
||||
const isPositive = amountValue > 0;
|
||||
typeof item.amount === 'number' && Number.isFinite(item.amount) ? item.amount : 0
|
||||
const isPositive = amountValue > 0
|
||||
const amountTextStyle = [
|
||||
styles.orderAmount,
|
||||
isPositive ? styles.amountPositive : styles.amountNegative,
|
||||
];
|
||||
]
|
||||
|
||||
const { dateLabel } = formatDateParts(item.createdAt);
|
||||
const { dateLabel } = formatDateParts(item.createdAt)
|
||||
|
||||
let reasonLabel = mapOrderType(item.type);
|
||||
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 === '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()
|
||||
}
|
||||
} else if (item.type === "SONG") {
|
||||
reasonLabel = "Génération de musique";
|
||||
} else if (item.type === "COINS") {
|
||||
} 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;
|
||||
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";
|
||||
reasonLabel = 'Rechargement de coins'
|
||||
}
|
||||
} else if (item.type === "SUBSCRIPTION") {
|
||||
} else if (item.type === 'SUBSCRIPTION') {
|
||||
const rawPeriod =
|
||||
typeof item.metadata?.billingPeriod === "string"
|
||||
typeof item.metadata?.billingPeriod === 'string'
|
||||
? item.metadata.billingPeriod.toLowerCase()
|
||||
: null;
|
||||
: null
|
||||
reasonLabel =
|
||||
rawPeriod === "annual"
|
||||
? "Abonnement annuel"
|
||||
: rawPeriod === "monthly"
|
||||
? "Abonnement mensuel"
|
||||
: "Abonnement";
|
||||
rawPeriod === 'annual'
|
||||
? 'Abonnement annuel'
|
||||
: rawPeriod === 'monthly'
|
||||
? 'Abonnement mensuel'
|
||||
: 'Abonnement'
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.orderCard}>
|
||||
<CreditAmount
|
||||
value={amountValue}
|
||||
showPlus
|
||||
textStyle={amountTextStyle}
|
||||
iconSize={18}
|
||||
/>
|
||||
<CreditAmount value={amountValue} showPlus textStyle={amountTextStyle} iconSize={18} />
|
||||
<Text style={styles.orderReason}>{reasonLabel}</Text>
|
||||
<Text style={styles.orderTimestamp}>{dateLabel}</Text>
|
||||
</View>
|
||||
);
|
||||
}, []);
|
||||
)
|
||||
}, [])
|
||||
|
||||
const keyExtractor = useCallback((item) => item.id, []);
|
||||
const keyExtractor = useCallback((item) => item.id, [])
|
||||
|
||||
const listEmptyComponent = useMemo(() => {
|
||||
if (loading) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
if (!currentUID) {
|
||||
return (
|
||||
<Text style={styles.emptyText}>
|
||||
Connecte-toi pour consulter l'historique de tes commandes.
|
||||
</Text>
|
||||
);
|
||||
)
|
||||
}
|
||||
if (error) {
|
||||
return <Text style={styles.errorText}>{error}</Text>;
|
||||
return <Text style={styles.errorText}>{error}</Text>
|
||||
}
|
||||
return (
|
||||
<Text style={styles.emptyText}>
|
||||
Aucune opération de coins pour le moment.
|
||||
</Text>
|
||||
);
|
||||
}, [loading, currentUID, error]);
|
||||
return <Text style={styles.emptyText}>Aucune opération de coins pour le moment.</Text>
|
||||
}, [loading, currentUID, error])
|
||||
|
||||
return (
|
||||
<Page
|
||||
@@ -213,7 +184,7 @@ const OrderHistory = () => {
|
||||
backgroundImg={background.profileBG}
|
||||
contentContainerStyle={{ paddingBottom: gutters * 2 }}
|
||||
containerStyle={{
|
||||
backgroundColor: "rgba(0,0,0,0.4)",
|
||||
backgroundColor: 'rgba(0,0,0,0.4)',
|
||||
}}
|
||||
>
|
||||
<View style={styles.container}>
|
||||
@@ -236,8 +207,8 @@ const OrderHistory = () => {
|
||||
)}
|
||||
</View>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
@@ -247,22 +218,22 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
loaderContainer: {
|
||||
flex: 1,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
listContent: {
|
||||
paddingBottom: gutters * 2,
|
||||
},
|
||||
emptyListContent: {
|
||||
flexGrow: 1,
|
||||
justifyContent: "center",
|
||||
justifyContent: 'center',
|
||||
},
|
||||
orderCard: {
|
||||
padding: 16,
|
||||
borderRadius: 16,
|
||||
backgroundColor: Palette.ultraLightWhite,
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255, 255, 255, 0.08)",
|
||||
borderColor: 'rgba(255, 255, 255, 0.08)',
|
||||
gap: 6,
|
||||
},
|
||||
orderAmount: {
|
||||
@@ -286,17 +257,17 @@ const styles = StyleSheet.create({
|
||||
fontFamily: FONT_FAMILY.InterMedium,
|
||||
},
|
||||
emptyText: {
|
||||
textAlign: "center",
|
||||
textAlign: 'center',
|
||||
color: Palette.grayMid,
|
||||
fontSize: 15,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
},
|
||||
errorText: {
|
||||
textAlign: "center",
|
||||
textAlign: 'center',
|
||||
color: Palette.red,
|
||||
fontSize: 15,
|
||||
fontFamily: FONT_FAMILY.InterRegular,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
export default OrderHistory;
|
||||
export default OrderHistory
|
||||
|
||||
Reference in New Issue
Block a user