chore: add notification livreur

This commit is contained in:
2026-03-02 13:15:15 +01:00
parent 6c8af9acd4
commit d78a5743a1
7 changed files with 1063 additions and 1 deletions
@@ -48,6 +48,13 @@ import TomTomMap, {
TomTomMapRef,
TomTomMarker,
} from "../../components/TomTomMap";
import {
setupDeliveryNotificationChannel,
registerForPushNotificationsAsync,
sendPushTokenToBackend,
addNotificationReceivedListener,
} from "../../services/pushNotifications";
import { getLivreurNotifications } from "../../api/api_delivery";
const { width: SCREEN_WIDTH } = Dimensions.get("window");
const MAP_HEIGHT = 260;
@@ -99,6 +106,10 @@ export default function DashboardScreen() {
const pendingRouteAddress = useRef<string | null>(null);
const { alert, showError, showSuccess, hideAlert } = useAlert();
// Notifications
const [unreadNotifCount, setUnreadNotifCount] = useState(0);
const pushTokenRef = useRef<string | null>(null);
const STATUS_COLORS: Record<string, string> = useMemo(
() => ({
available: colors.success,
@@ -262,6 +273,38 @@ export default function DashboardScreen() {
loadData();
}, [loadData]);
// Push notifications: enregistrement + badge
useEffect(() => {
let notifSub: ReturnType<typeof addNotificationReceivedListener> | null = null;
const setupPush = async () => {
await setupDeliveryNotificationChannel();
const token = await registerForPushNotificationsAsync();
if (token) {
pushTokenRef.current = token;
await sendPushTokenToBackend(token);
}
// Charger le compteur de notifications non lues
const res = await getLivreurNotifications();
if (res.success) {
setUnreadNotifCount(res.unread_count ?? 0);
}
};
setupPush();
// Écouter les nouvelles notifications en foreground
notifSub = addNotificationReceivedListener((_notif) => {
setUnreadNotifCount((prev) => prev + 1);
loadData();
});
return () => {
if (notifSub) notifSub.remove();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// Quand GPS devient disponible, rejouer la route en attente
useEffect(() => {
if (lastCoords && pendingRouteAddress.current) {
@@ -1245,6 +1288,25 @@ export default function DashboardScreen() {
fontSize: fontSize.sm,
fontFamily: "monospace",
},
notifBadgeBar: {
flexDirection: "row",
alignItems: "center",
gap: 8,
backgroundColor: "#FF6B0015",
borderLeftWidth: 3,
borderLeftColor: "#FF6B00",
paddingHorizontal: spacing.m,
paddingVertical: 8,
marginHorizontal: spacing.l,
marginTop: spacing.s,
borderRadius: 6,
},
notifBadgeText: {
color: "#FF6B00",
fontSize: fontSize.sm,
fontWeight: "600",
flex: 1,
},
fullscreenStatusBadge: {
flexDirection: "row",
alignItems: "center",
@@ -1418,6 +1480,16 @@ export default function DashboardScreen() {
</View>
</Modal>
{/* ── Badge notifications ── */}
{unreadNotifCount > 0 && (
<View style={styles.notifBadgeBar}>
<Ionicons name="notifications" size={16} color="#FF6B00" />
<Text style={styles.notifBadgeText}>
{unreadNotifCount} nouvelle{unreadNotifCount > 1 ? "s" : ""} commande{unreadNotifCount > 1 ? "s" : ""} assignée{unreadNotifCount > 1 ? "s" : ""}
</Text>
</View>
)}
{/* ── Barre de statut ── */}
<View style={styles.statusBar}>
<Text style={styles.statusLabel}>Mon statut:</Text>