Ichitux b5d1cb12bf
Some checks failed
Run Tests / test-backend (push) Failing after 48s
Run Tests / test-frontend (push) Failing after 24s
Add tests in workflow
2026-04-01 01:24:17 +02:00
2026-04-01 01:24:17 +02:00
2026-04-01 01:18:21 +02:00
2026-04-01 01:18:21 +02:00
2026-04-01 01:18:21 +02:00
2026-04-01 01:18:21 +02:00
2026-04-01 01:18:21 +02:00
2026-04-01 01:18:21 +02:00
2026-04-01 01:17:33 +02:00

💊 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

  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":

# 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

📄 License

ISC

Description
No description provided
Readme 1.7 MiB
Languages
JavaScript 81.1%
CSS 17.9%
Shell 0.6%
HTML 0.4%