chore: update
This commit is contained in:
@@ -25,6 +25,7 @@ import OrdersScreen from "../screens/cabine/OrdersScreen";
|
|||||||
import DeliveryScreen from "../screens/cabine/DeliveryScreen";
|
import DeliveryScreen from "../screens/cabine/DeliveryScreen";
|
||||||
import UsersScreen from "../screens/cabine/UsersScreen";
|
import UsersScreen from "../screens/cabine/UsersScreen";
|
||||||
import AlertsScreen from "../screens/cabine/AlertsScreen";
|
import AlertsScreen from "../screens/cabine/AlertsScreen";
|
||||||
|
import AddressScreen from "../screens/cabine/AddressScreen";
|
||||||
|
|
||||||
const Tab = createBottomTabNavigator<CabineTabParamList>();
|
const Tab = createBottomTabNavigator<CabineTabParamList>();
|
||||||
|
|
||||||
@@ -42,7 +43,9 @@ export default function CabineNavigator() {
|
|||||||
const res = await getCabineNotifications();
|
const res = await getCabineNotifications();
|
||||||
setNotifications(res.notifications ?? []);
|
setNotifications(res.notifications ?? []);
|
||||||
setUnreadCount(res.unread_count ?? 0);
|
setUnreadCount(res.unread_count ?? 0);
|
||||||
} catch { /* ignore */ }
|
} catch {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -59,8 +62,12 @@ export default function CabineNavigator() {
|
|||||||
try {
|
try {
|
||||||
await markCabineNotificationsRead();
|
await markCabineNotificationsRead();
|
||||||
setUnreadCount(0);
|
setUnreadCount(0);
|
||||||
setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));
|
setNotifications((prev) =>
|
||||||
} catch { /* ignore */ }
|
prev.map((n) => ({ ...n, read: true })),
|
||||||
|
);
|
||||||
|
} catch {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -106,11 +113,16 @@ export default function CabineNavigator() {
|
|||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.badge,
|
styles.badge,
|
||||||
{ backgroundColor: colors.danger },
|
{
|
||||||
|
backgroundColor:
|
||||||
|
colors.danger,
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Text style={styles.badgeText}>
|
<Text style={styles.badgeText}>
|
||||||
{unreadCount > 9 ? "9+" : unreadCount}
|
{unreadCount > 9
|
||||||
|
? "9+"
|
||||||
|
: unreadCount}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
@@ -121,7 +133,11 @@ export default function CabineNavigator() {
|
|||||||
style={{ marginRight: spacing.m }}
|
style={{ marginRight: spacing.m }}
|
||||||
>
|
>
|
||||||
<Ionicons
|
<Ionicons
|
||||||
name={isDark ? "sunny-outline" : "moon-outline"}
|
name={
|
||||||
|
isDark
|
||||||
|
? "sunny-outline"
|
||||||
|
: "moon-outline"
|
||||||
|
}
|
||||||
size={22}
|
size={22}
|
||||||
color={colors.textSecondary}
|
color={colors.textSecondary}
|
||||||
/>
|
/>
|
||||||
@@ -151,7 +167,11 @@ export default function CabineNavigator() {
|
|||||||
options={{
|
options={{
|
||||||
title: "Dashboard",
|
title: "Dashboard",
|
||||||
tabBarIcon: ({ color, size }) => (
|
tabBarIcon: ({ color, size }) => (
|
||||||
<Ionicons name="grid-outline" size={size} color={color} />
|
<Ionicons
|
||||||
|
name="grid-outline"
|
||||||
|
size={size}
|
||||||
|
color={color}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -161,7 +181,11 @@ export default function CabineNavigator() {
|
|||||||
options={{
|
options={{
|
||||||
title: "Commandes",
|
title: "Commandes",
|
||||||
tabBarIcon: ({ color, size }) => (
|
tabBarIcon: ({ color, size }) => (
|
||||||
<Ionicons name="receipt-outline" size={size} color={color} />
|
<Ionicons
|
||||||
|
name="receipt-outline"
|
||||||
|
size={size}
|
||||||
|
color={color}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -171,7 +195,11 @@ export default function CabineNavigator() {
|
|||||||
options={{
|
options={{
|
||||||
title: "Livreurs",
|
title: "Livreurs",
|
||||||
tabBarIcon: ({ color, size }) => (
|
tabBarIcon: ({ color, size }) => (
|
||||||
<Ionicons name="bicycle-outline" size={size} color={color} />
|
<Ionicons
|
||||||
|
name="bicycle-outline"
|
||||||
|
size={size}
|
||||||
|
color={color}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -181,7 +209,11 @@ export default function CabineNavigator() {
|
|||||||
options={{
|
options={{
|
||||||
title: "Clients",
|
title: "Clients",
|
||||||
tabBarIcon: ({ color, size }) => (
|
tabBarIcon: ({ color, size }) => (
|
||||||
<Ionicons name="people-outline" size={size} color={color} />
|
<Ionicons
|
||||||
|
name="people-outline"
|
||||||
|
size={size}
|
||||||
|
color={color}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -191,7 +223,25 @@ export default function CabineNavigator() {
|
|||||||
options={{
|
options={{
|
||||||
title: "Alertes",
|
title: "Alertes",
|
||||||
tabBarIcon: ({ color, size }) => (
|
tabBarIcon: ({ color, size }) => (
|
||||||
<Ionicons name="alert-circle-outline" size={size} color={color} />
|
<Ionicons
|
||||||
|
name="alert-circle-outline"
|
||||||
|
size={size}
|
||||||
|
color={color}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tab.Screen
|
||||||
|
name="Adresses"
|
||||||
|
component={AddressScreen}
|
||||||
|
options={{
|
||||||
|
title: "Adresses",
|
||||||
|
tabBarIcon: ({ color, size }) => (
|
||||||
|
<Ionicons
|
||||||
|
name="map-outline"
|
||||||
|
size={size}
|
||||||
|
color={color}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -211,16 +261,32 @@ export default function CabineNavigator() {
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<View style={styles.modalHeader}>
|
<View style={styles.modalHeader}>
|
||||||
<Text style={[styles.modalTitle, { color: colors.textWhite }]}>
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.modalTitle,
|
||||||
|
{ color: colors.textWhite },
|
||||||
|
]}
|
||||||
|
>
|
||||||
Notifications
|
Notifications
|
||||||
</Text>
|
</Text>
|
||||||
<TouchableOpacity onPress={() => setModalVisible(false)}>
|
<TouchableOpacity
|
||||||
<Ionicons name="close" size={24} color={colors.textSecondary} />
|
onPress={() => setModalVisible(false)}
|
||||||
|
>
|
||||||
|
<Ionicons
|
||||||
|
name="close"
|
||||||
|
size={24}
|
||||||
|
color={colors.textSecondary}
|
||||||
|
/>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<ScrollView style={styles.notifList}>
|
<ScrollView style={styles.notifList}>
|
||||||
{notifications.length === 0 ? (
|
{notifications.length === 0 ? (
|
||||||
<Text style={[styles.emptyText, { color: colors.textMuted }]}>
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.emptyText,
|
||||||
|
{ color: colors.textMuted },
|
||||||
|
]}
|
||||||
|
>
|
||||||
Aucune notification
|
Aucune notification
|
||||||
</Text>
|
</Text>
|
||||||
) : (
|
) : (
|
||||||
@@ -235,7 +301,8 @@ export default function CabineNavigator() {
|
|||||||
: colors.info,
|
: colors.info,
|
||||||
backgroundColor: n.read
|
backgroundColor: n.read
|
||||||
? "transparent"
|
? "transparent"
|
||||||
: colors.bgPrimary ?? colors.bgSecondary,
|
: (colors.bgPrimary ??
|
||||||
|
colors.bgSecondary),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
@@ -248,7 +315,10 @@ export default function CabineNavigator() {
|
|||||||
{n.message}
|
{n.message}
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
style={[styles.notifTime, { color: colors.textMuted }]}
|
style={[
|
||||||
|
styles.notifTime,
|
||||||
|
{ color: colors.textMuted },
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
{formatTime(n.created_at)}
|
{formatTime(n.created_at)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
@@ -1,37 +1,38 @@
|
|||||||
export type AuthStackParamList = {
|
export type AuthStackParamList = {
|
||||||
RoleSelect: undefined;
|
RoleSelect: undefined;
|
||||||
AdminLogin: undefined;
|
AdminLogin: undefined;
|
||||||
CabineLogin: undefined;
|
CabineLogin: undefined;
|
||||||
DeliveryLogin: undefined;
|
DeliveryLogin: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AdminTabParamList = {
|
export type AdminTabParamList = {
|
||||||
Dashboard: undefined;
|
Dashboard: undefined;
|
||||||
Orders: undefined;
|
Orders: undefined;
|
||||||
Users: undefined;
|
Users: undefined;
|
||||||
Products: undefined;
|
Products: undefined;
|
||||||
Categories: undefined;
|
Categories: undefined;
|
||||||
Delivery: undefined;
|
Delivery: undefined;
|
||||||
Alerts: undefined;
|
Alerts: undefined;
|
||||||
Addresses: undefined;
|
Addresses: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AdminStackParamList = {
|
export type AdminStackParamList = {
|
||||||
AdminTabs: undefined;
|
AdminTabs: undefined;
|
||||||
OrderDetail: { orderId: number };
|
OrderDetail: { orderId: number };
|
||||||
Settings: undefined;
|
Settings: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CabineTabParamList = {
|
export type CabineTabParamList = {
|
||||||
Dashboard: undefined;
|
Dashboard: undefined;
|
||||||
Orders: undefined;
|
Orders: undefined;
|
||||||
Delivery: undefined;
|
Delivery: undefined;
|
||||||
Users: undefined;
|
Users: undefined;
|
||||||
Alerts: undefined;
|
Alerts: undefined;
|
||||||
|
Adresses: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DeliveryTabParamList = {
|
export type DeliveryTabParamList = {
|
||||||
Dashboard: undefined;
|
Dashboard: undefined;
|
||||||
Stats: undefined;
|
Stats: undefined;
|
||||||
Alerts: undefined;
|
Alerts: undefined;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -319,15 +319,10 @@ export default function SettingsScreen() {
|
|||||||
const ZIP_COLOR = "#9333ea";
|
const ZIP_COLOR = "#9333ea";
|
||||||
const TOTAL_COLOR = "#f97316";
|
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
|
// Chips disponibles selon le mode
|
||||||
const availableChips: PoolAssignment[] = settings.points_separated
|
const availableChips: PoolAssignment[] = settings.points_separated
|
||||||
? ["weed", "zipette", "none"] // mode séparé : T désactivé
|
? ["weed", "zipette", "none"] // mode séparé : T désactivé
|
||||||
: ["total", "none"]; // mode non-séparé : W/Z désactivés
|
: ["total", "none"]; // mode non-séparé : W/Z désactivés
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={s.container}>
|
<View style={s.container}>
|
||||||
@@ -411,20 +406,16 @@ export default function SettingsScreen() {
|
|||||||
thumbColor="#fff"
|
thumbColor="#fff"
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={[s.row, { opacity: hasBothPools ? 1 : 0.4 }]}>
|
<View style={s.row}>
|
||||||
<View style={s.rowLeft}>
|
<View style={s.rowLeft}>
|
||||||
<Text style={s.rowLabel}>Points séparés par pool</Text>
|
<Text style={s.rowLabel}>Points séparés par pool</Text>
|
||||||
<Text style={s.rowDesc}>
|
<Text style={s.rowDesc}>
|
||||||
Activé : Weed → point / Zipette → point_zipette{"\n"}
|
Activé : barèmes Weed + Zipette utilisés séparément{"\n"}
|
||||||
Désactivé : Barème Total sur la somme W+Z{"\n"}
|
Désactivé : barème Total utilisé (catégorie T)
|
||||||
{!hasBothPools && (
|
|
||||||
"⚠️ Nécessite des catégories W ET Z configurées"
|
|
||||||
)}
|
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<Switch
|
<Switch
|
||||||
value={settings.points_separated}
|
value={settings.points_separated}
|
||||||
disabled={!hasBothPools}
|
|
||||||
onValueChange={(v) =>
|
onValueChange={(v) =>
|
||||||
setSettings((prev) => ({ ...prev, points_separated: v }))
|
setSettings((prev) => ({ ...prev, points_separated: v }))
|
||||||
}
|
}
|
||||||
@@ -542,36 +533,31 @@ export default function SettingsScreen() {
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Barème de points — conditionnel selon le mode */}
|
{/* Barèmes de points — toujours présents */}
|
||||||
{settings.points_separated ? (
|
<TiersSection
|
||||||
<>
|
title="Barème Weed / Hash"
|
||||||
<TiersSection
|
tiers={settings.points_weed_tiers ?? []}
|
||||||
title="Barème Weed / Hash"
|
onChange={(tiers) => setSettings((p) => ({ ...p, points_weed_tiers: tiers }))}
|
||||||
tiers={settings.points_weed_tiers ?? []}
|
colors={colors}
|
||||||
onChange={(tiers) => setSettings((p) => ({ ...p, points_weed_tiers: tiers }))}
|
s={s}
|
||||||
colors={colors}
|
accentColor={WEED_COLOR}
|
||||||
s={s}
|
/>
|
||||||
accentColor={WEED_COLOR}
|
<TiersSection
|
||||||
/>
|
title="Barème Zipette"
|
||||||
<TiersSection
|
tiers={settings.points_zipette_tiers ?? []}
|
||||||
title="Barème Zipette"
|
onChange={(tiers) => setSettings((p) => ({ ...p, points_zipette_tiers: tiers }))}
|
||||||
tiers={settings.points_zipette_tiers ?? []}
|
colors={colors}
|
||||||
onChange={(tiers) => setSettings((p) => ({ ...p, points_zipette_tiers: tiers }))}
|
s={s}
|
||||||
colors={colors}
|
accentColor={ZIP_COLOR}
|
||||||
s={s}
|
/>
|
||||||
accentColor={ZIP_COLOR}
|
<TiersSection
|
||||||
/>
|
title="Barème Total"
|
||||||
</>
|
tiers={settings.points_total_tiers ?? []}
|
||||||
) : (
|
onChange={(tiers) => setSettings((p) => ({ ...p, points_total_tiers: tiers }))}
|
||||||
<TiersSection
|
colors={colors}
|
||||||
title="Barème Total (W + Z)"
|
s={s}
|
||||||
tiers={settings.points_total_tiers ?? []}
|
accentColor={TOTAL_COLOR}
|
||||||
onChange={(tiers) => setSettings((p) => ({ ...p, points_total_tiers: tiers }))}
|
/>
|
||||||
colors={colors}
|
|
||||||
s={s}
|
|
||||||
accentColor={TOTAL_COLOR}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={s.saveButton}
|
style={s.saveButton}
|
||||||
|
|||||||
Reference in New Issue
Block a user