308 lines
7.8 KiB
Markdown
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
|
|
|