124 lines
4.2 KiB
TypeScript
124 lines
4.2 KiB
TypeScript
import React, { useState, useEffect, useCallback, useMemo } from "react";
|
|
import { View, Text, StyleSheet, FlatList, RefreshControl } from "react-native";
|
|
import { Ionicons } from "@expo/vector-icons";
|
|
import { spacing, fontSize } from "../../theme";
|
|
import { useTheme } from "../../context/ThemeContext";
|
|
import { getAdminAlerts } from "../../api/api_admin";
|
|
import type { Alert as AlertType } from "../../api/types";
|
|
import LoadingSpinner from "../../components/ui/LoadingSpinner";
|
|
import Card from "../../components/ui/Card";
|
|
import Badge from "../../components/ui/Badge";
|
|
|
|
export default function AlertsScreen() {
|
|
const { colors } = useTheme();
|
|
const [alerts, setAlerts] = useState<AlertType[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [refreshing, setRefreshing] = useState(false);
|
|
|
|
const loadData = useCallback(async () => {
|
|
try {
|
|
const result = await getAdminAlerts();
|
|
setAlerts(result.alerts);
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
setLoading(false);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
loadData();
|
|
}, [loadData]);
|
|
const onRefresh = async () => {
|
|
setRefreshing(true);
|
|
await loadData();
|
|
setRefreshing(false);
|
|
};
|
|
|
|
const styles = useMemo(
|
|
() =>
|
|
StyleSheet.create({
|
|
container: { flex: 1, backgroundColor: colors.bgPrimary },
|
|
row: { flexDirection: "row", alignItems: "center" },
|
|
username: {
|
|
color: colors.textWhite,
|
|
fontSize: fontSize.md,
|
|
fontWeight: "600",
|
|
},
|
|
alertMessage: {
|
|
color: colors.danger,
|
|
fontSize: fontSize.sm,
|
|
fontWeight: "600",
|
|
marginTop: 2,
|
|
},
|
|
date: {
|
|
color: colors.textMuted,
|
|
fontSize: fontSize.xs,
|
|
marginTop: 2,
|
|
},
|
|
empty: {
|
|
color: colors.textMuted,
|
|
textAlign: "center",
|
|
marginTop: spacing.xxl,
|
|
fontSize: fontSize.md,
|
|
},
|
|
}),
|
|
[colors],
|
|
);
|
|
|
|
const renderAlert = ({ item }: { item: AlertType }) => (
|
|
<Card style={{ marginBottom: spacing.m }}>
|
|
<View style={styles.row}>
|
|
<Ionicons
|
|
name="alert-circle"
|
|
size={24}
|
|
color={
|
|
item.status === "true"
|
|
? colors.danger
|
|
: colors.textMuted
|
|
}
|
|
/>
|
|
<View style={{ flex: 1, marginLeft: spacing.m }}>
|
|
<Text style={styles.username}>
|
|
Livreur: {item.username}
|
|
</Text>
|
|
{item.message ? (
|
|
<Text style={styles.alertMessage}>{item.message}</Text>
|
|
) : null}
|
|
<Text style={styles.date}>
|
|
{new Date(item.created_at).toLocaleString("fr-FR")}
|
|
</Text>
|
|
</View>
|
|
<Badge
|
|
label={item.status === "true" ? "Active" : "Terminée"}
|
|
color={
|
|
item.status === "true" ? colors.danger : colors.success
|
|
}
|
|
/>
|
|
</View>
|
|
</Card>
|
|
);
|
|
|
|
if (loading) return <LoadingSpinner message="Chargement alertes..." />;
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
<FlatList
|
|
data={alerts}
|
|
keyExtractor={(item) => item.id.toString()}
|
|
renderItem={renderAlert}
|
|
refreshControl={
|
|
<RefreshControl
|
|
refreshing={refreshing}
|
|
onRefresh={onRefresh}
|
|
tintColor={colors.accent}
|
|
/>
|
|
}
|
|
contentContainerStyle={{ padding: spacing.l }}
|
|
ListEmptyComponent={
|
|
<Text style={styles.empty}>Aucune alerte</Text>
|
|
}
|
|
/>
|
|
</View>
|
|
);
|
|
}
|