chore: fix
This commit is contained in:
@@ -663,10 +663,15 @@ export const deleteCategoryAdmin = async (
|
||||
|
||||
export interface AppSettings {
|
||||
penalties_enabled: boolean;
|
||||
show_amende_score: boolean;
|
||||
points_enabled: boolean;
|
||||
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;
|
||||
}
|
||||
|
||||
export const getSettings = async (): Promise<{ success: boolean; settings?: AppSettings; error?: string }> => {
|
||||
|
||||
@@ -346,7 +346,9 @@ export const getAllAlerts = async (): Promise<{
|
||||
|
||||
export interface PublicSettings {
|
||||
penalties_enabled: boolean;
|
||||
show_amende_score: boolean;
|
||||
points_enabled: boolean;
|
||||
points_separated: boolean;
|
||||
}
|
||||
|
||||
export const getPublicSettings = async (): Promise<PublicSettings> => {
|
||||
@@ -354,9 +356,11 @@ export const getPublicSettings = async (): Promise<PublicSettings> => {
|
||||
const { data } = await apiClient.get(`http://5.181.0.112/api/v1/app-settings`);
|
||||
return {
|
||||
penalties_enabled: data.penalties_enabled ?? true,
|
||||
show_amende_score: data.show_amende_score ?? true,
|
||||
points_enabled: data.points_enabled ?? true,
|
||||
points_separated: data.points_separated ?? true,
|
||||
};
|
||||
} catch {
|
||||
return { penalties_enabled: true, points_enabled: true };
|
||||
return { penalties_enabled: true, show_amende_score: true, points_enabled: true, points_separated: true };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
Switch,
|
||||
TouchableOpacity,
|
||||
ActivityIndicator,
|
||||
TextInput,
|
||||
} from "react-native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { spacing, fontSize, borderRadius } from "../../theme";
|
||||
@@ -26,10 +27,15 @@ export default function SettingsScreen() {
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [settings, setSettings] = useState<AppSettings>({
|
||||
penalties_enabled: true,
|
||||
show_amende_score: true,
|
||||
points_enabled: true,
|
||||
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,
|
||||
});
|
||||
const [categories, setCategories] = useState<Category[]>([]);
|
||||
|
||||
@@ -142,6 +148,31 @@ export default function SettingsScreen() {
|
||||
paddingHorizontal: spacing.l,
|
||||
paddingBottom: spacing.m,
|
||||
},
|
||||
thresholdRow: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
paddingHorizontal: spacing.l,
|
||||
paddingVertical: spacing.m,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: colors.border,
|
||||
gap: spacing.m,
|
||||
},
|
||||
thresholdLabel: { flex: 1, fontSize: fontSize.md, color: colors.textPrimary, fontWeight: "600" },
|
||||
thresholdDesc: { fontSize: fontSize.sm, color: colors.textMuted, marginTop: 2 },
|
||||
thresholdInputs: { flexDirection: "row", alignItems: "center", gap: spacing.s },
|
||||
thresholdInput: {
|
||||
backgroundColor: colors.bgPrimary,
|
||||
borderWidth: 1,
|
||||
borderColor: colors.border,
|
||||
borderRadius: borderRadius.sm,
|
||||
paddingHorizontal: spacing.s,
|
||||
paddingVertical: 6,
|
||||
color: colors.textPrimary,
|
||||
fontSize: fontSize.md,
|
||||
width: 64,
|
||||
textAlign: "center",
|
||||
},
|
||||
thresholdSep: { fontSize: fontSize.md, color: colors.textMuted },
|
||||
saveButton: {
|
||||
backgroundColor: colors.accent,
|
||||
borderRadius: borderRadius.lg,
|
||||
@@ -188,6 +219,22 @@ export default function SettingsScreen() {
|
||||
thumbColor="#fff"
|
||||
/>
|
||||
</View>
|
||||
<View style={s.row}>
|
||||
<View style={s.rowLeft}>
|
||||
<Text style={s.rowLabel}>Afficher le score d'amendes</Text>
|
||||
<Text style={s.rowDesc}>
|
||||
Les clients et la cabine voient le nombre d'amendes
|
||||
</Text>
|
||||
</View>
|
||||
<Switch
|
||||
value={settings.show_amende_score}
|
||||
onValueChange={(v) =>
|
||||
setSettings((prev) => ({ ...prev, show_amende_score: v }))
|
||||
}
|
||||
trackColor={{ false: colors.border, true: colors.accent }}
|
||||
thumbColor="#fff"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Système de points */}
|
||||
@@ -324,6 +371,79 @@ export default function SettingsScreen() {
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* Barème de points */}
|
||||
<View style={s.section}>
|
||||
<Text style={s.sectionTitle}>Barème de points</Text>
|
||||
<Text style={s.hint}>
|
||||
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...
|
||||
</Text>
|
||||
|
||||
{/* Weed */}
|
||||
<View style={[s.thresholdRow, { borderTopWidth: 0 }]}>
|
||||
<View style={{ flex: 1 }}>
|
||||
<Text style={s.thresholdLabel}>Pool Weed / Hash</Text>
|
||||
<Text style={s.thresholdDesc}>Prix seuil → points gagnés</Text>
|
||||
</View>
|
||||
<View style={s.thresholdInputs}>
|
||||
<TextInput
|
||||
style={s.thresholdInput}
|
||||
keyboardType="decimal-pad"
|
||||
value={String(settings.points_weed_threshold_price)}
|
||||
onChangeText={(v) => {
|
||||
const n = parseFloat(v);
|
||||
if (!isNaN(n) && n > 0)
|
||||
setSettings((p) => ({ ...p, points_weed_threshold_price: n }));
|
||||
}}
|
||||
/>
|
||||
<Text style={s.thresholdSep}>€ =</Text>
|
||||
<TextInput
|
||||
style={s.thresholdInput}
|
||||
keyboardType="number-pad"
|
||||
value={String(settings.points_weed_per_threshold)}
|
||||
onChangeText={(v) => {
|
||||
const n = parseInt(v, 10);
|
||||
if (!isNaN(n) && n >= 0)
|
||||
setSettings((p) => ({ ...p, points_weed_per_threshold: n }));
|
||||
}}
|
||||
/>
|
||||
<Text style={s.thresholdSep}>pts</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Zipette */}
|
||||
<View style={s.thresholdRow}>
|
||||
<View style={{ flex: 1 }}>
|
||||
<Text style={s.thresholdLabel}>Pool Zipette</Text>
|
||||
<Text style={s.thresholdDesc}>Prix seuil → points gagnés</Text>
|
||||
</View>
|
||||
<View style={s.thresholdInputs}>
|
||||
<TextInput
|
||||
style={s.thresholdInput}
|
||||
keyboardType="decimal-pad"
|
||||
value={String(settings.points_zipette_threshold_price)}
|
||||
onChangeText={(v) => {
|
||||
const n = parseFloat(v);
|
||||
if (!isNaN(n) && n > 0)
|
||||
setSettings((p) => ({ ...p, points_zipette_threshold_price: n }));
|
||||
}}
|
||||
/>
|
||||
<Text style={s.thresholdSep}>€ =</Text>
|
||||
<TextInput
|
||||
style={s.thresholdInput}
|
||||
keyboardType="number-pad"
|
||||
value={String(settings.points_zipette_per_threshold)}
|
||||
onChangeText={(v) => {
|
||||
const n = parseInt(v, 10);
|
||||
if (!isNaN(n) && n >= 0)
|
||||
setSettings((p) => ({ ...p, points_zipette_per_threshold: n }));
|
||||
}}
|
||||
/>
|
||||
<Text style={s.thresholdSep}>pts</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<TouchableOpacity
|
||||
style={s.saveButton}
|
||||
onPress={handleSave}
|
||||
|
||||
@@ -19,7 +19,9 @@ export default function UsersScreen() {
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [appSettings, setAppSettings] = useState<PublicSettings>({
|
||||
penalties_enabled: true,
|
||||
show_amende_score: true,
|
||||
points_enabled: true,
|
||||
points_separated: true,
|
||||
});
|
||||
const [penaltyModal, setPenaltyModal] = useState<{
|
||||
visible: boolean;
|
||||
@@ -145,22 +147,31 @@ export default function UsersScreen() {
|
||||
</Text>
|
||||
<View style={styles.statsRow}>
|
||||
{appSettings.points_enabled && (
|
||||
<>
|
||||
appSettings.points_separated ? (
|
||||
<>
|
||||
<View style={styles.stat}>
|
||||
<Text style={[styles.statValue, { color: colors.success }]}>
|
||||
{item.point}
|
||||
</Text>
|
||||
<Text style={styles.statLabel}>Points</Text>
|
||||
</View>
|
||||
<View style={styles.stat}>
|
||||
<Text style={[styles.statValue, { color: colors.info }]}>
|
||||
{item.points_zipette}
|
||||
</Text>
|
||||
<Text style={styles.statLabel}>Zipette</Text>
|
||||
</View>
|
||||
</>
|
||||
) : (
|
||||
<View style={styles.stat}>
|
||||
<Text style={[styles.statValue, { color: colors.success }]}>
|
||||
{item.point}
|
||||
</Text>
|
||||
<Text style={styles.statLabel}>Points</Text>
|
||||
</View>
|
||||
<View style={styles.stat}>
|
||||
<Text style={[styles.statValue, { color: colors.info }]}>
|
||||
{item.points_zipette}
|
||||
</Text>
|
||||
<Text style={styles.statLabel}>Zipette</Text>
|
||||
</View>
|
||||
</>
|
||||
)
|
||||
)}
|
||||
{appSettings.penalties_enabled && (
|
||||
{appSettings.show_amende_score && (
|
||||
<View style={styles.stat}>
|
||||
<Text style={[styles.statValue, { color: colors.warning }]}>
|
||||
{item.amende}
|
||||
|
||||
Reference in New Issue
Block a user