chore: add parrainage

This commit is contained in:
2026-03-08 13:57:25 +01:00
parent 51c65d1179
commit fee1972435
20 changed files with 1356 additions and 348 deletions
+108 -10
View File
@@ -19,6 +19,7 @@ import {
deleteClientAdmin,
createClientByAdmin,
createUserByAdmin,
creditClientReferral,
} from "../../api/api_admin";
import type { ClientResponse } from "../../api/types";
import LoadingSpinner from "../../components/ui/LoadingSpinner";
@@ -155,6 +156,15 @@ export default function UsersScreen() {
const [createTel, setCreateTel] = useState("");
const [creating, setCreating] = useState(false);
// Referral credit modal
const [referralModal, setReferralModal] = useState<{
visible: boolean;
username: string;
currentBalance: number;
}>({ visible: false, username: "", currentBalance: 0 });
const [referralAmount, setReferralAmount] = useState("");
const [referralLoading, setReferralLoading] = useState(false);
const { alert, showError, showConfirm, hideAlert } = useAlert();
// --------------------------------------------------
@@ -318,6 +328,40 @@ export default function UsersScreen() {
);
};
// --------------------------------------------------
// Referral credit
// --------------------------------------------------
const openReferralModal = (client: ClientResponse) => {
setReferralAmount("");
setReferralModal({
visible: true,
username: client.username,
currentBalance: client.referral_balance ?? 0,
});
};
const handleCreditReferral = async () => {
const amount = parseFloat(referralAmount);
if (isNaN(amount) || amount <= 0) {
showError("Erreur", "Entrez un montant valide");
return;
}
setReferralLoading(true);
try {
const res = await creditClientReferral(referralModal.username, amount);
if (res.success) {
setReferralModal((prev) => ({ ...prev, visible: false }));
await loadData();
} else {
showError("Erreur", res.message || "Echec du crédit");
}
} catch (e: any) {
showError("Erreur", e.message);
} finally {
setReferralLoading(false);
}
};
// --------------------------------------------------
// Create user
// --------------------------------------------------
@@ -603,16 +647,28 @@ export default function UsersScreen() {
</View>
<View style={{ flexDirection: "row", gap: spacing.xs }}>
{isClient && (
<TouchableOpacity
style={styles.editIconBtn}
onPress={() => openEditClient(item.clientData!)}
>
<Ionicons
name="create-outline"
size={20}
color={colors.info}
/>
</TouchableOpacity>
<>
<TouchableOpacity
style={styles.editIconBtn}
onPress={() => openReferralModal(item.clientData!)}
>
<Ionicons
name="gift-outline"
size={20}
color={colors.success}
/>
</TouchableOpacity>
<TouchableOpacity
style={styles.editIconBtn}
onPress={() => openEditClient(item.clientData!)}
>
<Ionicons
name="create-outline"
size={20}
color={colors.info}
/>
</TouchableOpacity>
</>
)}
{(item.role === "livreur" ||
item.role === "cabine") && (
@@ -704,6 +760,19 @@ export default function UsersScreen() {
</Text>
<Text style={styles.statLabel}>Annul.</Text>
</View>
{(item.clientData.referral_balance ?? 0) > 0 && (
<View style={styles.stat}>
<Text
style={[
styles.statValue,
{ color: colors.success },
]}
>
{(item.clientData.referral_balance ?? 0).toFixed(0)}
</Text>
<Text style={styles.statLabel}>Parrain</Text>
</View>
)}
</View>
</>
)}
@@ -977,6 +1046,35 @@ export default function UsersScreen() {
confirmText={alert.confirmText}
cancelText={alert.cancelText}
/>
{/* Modal crédit parrainage */}
<Modal
visible={referralModal.visible}
onClose={() => setReferralModal((prev) => ({ ...prev, visible: false }))}
title={`Crédit parrainage — ${referralModal.username}`}
icon="gift-outline"
iconColor={colors.success}
>
<Text style={{ color: colors.textSecondary, fontSize: fontSize.sm, marginBottom: spacing.s }}>
Solde actuel : {referralModal.currentBalance.toFixed(2)} €
</Text>
<TextInput
placeholder="Montant à créditer (ex: 10)"
value={referralAmount}
onChangeText={setReferralAmount}
keyboardType="decimal-pad"
icon={<Ionicons name="cash-outline" size={18} color={colors.textMuted} />}
/>
<Button
title={referralLoading ? "Chargement..." : "Créditer"}
onPress={handleCreditReferral}
disabled={referralLoading}
variant="success"
size="md"
fullWidth
style={{ marginTop: spacing.m }}
/>
</Modal>
</View>
);
}