From 51c65d11797bbf8f51d03959e3f725351a22638c Mon Sep 17 00:00:00 2001 From: Xor290 Date: Sat, 7 Mar 2026 23:26:30 +0100 Subject: [PATCH] chore: update point system --- frontend-admin/src/api/api_admin.ts | 12 +- .../src/screens/admin/SettingsScreen.tsx | 210 +++++++++++------- 2 files changed, 142 insertions(+), 80 deletions(-) diff --git a/frontend-admin/src/api/api_admin.ts b/frontend-admin/src/api/api_admin.ts index 458af2b5..cefcae2f 100644 --- a/frontend-admin/src/api/api_admin.ts +++ b/frontend-admin/src/api/api_admin.ts @@ -661,6 +661,12 @@ export const deleteCategoryAdmin = async ( // PARAMÈTRES GLOBAUX // ============================================ +export interface PointsTier { + min: number; + max: number; // 0 = illimité + points: number; +} + export interface AppSettings { penalties_enabled: boolean; show_amende_score: boolean; @@ -668,10 +674,8 @@ export interface AppSettings { points_categories_weed: string[]; points_categories_zipette: string[]; points_separated: boolean; - points_weed_threshold_price: number; - points_weed_per_threshold: number; - points_zipette_threshold_price: number; - points_zipette_per_threshold: number; + points_weed_tiers: PointsTier[]; + points_zipette_tiers: PointsTier[]; } export const getSettings = async (): Promise<{ success: boolean; settings?: AppSettings; error?: string }> => { diff --git a/frontend-admin/src/screens/admin/SettingsScreen.tsx b/frontend-admin/src/screens/admin/SettingsScreen.tsx index 570789eb..b9563532 100644 --- a/frontend-admin/src/screens/admin/SettingsScreen.tsx +++ b/frontend-admin/src/screens/admin/SettingsScreen.tsx @@ -13,12 +13,127 @@ import { Ionicons } from "@expo/vector-icons"; import { spacing, fontSize, borderRadius } from "../../theme"; import { useTheme } from "../../context/ThemeContext"; import { getSettings, updateSettings, getCategories } from "../../api/api_admin"; -import type { AppSettings, Category } from "../../api/api_admin"; +import type { AppSettings, Category, PointsTier } from "../../api/api_admin"; import AlertModal from "../../components/ui/AlertModal"; import { useAlert } from "../../hooks/useAlert"; type PoolAssignment = "weed" | "zipette" | "none"; +// ────────────────────────────────────────────────────────────── +// Composant éditeur de paliers +// ────────────────────────────────────────────────────────────── +function TiersSection({ + title, + tiers, + onChange, + colors, + s, + accentColor, +}: { + title: string; + tiers: PointsTier[]; + onChange: (tiers: PointsTier[]) => void; + colors: any; + s: any; + accentColor: string; +}) { + const updateTier = (i: number, field: keyof PointsTier, raw: string) => { + const val = field === "points" ? parseInt(raw, 10) : parseFloat(raw); + if (isNaN(val)) return; + const next = tiers.map((t, idx) => (idx === i ? { ...t, [field]: val } : t)); + onChange(next); + }; + + const addTier = () => { + onChange([...tiers, { min: 0, max: 0, points: 1 }]); + }; + + const removeTier = (i: number) => { + onChange(tiers.filter((_, idx) => idx !== i)); + }; + + return ( + + {title} + + Définissez chaque palier : de X€ à Y€ = N points.{"\n"} + Max = 0 signifie illimité (pas de borne supérieure). + + + {/* En-tête colonnes */} + + Min € + Max € + Pts + + + {tiers.map((tier, i) => ( + + updateTier(i, "min", v)} + /> + + updateTier(i, "max", v)} + placeholder="0=∞" + placeholderTextColor={colors.textMuted} + /> + = + updateTier(i, "points", v)} + /> + pts + removeTier(i)}> + + + + ))} + + {tiers.length === 0 && ( + Aucun palier défini + )} + + + + + Ajouter un palier + + + + ); +} + export default function SettingsScreen() { const { colors } = useTheme(); const { alert, showError, showSuccess, hideAlert } = useAlert(); @@ -32,10 +147,8 @@ export default function SettingsScreen() { points_categories_weed: [], points_categories_zipette: [], points_separated: true, - points_weed_threshold_price: 30, - points_weed_per_threshold: 1, - points_zipette_threshold_price: 30, - points_zipette_per_threshold: 1, + points_weed_tiers: [], + points_zipette_tiers: [], }); const [categories, setCategories] = useState([]); @@ -372,77 +485,22 @@ export default function SettingsScreen() { {/* Barème de points */} - - Barème de points - - Pour chaque tranche de prix dépensée, le client gagne un nombre de points.{"\n"} - Exemple : 50€ = 2 pts → 100€ = 4 pts, 150€ = 6 pts... - - - {/* Weed */} - - - Pool Weed / Hash - Prix seuil → points gagnés - - - { - const n = parseFloat(v); - if (!isNaN(n) && n > 0) - setSettings((p) => ({ ...p, points_weed_threshold_price: n })); - }} - /> - € = - { - const n = parseInt(v, 10); - if (!isNaN(n) && n >= 0) - setSettings((p) => ({ ...p, points_weed_per_threshold: n })); - }} - /> - pts - - - - {/* Zipette */} - - - Pool Zipette - Prix seuil → points gagnés - - - { - const n = parseFloat(v); - if (!isNaN(n) && n > 0) - setSettings((p) => ({ ...p, points_zipette_threshold_price: n })); - }} - /> - € = - { - const n = parseInt(v, 10); - if (!isNaN(n) && n >= 0) - setSettings((p) => ({ ...p, points_zipette_per_threshold: n })); - }} - /> - pts - - - + setSettings((p) => ({ ...p, points_weed_tiers: tiers }))} + colors={colors} + s={s} + accentColor={WEED_COLOR} + /> + setSettings((p) => ({ ...p, points_zipette_tiers: tiers }))} + colors={colors} + s={s} + accentColor={ZIP_COLOR} + />