chore: update

This commit is contained in:
2026-03-08 16:33:50 +01:00
parent 712d667d86
commit dc9e812391
5 changed files with 476 additions and 66 deletions
@@ -17,7 +17,7 @@ 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";
type PoolAssignment = "weed" | "zipette" | "total" | "none";
// ──────────────────────────────────────────────────────────────
// Composant éditeur de paliers
@@ -146,9 +146,11 @@ export default function SettingsScreen() {
points_enabled: true,
points_categories_weed: [],
points_categories_zipette: [],
points_categories_total: [],
points_separated: true,
points_weed_tiers: [],
points_zipette_tiers: [],
points_total_tiers: [],
referral_enabled: true,
});
const [categories, setCategories] = useState<Category[]>([]);
@@ -164,6 +166,8 @@ export default function SettingsScreen() {
...settingsRes.settings,
points_categories_weed: settingsRes.settings.points_categories_weed ?? [],
points_categories_zipette: settingsRes.settings.points_categories_zipette ?? [],
points_categories_total: settingsRes.settings.points_categories_total ?? [],
points_total_tiers: settingsRes.settings.points_total_tiers ?? [],
});
}
if (categoriesRes) {
@@ -179,6 +183,7 @@ export default function SettingsScreen() {
const getPoolFor = (name: string): PoolAssignment => {
if ((settings.points_categories_weed ?? []).includes(name)) return "weed";
if ((settings.points_categories_zipette ?? []).includes(name)) return "zipette";
if ((settings.points_categories_total ?? []).includes(name)) return "total";
return "none";
};
@@ -186,9 +191,11 @@ export default function SettingsScreen() {
setSettings((prev) => {
const weed = (prev.points_categories_weed ?? []).filter((c) => c !== name);
const zipette = (prev.points_categories_zipette ?? []).filter((c) => c !== name);
const total = (prev.points_categories_total ?? []).filter((c) => c !== name);
if (pool === "weed") weed.push(name);
else if (pool === "zipette") zipette.push(name);
return { ...prev, points_categories_weed: weed, points_categories_zipette: zipette };
else if (pool === "total") total.push(name);
return { ...prev, points_categories_weed: weed, points_categories_zipette: zipette, points_categories_total: total };
});
};
@@ -310,6 +317,17 @@ export default function SettingsScreen() {
const WEED_COLOR = "#10b981";
const ZIP_COLOR = "#9333ea";
const TOTAL_COLOR = "#f97316";
// Le mode séparé nécessite que W ET Z aient au moins une catégorie
const hasBothPools =
(settings.points_categories_weed ?? []).length > 0 &&
(settings.points_categories_zipette ?? []).length > 0;
// Chips disponibles selon le mode
const availableChips: PoolAssignment[] = settings.points_separated
? ["weed", "zipette", "none"] // mode séparé : T désactivé
: ["total", "none"]; // mode non-séparé : W/Z désactivés
return (
<View style={s.container}>
@@ -393,16 +411,20 @@ export default function SettingsScreen() {
thumbColor="#fff"
/>
</View>
<View style={s.row}>
<View style={[s.row, { opacity: hasBothPools ? 1 : 0.4 }]}>
<View style={s.rowLeft}>
<Text style={s.rowLabel}>Points séparés par pool</Text>
<Text style={s.rowDesc}>
Activé : Weed point / Zipette point_zipette{"\n"}
Désactivé : tout dans un seul compteur (point)
Désactivé : Barème Total sur la somme W+Z{"\n"}
{!hasBothPools && (
"⚠️ Nécessite des catégories W ET Z configurées"
)}
</Text>
</View>
<Switch
value={settings.points_separated}
disabled={!hasBothPools}
onValueChange={(v) =>
setSettings((prev) => ({ ...prev, points_separated: v }))
}
@@ -416,19 +438,30 @@ export default function SettingsScreen() {
<View style={s.section}>
<Text style={s.sectionTitle}>Attribution des catégories aux points</Text>
<Text style={s.hint}>
Pour chaque catégorie, choisis si elle génère des points Weed, Zipette, ou aucun.
{settings.points_separated
? "Mode séparé : W = pool Weed, Z = pool Zipette."
: "Mode non-séparé : T = pool Total (barème sur W+Z). W et Z désactivés."}
</Text>
{/* Légende */}
<View style={{ flexDirection: "row", gap: spacing.m, paddingHorizontal: spacing.l, paddingBottom: spacing.m }}>
<View style={{ flexDirection: "row", alignItems: "center", gap: spacing.xs }}>
<View style={[s.colorDot, { backgroundColor: WEED_COLOR }]} />
<Text style={{ fontSize: fontSize.sm, color: colors.textMuted }}>Weed</Text>
</View>
<View style={{ flexDirection: "row", alignItems: "center", gap: spacing.xs }}>
<View style={[s.colorDot, { backgroundColor: ZIP_COLOR }]} />
<Text style={{ fontSize: fontSize.sm, color: colors.textMuted }}>Zipette</Text>
</View>
<View style={{ flexDirection: "row", gap: spacing.m, paddingHorizontal: spacing.l, paddingBottom: spacing.m, flexWrap: "wrap" }}>
{settings.points_separated ? (
<>
<View style={{ flexDirection: "row", alignItems: "center", gap: spacing.xs }}>
<View style={[s.colorDot, { backgroundColor: WEED_COLOR }]} />
<Text style={{ fontSize: fontSize.sm, color: colors.textMuted }}>Weed</Text>
</View>
<View style={{ flexDirection: "row", alignItems: "center", gap: spacing.xs }}>
<View style={[s.colorDot, { backgroundColor: ZIP_COLOR }]} />
<Text style={{ fontSize: fontSize.sm, color: colors.textMuted }}>Zipette</Text>
</View>
</>
) : (
<View style={{ flexDirection: "row", alignItems: "center", gap: spacing.xs }}>
<View style={[s.colorDot, { backgroundColor: TOTAL_COLOR }]} />
<Text style={{ fontSize: fontSize.sm, color: colors.textMuted }}>Total</Text>
</View>
)}
<View style={{ flexDirection: "row", alignItems: "center", gap: spacing.xs }}>
<View style={[s.colorDot, { backgroundColor: colors.border }]} />
<Text style={{ fontSize: fontSize.sm, color: colors.textMuted }}>Aucun</Text>
@@ -450,21 +483,24 @@ export default function SettingsScreen() {
/>
<Text style={s.catName}>{cat.name}</Text>
<View style={s.chips}>
{(["weed", "zipette", "none"] as PoolAssignment[]).map(
(p) => {
{availableChips.map((p) => {
const active = pool === p;
const chipColor =
p === "weed"
? WEED_COLOR
: p === "zipette"
? ZIP_COLOR
: colors.textMuted;
: p === "total"
? TOTAL_COLOR
: colors.textMuted;
const label =
p === "weed"
? "W"
: p === "zipette"
? "Z"
: "—";
: p === "total"
? "T"
: "—";
return (
<TouchableOpacity
key={p}
@@ -493,8 +529,7 @@ export default function SettingsScreen() {
</Text>
</TouchableOpacity>
);
},
)}
})}
</View>
</View>
);
@@ -507,23 +542,36 @@ export default function SettingsScreen() {
)}
</View>
{/* Barème de points */}
<TiersSection
title="Barème Weed / Hash"
tiers={settings.points_weed_tiers ?? []}
onChange={(tiers) => setSettings((p) => ({ ...p, points_weed_tiers: tiers }))}
colors={colors}
s={s}
accentColor={WEED_COLOR}
/>
<TiersSection
title="Barème Zipette"
tiers={settings.points_zipette_tiers ?? []}
onChange={(tiers) => setSettings((p) => ({ ...p, points_zipette_tiers: tiers }))}
colors={colors}
s={s}
accentColor={ZIP_COLOR}
/>
{/* Barème de points — conditionnel selon le mode */}
{settings.points_separated ? (
<>
<TiersSection
title="Barème Weed / Hash"
tiers={settings.points_weed_tiers ?? []}
onChange={(tiers) => setSettings((p) => ({ ...p, points_weed_tiers: tiers }))}
colors={colors}
s={s}
accentColor={WEED_COLOR}
/>
<TiersSection
title="Barème Zipette"
tiers={settings.points_zipette_tiers ?? []}
onChange={(tiers) => setSettings((p) => ({ ...p, points_zipette_tiers: tiers }))}
colors={colors}
s={s}
accentColor={ZIP_COLOR}
/>
</>
) : (
<TiersSection
title="Barème Total (W + Z)"
tiers={settings.points_total_tiers ?? []}
onChange={(tiers) => setSettings((p) => ({ ...p, points_total_tiers: tiers }))}
colors={colors}
s={s}
accentColor={TOTAL_COLOR}
/>
)}
<TouchableOpacity
style={s.saveButton}