Files
FarmaFinder/README.md
2026-04-01 01:17:33 +02:00

308 lines
7.8 KiB
Markdown

# 💊 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:**
```bash
sudo apt-get update
sudo apt-get install redis-server
sudo systemctl start redis-server
sudo systemctl enable redis-server
```
**On macOS (using Homebrew):**
```bash
brew install redis
brew services start redis
```
**On Windows:**
Download and install from: https://redis.io/download
**Using Docker:**
```bash
docker run -d -p 6379:6379 redis:alpine
```
Verify Redis is running:
```bash
redis-cli ping
# Should respond with: PONG
```
### 2. Install Application Dependencies
**Install backend dependencies:**
```bash
cd backend
npm install
```
**Install frontend dependencies:**
```bash
cd ../frontend
npm install
```
### 3. Configure Environment (Optional)
Create a `.env` file in the `backend` directory if you need custom Redis settings:
```env
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
SESSION_SECRET=your-secret-key-here
```
### 4. Initialize Database
**Seed the database with sample pharmacies:**
```bash
cd backend
npm run seed
```
**Create admin user:**
```bash
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:
```bash
ADMIN_USERNAME=myadmin ADMIN_PASSWORD=mypassword npm run create-admin
```
### 5. Running the Application
**Start Redis** (if not running):
```bash
redis-server
```
**Start the backend server:**
```bash
cd backend
npm start
```
The backend will run on `http://localhost:3001`
**Start the frontend development server:**
```bash
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
1. Type the name of a medicine in the search bar
2. The app will search the CIMA database in real-time
3. Click on a medicine to see which pharmacies have it
4. View prices and stock availability
### Admin Panel
1. Click the "⚙️ Admin Panel" button
2. Login with your credentials (default: `admin` / `admin123`)
3. **Pharmacies Tab**: Add, edit, or delete pharmacies
4. **Medicines Tab**: Search medicines from the CIMA database
5. **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 CIMA
- `GET /api/medicines/:nregistro/pharmacies` - Get pharmacies selling a medicine
- `GET /api/pharmacies` - Get all pharmacies
### Authentication API
- `POST /api/auth/login` - Login (requires username and password)
- `POST /api/auth/logout` - Logout
- `GET /api/auth/check` - Check authentication status
### Admin API (All require authentication)
- `POST /api/admin/pharmacies` - Add a new pharmacy
- `PUT /api/admin/pharmacies/:id` - Update a pharmacy
- `DELETE /api/admin/pharmacies/:id` - Delete a pharmacy
- `GET /api/admin/medicines?q=<query>` - Search medicines from CIMA (for admin)
- `GET /api/admin/pharmacies/:id/medicines` - Get medicines linked to a pharmacy
- `POST /api/admin/pharmacy-medicines` - Link medicine to pharmacy
- `PUT /api/admin/pharmacy-medicines/:id` - Update price/stock
- `DELETE /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_medicines` now uses `medicine_nregistro` (CIMA registration number) instead of local `medicine_id`
## 🐛 Troubleshooting
### Redis Connection Issues
If you see "Redis Client Error":
```bash
# 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:
```bash
cd backend
rm database.sqlite
npm run seed
npm run create-admin
```
## 📝 Development
**Backend development with auto-reload:**
```bash
cd backend
npm run dev
```
**Frontend development:**
```bash
cd frontend
npm run dev
```
**Clear Redis cache:**
```bash
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