This commit is contained in:
@@ -67,6 +67,11 @@ export default function OrderHistoryScreen() {
|
||||
telegram_notifications_enabled: false,
|
||||
two_fa_enabled: false,
|
||||
contact_telegram: "",
|
||||
client_color_primary: "",
|
||||
client_color_secondary: "",
|
||||
client_color_success: "",
|
||||
client_color_danger: "",
|
||||
client_color_warning: "",
|
||||
});
|
||||
const [referralBalance, setReferralBalance] = useState(0);
|
||||
const [pointsRewards, setPointsRewards] = useState<{
|
||||
|
||||
@@ -274,6 +274,21 @@ export default function OrderTrackingScreen() {
|
||||
gap: spacing.s,
|
||||
marginTop: spacing.l,
|
||||
},
|
||||
confirmBanner: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
gap: spacing.s,
|
||||
backgroundColor: colors.success,
|
||||
borderRadius: borderRadius.md,
|
||||
paddingVertical: spacing.m,
|
||||
marginTop: spacing.m,
|
||||
},
|
||||
confirmBannerText: {
|
||||
color: "#fff",
|
||||
fontWeight: "700",
|
||||
fontSize: fontSize.sm,
|
||||
},
|
||||
proposalBox: {
|
||||
backgroundColor: colors.warning + "18",
|
||||
borderWidth: 1,
|
||||
@@ -466,6 +481,16 @@ export default function OrderTrackingScreen() {
|
||||
color={colors.textMuted}
|
||||
/>
|
||||
</View>
|
||||
{canConfirm && (
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.85}
|
||||
onPress={() => setConfirmingId(order.id)}
|
||||
style={styles.confirmBanner}
|
||||
>
|
||||
<Ionicons name="checkmark-circle-outline" size={18} color="#fff" />
|
||||
<Text style={styles.confirmBannerText}>Valider la réception</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{order.address_proposal_status === "pending" &&
|
||||
order.proposed_address && (
|
||||
<View style={styles.proposalBox}>
|
||||
@@ -602,18 +627,6 @@ export default function OrderTrackingScreen() {
|
||||
variant="outline"
|
||||
size="sm"
|
||||
/>
|
||||
{canConfirm && (
|
||||
<Button
|
||||
title="Confirmer reception"
|
||||
onPress={() =>
|
||||
setConfirmingId(
|
||||
order.id,
|
||||
)
|
||||
}
|
||||
variant="success"
|
||||
size="sm"
|
||||
/>
|
||||
)}
|
||||
{canCancel && (
|
||||
<Button
|
||||
title="Annuler"
|
||||
|
||||
@@ -41,6 +41,7 @@ export default function ProductDetailScreen() {
|
||||
const [adding, setAdding] = useState(false);
|
||||
const [showSuccess, setShowSuccess] = useState(false);
|
||||
const [showQuantityPicker, setShowQuantityPicker] = useState(false);
|
||||
const [stockWarning, setStockWarning] = useState<{ wanted: number; available: number } | null>(null);
|
||||
const [showVideo, setShowVideo] = useState(false);
|
||||
const [catColor, setCatColor] = useState<string>("#7c3aed");
|
||||
|
||||
@@ -95,6 +96,10 @@ export default function ProductDetailScreen() {
|
||||
|
||||
const handleAddToCart = async () => {
|
||||
if (!product || isOutOfStock || selectedGrams === null) return;
|
||||
if (product.stock > 0 && selectedGrams > product.stock) {
|
||||
setStockWarning({ wanted: selectedGrams, available: product.stock });
|
||||
return;
|
||||
}
|
||||
setAdding(true);
|
||||
try {
|
||||
await addToCart({
|
||||
@@ -794,6 +799,42 @@ export default function ProductDetailScreen() {
|
||||
</View>
|
||||
</Pressable>
|
||||
</Modal>
|
||||
|
||||
{/* Modal stock insuffisant */}
|
||||
<Modal
|
||||
visible={stockWarning !== null}
|
||||
transparent
|
||||
animationType="fade"
|
||||
onRequestClose={() => setStockWarning(null)}
|
||||
>
|
||||
<Pressable
|
||||
style={{ flex: 1, backgroundColor: "rgba(0,0,0,0.6)", justifyContent: "center", alignItems: "center", padding: 24 }}
|
||||
onPress={() => setStockWarning(null)}
|
||||
>
|
||||
<Pressable
|
||||
style={{ backgroundColor: colors.bgCard, borderRadius: 16, padding: 28, width: "100%", maxWidth: 340, alignItems: "center" }}
|
||||
onPress={() => {}}
|
||||
>
|
||||
<Text style={{ fontSize: 36, marginBottom: 12 }}>⚠️</Text>
|
||||
<Text style={{ fontSize: 17, fontWeight: "700", color: colors.textPrimary, marginBottom: 8, textAlign: "center" }}>
|
||||
Stock insuffisant
|
||||
</Text>
|
||||
<Text style={{ fontSize: 14, color: colors.textMuted, textAlign: "center", marginBottom: 20, lineHeight: 20 }}>
|
||||
Vous avez sélectionné{" "}
|
||||
<Text style={{ fontWeight: "700", color: colors.textPrimary }}>{stockWarning?.wanted}g</Text>
|
||||
{" "}mais il ne reste que{" "}
|
||||
<Text style={{ fontWeight: "700", color: "#ef4444" }}>{stockWarning?.available}g</Text>
|
||||
{" "}disponible pour ce produit.
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
onPress={() => setStockWarning(null)}
|
||||
style={{ backgroundColor: "#ef4444", borderRadius: 10, paddingVertical: 12, paddingHorizontal: 32 }}
|
||||
>
|
||||
<Text style={{ color: "#fff", fontWeight: "700", fontSize: 15 }}>OK</Text>
|
||||
</TouchableOpacity>
|
||||
</Pressable>
|
||||
</Pressable>
|
||||
</Modal>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,13 @@ export default function ProductsScreen() {
|
||||
const scaleAnim = useRef(new Animated.Value(1)).current;
|
||||
|
||||
useEffect(() => {
|
||||
getCategories().then(setCategories);
|
||||
getCategories().then((cats) => {
|
||||
const sorted = [...cats].sort((a, b) => {
|
||||
if (a.is_coming_soon === b.is_coming_soon) return 0;
|
||||
return a.is_coming_soon ? 1 : -1;
|
||||
});
|
||||
setCategories(sorted);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user