7.8 KiB
💊 FarmaFinder
A web application to search for medicines from the official Spanish CIMA database and find which pharmacies sell them.
✨ Features
- 🔍 Real-time medicine search from CIMA API (Agencia Española de Medicamentos)
- 💾 Redis caching for improved performance
- 📍 View pharmacies that sell a specific medicine
- 💰 See prices and stock availability
- 📱 Responsive design for mobile and desktop
- ⚙️ Admin Panel - Manage pharmacies and link medicines
- 🔐 Secure authentication - Login required to access admin features
- Add, edit, and delete pharmacies
- Search medicines from CIMA database
- Link medicines to pharmacies with prices and stock
🛠️ Tech Stack
- Frontend: React + Vite
- Backend: Node.js + Express
- Database: SQLite (for pharmacies and relationships)
- Cache: Redis
- External API: CIMA (Centro de Información online de Medicamentos de la AEMPS)
📋 Prerequisites
- Node.js (v18 or higher)
- npm or yarn
- Redis server (v6.0 or higher)
🚀 Setup Instructions
1. Install Redis
On Ubuntu/Debian:
sudo apt-get update
sudo apt-get install redis-server
sudo systemctl start redis-server
sudo systemctl enable redis-server
On macOS (using Homebrew):
brew install redis
brew services start redis
On Windows: Download and install from: https://redis.io/download
Using Docker:
docker run -d -p 6379:6379 redis:alpine
Verify Redis is running:
redis-cli ping
# Should respond with: PONG
2. Install Application Dependencies
Install backend dependencies:
cd backend
npm install
Install frontend dependencies:
cd ../frontend
npm install
3. Configure Environment (Optional)
Create a .env file in the backend directory if you need custom Redis settings:
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
SESSION_SECRET=your-secret-key-here
4. Initialize Database
Seed the database with sample pharmacies:
cd backend
npm run seed
Create admin user:
npm run create-admin
This creates a default admin user with:
- Username:
admin - Password:
admin123
⚠️ Important: Change the default password after first login!
You can customize credentials using environment variables:
ADMIN_USERNAME=myadmin ADMIN_PASSWORD=mypassword npm run create-admin
5. Running the Application
Start Redis (if not running):
redis-server
Start the backend server:
cd backend
npm start
The backend will run on http://localhost:3001
Start the frontend development server:
cd frontend
npm run dev
The frontend will run on http://localhost:3000
Open your browser and navigate to http://localhost:3000
🎯 How to Use
Public Search
- Type the name of a medicine in the search bar
- The app will search the CIMA database in real-time
- Click on a medicine to see which pharmacies have it
- View prices and stock availability
Admin Panel
- Click the "⚙️ Admin Panel" button
- Login with your credentials (default:
admin/admin123) - Pharmacies Tab: Add, edit, or delete pharmacies
- Medicines Tab: Search medicines from the CIMA database
- Link Medicine Tab: Associate medicines with pharmacies and set prices/stock
📁 Project Structure
FarmaFinder/
├── backend/
│ ├── server.js # Express server and API routes
│ ├── cima-service.js # CIMA API integration with Redis cache
│ ├── redis-client.js # Redis connection configuration
│ ├── seed.js # Database seeding script
│ ├── create-admin.js # Admin user creation script
│ ├── database.sqlite # SQLite database (created after first run)
│ └── package.json
├── frontend/
│ ├── src/
│ │ ├── components/ # React components
│ │ │ ├── admin/ # Admin panel components
│ │ │ └── ... # Public view components
│ │ ├── views/ # View components (Public/Admin)
│ │ ├── App.jsx # Main app component
│ │ └── main.jsx # Entry point
│ ├── index.html
│ └── package.json
└── README.md
🔌 API Endpoints
Public API
GET /api/medicines/search?q=<query>- Search medicines from CIMA API (cached in Redis)GET /api/medicines/:nregistro- Get medicine details from CIMAGET /api/medicines/:nregistro/pharmacies- Get pharmacies selling a medicineGET /api/pharmacies- Get all pharmacies
Authentication API
POST /api/auth/login- Login (requires username and password)POST /api/auth/logout- LogoutGET /api/auth/check- Check authentication status
Admin API (All require authentication)
POST /api/admin/pharmacies- Add a new pharmacyPUT /api/admin/pharmacies/:id- Update a pharmacyDELETE /api/admin/pharmacies/:id- Delete a pharmacyGET /api/admin/medicines?q=<query>- Search medicines from CIMA (for admin)GET /api/admin/pharmacies/:id/medicines- Get medicines linked to a pharmacyPOST /api/admin/pharmacy-medicines- Link medicine to pharmacyPUT /api/admin/pharmacy-medicines/:id- Update price/stockDELETE /api/admin/pharmacy-medicines/:id- Remove medicine from pharmacy
💾 Database Schema
SQLite Tables
pharmacies
id: Integer (Primary Key)name: Text (Pharmacy name)address: Text (Full address)phone: Text (Contact phone)latitude: Real (GPS coordinate)longitude: Real (GPS coordinate)
pharmacy_medicines
id: Integer (Primary Key)pharmacy_id: Integer (Foreign Key → pharmacies.id)medicine_nregistro: Text (CIMA medicine registration number)medicine_name: Text (Cached medicine name)price: Real (Price in EUR)stock: Integer (Available units)
users
id: Integer (Primary Key)username: Text (Unique)password_hash: Text (Bcrypt hashed)created_at: DateTime
Redis Cache Structure
medicines:search:{query}- Search results (TTL: 1 hour)medicine:{nregistro}- Medicine details (TTL: 24 hours)
🔧 Architecture Changes
Migration from Local Database to CIMA API
The application now uses the CIMA (Centro de Información online de Medicamentos) API as the source of truth for medicine data, with Redis caching for performance:
Benefits:
- ✅ Always up-to-date medicine information
- ✅ Official data from Spanish health authorities
- ✅ Reduced database maintenance
- ✅ Fast responses thanks to Redis cache
- ✅ Fallback to stale cache if API is down
Changes:
- Medicines are no longer stored locally in SQLite
- Medicine searches query the CIMA API
- Results are cached in Redis for performance
pharmacy_medicinesnow usesmedicine_nregistro(CIMA registration number) instead of localmedicine_id
🐛 Troubleshooting
Redis Connection Issues
If you see "Redis Client Error":
# Check if Redis is running
redis-cli ping
# Start Redis if needed
redis-server
CIMA API Timeout
If medicine searches are slow or failing:
- Check your internet connection
- The CIMA API may be temporarily unavailable
- The app will use cached data if available
Database Issues
Reset the database:
cd backend
rm database.sqlite
npm run seed
npm run create-admin
📝 Development
Backend development with auto-reload:
cd backend
npm run dev
Frontend development:
cd frontend
npm run dev
Clear Redis cache:
redis-cli FLUSHALL
🌐 External Resources
- CIMA API: https://cima.aemps.es/
- Redis Documentation: https://redis.io/documentation
- React Documentation: https://react.dev
- Express Documentation: https://expressjs.com
📄 License
ISC