# πŸ’Š 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=` - 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=` - 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