diff --git a/apps/backend/package.json b/apps/backend/package.json
index 8a86a18..21a99e8 100644
--- a/apps/backend/package.json
+++ b/apps/backend/package.json
@@ -12,7 +12,7 @@
"migrate": "node migrate.js",
"reset-db": "bash reset-db.sh",
"import-farmacias": "node import-farmacias.js",
- "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --forceExit"
+ "test": "NODE_OPTIONS='--experimental-vm-modules' npx jest --forceExit"
},
"keywords": [],
"author": "",
diff --git a/apps/frontend/src/App.jsx b/apps/frontend/src/App.jsx
index 8ab6ec8..712f227 100644
--- a/apps/frontend/src/App.jsx
+++ b/apps/frontend/src/App.jsx
@@ -16,6 +16,7 @@ function App() {
const [authChecked, setAuthChecked] = useState(false);
const [showLogin, setShowLogin] = useState(false);
const [showSaved, setShowSaved] = useState(false);
+ const [badgeCount, setBadgeCount] = useState(0);
const [screenSize, setScreenSize] = useState({
width: window.innerWidth,
height: window.innerHeight
@@ -45,6 +46,31 @@ function App() {
return () => window.removeEventListener('resize', handleResize);
}, []);
+ useEffect(() => {
+ if (!currentUser) { setBadgeCount(0); return; }
+ let cancelled = false;
+ fetch('/api/notifications/mine', { credentials: 'include' })
+ .then(r => r.ok ? r.json() : null)
+ .then(data => {
+ if (cancelled || !data) return;
+ const count = (data.global?.length || 0) + (data.pharmacy?.length || 0);
+ setBadgeCount(count);
+ })
+ .catch(() => {});
+ return () => { cancelled = true; };
+ }, [currentUser]);
+
+ function refreshBadgeCount() {
+ if (!currentUser) return;
+ fetch('/api/notifications/mine', { credentials: 'include' })
+ .then(r => r.ok ? r.json() : null)
+ .then(data => {
+ if (!data) return;
+ setBadgeCount((data.global?.length || 0) + (data.pharmacy?.length || 0));
+ })
+ .catch(() => {});
+ }
+
function handleLogin(user) {
setCurrentUser(user);
setShowLogin(false);
@@ -98,7 +124,7 @@ function App() {
);
break;
case 'alerts':
- activeView = ;
+ activeView = ;
break;
case 'search':
activeView = (
@@ -143,7 +169,7 @@ function App() {
activeTab={screen}
onChange={handleNavChange}
isLoggedIn={Boolean(currentUser)}
- badgeCount={currentUser ? 2 : 0}
+ badgeCount={badgeCount}
/>
{showLogin && (
@@ -154,7 +180,7 @@ function App() {
)}
{showSaved && currentUser && (
- setShowSaved(false)} />
+ setShowSaved(false)} onNotificationChange={refreshBadgeCount} />
)}
);
diff --git a/apps/frontend/src/components/SavedNotifications.jsx b/apps/frontend/src/components/SavedNotifications.jsx
index ef1edca..9bd5882 100644
--- a/apps/frontend/src/components/SavedNotifications.jsx
+++ b/apps/frontend/src/components/SavedNotifications.jsx
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import './SavedNotifications.css';
-function SavedNotifications({ onClose }) {
+function SavedNotifications({ onClose, onNotificationChange }) {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [items, setItems] = useState([]);
@@ -41,6 +41,7 @@ function SavedNotifications({ onClose }) {
});
if (!res.ok && res.status !== 204) throw new Error(`HTTP ${res.status}`);
setItems(prev => prev.filter(i => !(i.scope === item.scope && i.id === item.id)));
+ onNotificationChange?.();
} catch (err) {
setError(err.message || 'No se pudo eliminar la notificación');
} finally {
diff --git a/apps/frontend/src/views/AlertsView.jsx b/apps/frontend/src/views/AlertsView.jsx
index ec4ad47..d1b0162 100644
--- a/apps/frontend/src/views/AlertsView.jsx
+++ b/apps/frontend/src/views/AlertsView.jsx
@@ -14,7 +14,7 @@ const iconMap = {
),
};
-function AlertsView() {
+function AlertsView({ onNotificationChange }) {
const [availability, setAvailability] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
@@ -63,6 +63,7 @@ function AlertsView() {
});
if (res.ok || res.status === 204) {
setAvailability(prev => prev.filter(i => !(i.scope === item.scope && i.id === item.id)));
+ onNotificationChange?.();
// Also update local storage if possible to reflect that we unsubscribed
try {