# 💊 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)

## 🐳 Docker Setup (Recommended)

Runs the full stack (backend, frontend, Redis) with a single command.

**Prerequisites**: Docker and Docker Compose v2.

```bash
# Copy and configure environment (optional — defaults work for local dev)
cp backend/.env.example backend/.env
# Edit backend/.env to set SESSION_SECRET and any other vars

docker compose up --build
```

App available at `http://localhost:3000`.

**First run — create an admin user:**
```bash
docker compose exec backend node create-admin.js
# Default: admin / admin123 — change after first login
```

**Seed sample pharmacies:**
```bash
docker compose exec backend node seed.js
```

**Stop:**
```bash
docker compose down
```

Database is persisted in a named Docker volume (`backend_data`). To wipe it:
```bash
docker compose down -v
```

---

## 🚀 Manual 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/
├── docker-compose.yml         # Full stack: backend + frontend + Redis
├── backend/
│   ├── Dockerfile
│   ├── 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
│   ├── .env.example           # Environment variable template
│   └── package.json
├── frontend/
│   ├── Dockerfile
│   ├── nginx.conf             # Nginx config (Docker): serves SPA + proxies /api
│   ├── src/
│   │   ├── components/        # React components
│   │   │   ├── admin/        # Admin panel components
│   │   │   ├── PharmacyMap.jsx  # Leaflet map (OpenStreetMap)
│   │   │   └── ...
│   │   ├── 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

