import React, { useEffect, useState } from 'react'; import { View, Text, StyleSheet, FlatList, TouchableOpacity, Alert, useWindowDimensions } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { useThemeContext } from '../../components/ThemeProvider'; import { spacing, borderRadius, shadows } from '../../constants/theme'; import { LoadingSpinner } from '../../components/LoadingSpinner'; import api from '../../services/api'; const TABLET_MIN_WIDTH = 768; interface NotificationItem { scope: string; id: number; medicine_name?: string; medicine_nregistro?: string; pharmacy_name?: string; pharmacy_id?: number; pharmacy_address?: string; created_at?: string; } export default function AlertsScreen() { const { width } = useWindowDimensions(); const isTablet = width >= TABLET_MIN_WIDTH; const { colors } = useThemeContext(); const [items, setItems] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const [deletingId, setDeletingId] = useState(null); useEffect(() => { loadNotifications(); }, []); async function loadNotifications() { setIsLoading(true); setError(null); try { const res = await api.get('/notifications/mine'); const data = res.data; const merged = [ ...(data.pharmacy || []), ...(data.global || []), ].sort((a: NotificationItem, b: NotificationItem) => (b.created_at || '').localeCompare(a.created_at || '') ); setItems(merged); } catch (err: any) { setError(err.message || 'No se pudieron cargar las notificaciones'); } finally { setIsLoading(false); } } async function handleDelete(item: NotificationItem) { const key = `${item.scope}:${item.id}`; Alert.alert( 'Eliminar notificación', `¿Eliminar la notificación de ${item.medicine_name || item.medicine_nregistro}?`, [ { text: 'Cancelar', style: 'cancel' }, { text: 'Eliminar', style: 'destructive', onPress: async () => { setDeletingId(key); try { await api.delete('/notifications/mine', { data: { scope: item.scope, id: item.id }, }); setItems(prev => prev.filter(i => !(i.scope === item.scope && i.id === item.id))); } catch (err: any) { Alert.alert('Error', err.message || 'No se pudo eliminar'); } finally { setDeletingId(null); } }, }, ] ); } function renderItem({ item }: { item: NotificationItem }) { const key = `${item.scope}:${item.id}`; return ( {item.medicine_name || item.medicine_nregistro} {item.scope === 'pharmacy' ? item.pharmacy_name || `Farmacia #${item.pharmacy_id}` : 'Cualquier farmacia'} {item.pharmacy_address && ( {item.pharmacy_address} )} handleDelete(item)} disabled={deletingId === key} > {deletingId === key ? ( ) : ( )} ); } if (isLoading) { return ; } return ( Notificaciones Guardadas Recibe avisos cuando medicamentos sin stock se repongan {error && ( {error} Reintentar )} {!error && items.length === 0 && ( Sin notificaciones Toca la campana en una farmacia sin stock para recibir notificaciones cuando se reponga. )} {!error && items.length > 0 && ( `${item.scope}:${item.id}`} renderItem={renderItem} contentContainerStyle={[styles.list, isTablet && styles.listTablet]} showsVerticalScrollIndicator={false} /> )} ); } const styles = StyleSheet.create({ container: { flex: 1, }, header: { paddingHorizontal: spacing.lg, paddingTop: spacing.lg, paddingBottom: spacing.md, }, headerTablet: { maxWidth: 700, alignSelf: 'center', width: '100%', }, title: { fontSize: 22, fontWeight: 'bold', }, titleTablet: { fontSize: 28, }, subtitle: { fontSize: 14, marginTop: spacing.xs, lineHeight: 20, }, subtitleTablet: { fontSize: 16, lineHeight: 24, }, list: { paddingHorizontal: spacing.lg, paddingBottom: spacing.xl, gap: spacing.sm, }, listTablet: { maxWidth: 700, alignSelf: 'center', width: '100%', }, item: { flexDirection: 'row', alignItems: 'center', borderRadius: borderRadius.lg, padding: spacing.md, ...shadows.card, }, itemContent: { flex: 1, gap: spacing.xs, }, itemName: { fontSize: 16, fontWeight: '600', lineHeight: 22, }, itemMeta: { gap: spacing.xs, }, chip: { flexDirection: 'row', alignItems: 'center', gap: spacing.xs, borderRadius: borderRadius.full, paddingHorizontal: spacing.sm, paddingVertical: 3, alignSelf: 'flex-start', }, chipText: { fontSize: 12, fontWeight: '600', }, itemAddress: { fontSize: 12, }, deleteButton: { width: 36, height: 36, borderRadius: 18, alignItems: 'center', justifyContent: 'center', marginLeft: spacing.sm, }, errorContainer: { margin: spacing.lg, padding: spacing.md, borderRadius: borderRadius.lg, alignItems: 'center', gap: spacing.sm, }, errorContainerTablet: { maxWidth: 700, alignSelf: 'center', }, errorText: { fontSize: 14, textAlign: 'center', }, retryButton: { paddingHorizontal: spacing.md, paddingVertical: spacing.xs, }, retryText: { fontSize: 14, fontWeight: '600', }, emptyContainer: { flex: 1, alignItems: 'center', justifyContent: 'center', paddingHorizontal: spacing.xl, gap: spacing.md, }, emptyTitle: { fontSize: 18, fontWeight: '600', }, emptyTitleTablet: { fontSize: 24, }, emptyText: { fontSize: 14, textAlign: 'center', lineHeight: 20, }, emptyTextTablet: { fontSize: 16, maxWidth: 400, lineHeight: 24, }, });