feat: pharmacy hours status and open now filter
Run Tests on Branches / Detect Changes (push) Successful in 17s
Run Tests on Branches / Backend Tests (push) Successful in 2m44s
Run Tests on Branches / Frontend Tests (push) Successful in 1m59s
Run Tests on Branches / Frontend Mobile Tests (push) Has been skipped
Run Tests on Branches / Parapharmacy API Tests (push) Has been skipped
Run Tests on Branches / PIP Platform Tests (push) Has been skipped

- Add is_open_now and is_always_open helpers in backend
- Add backend endpoint enrichment with is_open and is_24h fields
- Add client-side getOpenStatus with 24h, opens-at, opens-tomorrow support
- Add open-now filter toggle in PublicView and SearchView
- Add pharmacy no-hours fallback display
- Add sticky pharmacy controls on scroll
- Add admin hours editor with 24h toggle
- Add translations (es/ca) for all hour-related strings
- Add backend tests for hours logic and pharmacy endpoint
- Remove unused backup test files
This commit is contained in:
Antoni Nuñez Romeu
2026-07-27 14:32:05 +02:00
parent d43cbfa44e
commit e3e7d2f60b
18 changed files with 678 additions and 73 deletions
+15 -3
View File
@@ -27,6 +27,7 @@ import { searchMedicines, getMedicineDetails, searchOTC } from './cima-service.j
import { runFarmaciaWebhookImport, DEFAULT_FARMACIAS_WEBHOOK, importPharmaciesFromRows } from './farmacias-webhook-import.js';
import { fetchPharmaciesExternal } from '../API/index.js';
import { validateProductionEnv } from './src/config/required-env.js';
import { isOpenNow, isAlwaysOpen } from './src/hours.js';
validateProductionEnv();
@@ -226,6 +227,17 @@ function serializeOpeningHours(value) {
return null;
}
function enrichPharmacy(row) {
let isOpen = null;
let is24h = false;
if (row.opening_hours) {
const status = isOpenNow(row.opening_hours);
isOpen = status ? status.isOpen : null;
is24h = isAlwaysOpen(row.opening_hours);
}
return { ...row, is_open: isOpen, is_24h: is24h };
}
// Initialize database tables
async function initDatabase() {
try {
@@ -658,7 +670,7 @@ app.get('/api/medicines/:medicineId/pharmacies', async (req, res) => {
`);
}
res.json(pharmacies);
res.json(pharmacies.map(enrichPharmacy));
} catch (error) {
console.error('Error fetching pharmacies:', error);
res.status(500).json({ error: 'Internal server error' });
@@ -823,7 +835,7 @@ app.get('/api/products/:source/:productId/pharmacies', async (req, res) => {
`);
}
res.json(pharmacies);
res.json(pharmacies.map(enrichPharmacy));
} catch (error) {
console.error('Error fetching pharmacies for product:', error);
res.status(500).json({ error: 'Internal server error' });
@@ -920,7 +932,7 @@ app.get('/api/pharmacies', async (req, res) => {
const pharmacies = await userDbAll(`
SELECT * FROM pharmacies ORDER BY name
`);
res.json(pharmacies);
res.json(pharmacies.map(enrichPharmacy));
} catch (error) {
console.error('Error fetching pharmacies:', error);
res.status(500).json({ error: 'Internal server error' });