# FarmaFinder A web application to search for medicines from the official Spanish CIMA database and find which pharmacies sell them. ## Features ### Web App (Desktop/PWA) - Real-time medicine search from CIMA API (Agencia Espanola 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 ### Mobile App (React Native) - Native iOS/Android experience with Expo - Medicine search with real-time results - Interactive map with pharmacy markers - Barcode scanner for quick medicine lookup - Push notifications for availability alerts - Biometric authentication (Face ID / Touch ID) - Offline cache for favorite medicines ## Tech Stack | App | Stack | |-----|-------| | Backend | Node.js + Express, SQLite/PostgreSQL, Redis | | Parapharmacy API | Node.js + Express, MongoDB | | Frontend (Web) | React + Vite, Capacitor | | Frontend (Mobile) | Expo SDK 57 + React Native, Zustand, Axios + TanStack Query | | Workflow Automation | N8N | | Build system | Turborepo | | Package manager | npm workspaces | ## Prerequisites - Node.js v20+ - npm v9+ - Redis server v6.0+ (or use Docker) - Docker + Docker Compose v2 (optional, for containerized deployment) ## Project Structure This is a **Turborepo monorepo**. All applications live under `apps/`: ``` FarmaFinder/ ├── package.json # Root: workspaces + turbo scripts ├── turbo.json # Turborepo task configuration ├── docker-compose.yml # Full stack: backend + frontend + Redis + Postgres + MongoDB + N8N ├── .env.example # Environment variables template │ ├── apps/ │ ├── backend/ # Node.js + Express API (medicines) │ │ ├── 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 │ │ └── package.json │ │ │ ├── parapharmacy-api/ # Parapharmacy products API │ │ ├── Dockerfile │ │ ├── src/ │ │ │ ├── server.js # Express + Swagger │ │ │ ├── config.js # Configuration │ │ │ ├── models/ │ │ │ │ └── Product.js │ │ │ └── routes/ │ │ │ └── products.js │ │ ├── README.md │ │ └── package.json │ │ │ ├── frontend/ # React + Vite (Desktop/PWA) │ │ ├── Dockerfile │ │ ├── nginx.conf # Nginx config for Docker │ │ ├── src/ │ │ │ ├── components/ # React components │ │ │ ├── views/ # View components (Public/Admin) │ │ │ ├── App.jsx │ │ │ └── main.jsx │ │ └── package.json │ │ │ ├── frontend-mobile/ # Expo + React Native (iOS/Android) │ │ ├── app/ # Expo Router screens │ │ ├── components/ │ │ ├── services/ │ │ ├── store/ │ │ └── package.json │ │ │ ├── scraper/ # Puppeteer scraper (legacy) │ │ └── package.json │ │ │ └── pip-platform/ # Python FastAPI platform (separate docker-compose) │ ├── Dockerfile │ ├── docker-compose.yml │ └── pyproject.toml │ ├── n8n/ # N8N workflow automation │ ├── workflows/ # Workflow JSON files │ │ ├── parapharmacy-scraper.json │ │ └── parapharmacy-manual-scraper.json │ └── README.md │ ├── API/ # Shared API source files ├── scripts/ # Build/utility scripts └── docs/ # Documentation └── parapharmacy.md # Parapharmacy system documentation ``` ## Features ### Parapharmacy Search - Scraping de múltiples tiendas españolas (Promofarma, Pharmarket, DocMorris, etc.) - API REST dedicada con MongoDB - Scraping automático cada 3 días via N8N - Búsqueda full-text por nombre, marca y categoría - [Documentación completa](docs/parapharmacy.md) --- ## Quick Start ### Install dependencies ```bash npm install ``` This installs all workspace dependencies (backend, frontend, mobile, scraper) via npm workspaces. ### Development ```bash # Start everything (backend + frontend) npm run dev # Start only backend npm run dev:backend # Start only frontend npm run dev:frontend # Start mobile app npx turbo run dev --filter=frontend-mobile ``` ### Build ```bash # Build all apps npm run build # Build only frontend npm run build:web ``` ### Test ```bash # Run all tests npm test # Test specific app npm test --workspace=farma-clic-backend npm test --workspace=farma-clic-frontend ``` ## Docker Setup Runs the full stack with a single command. ```bash # Copy and configure environment cp .env.example .env # Edit .env with your settings (especially passwords) docker compose up --build ``` ### Services | Service | URL | Description | |---------|-----|-------------| | Frontend | http://localhost:4000 | React web app | | Backend API | http://localhost:3001 | Medicines API | | Parapharmacy API | http://localhost:3002 | Parapharmacy products API | | Swagger Docs | http://localhost:3002/api/docs | API documentation | | N8N | http://localhost:5678 | Workflow automation | ### First Run ```bash # Create admin user for FarmaFinder docker compose exec backend node create-admin.js # Default: admin / admin123 # Seed sample pharmacies docker compose exec backend node seed.js ``` ### N8N Setup N8N auto-creates an admin account on first start: - **Email**: admin@farmafinder.com - **Password**: change-me (configurable in `.env`) See [Parapharmacy Documentation](docs/parapharmacy.md) for details. ### Stop ```bash docker compose down ``` ### Reset Data ```bash docker compose down -v ``` ## Manual Setup ### 1. Install Redis **Ubuntu/Debian:** ```bash sudo apt-get install redis-server sudo systemctl start redis-server ``` **macOS:** ```bash brew install redis brew services start redis ``` **Docker:** ```bash docker run -d -p 6379:6379 redis:alpine ``` Verify: `redis-cli ping` should respond `PONG`. ### 2. Configure Environment (Optional) Create `apps/backend/.env`: ```env REDIS_HOST=localhost REDIS_PORT=6379 REDIS_PASSWORD= SESSION_SECRET=your-secret-key-here ``` ### 3. Initialize Database ```bash # Seed sample pharmacies npm run dev --workspace=farma-clic-backend -- run seed # Create admin user (default: admin / admin123) npm run dev --workspace=farma-clic-backend -- run create-admin ``` ### 4. Run ```bash npm run dev ``` ## API Endpoints ### Medicines (Backend - Port 3001) **Public:** - `GET /api/medicines/search?q=` - Search medicines (CIMA API) - `GET /api/medicines/:nregistro` - Medicine details - `GET /api/medicines/:nregistro/pharmacies` - Pharmacies selling a medicine - `GET /api/pharmacies` - All pharmacies **Parapharmacy Proxy:** - `GET /api/products/parapharmacy/search?q=` - Search parapharmacy products - `GET /api/products/parapharmacy/:id` - Parapharmacy product details - `GET /api/products/parapharmacy/categories` - List categories - `GET /api/products/parapharmacy/brands` - List brands **Auth:** - `POST /api/auth/login` - Login - `POST /api/auth/logout` - Logout - `GET /api/auth/check` - Check auth status **Admin:** - `POST /api/admin/pharmacies` - Add pharmacy - `PUT /api/admin/pharmacies/:id` - Update pharmacy - `DELETE /api/admin/pharmacies/:id` - Delete pharmacy - `GET /api/admin/medicines?q=` - Search medicines - `GET /api/admin/pharmacies/:id/medicines` - Linked medicines - `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 link ### Parapharmacy API (Port 3002) - `GET /api/products/search?q=` - Search products (full-text) - `GET /api/products/:id` - Product details - `GET /api/products` - List products - `POST /api/products` - Create product - `POST /api/products/bulk` - Bulk upsert (for scrapers) - `PUT /api/products/:id` - Update product - `DELETE /api/products/:id` - Delete product - `GET /api/products/categories` - List categories - `GET /api/products/brands` - List brands - `GET /api/sources` - Configured sources - `GET /api/health` - Health check - `GET /api/docs` - Swagger documentation See [Parapharmacy Documentation](docs/parapharmacy.md) for details. ## Database Schema ### SQLite Tables **pharmacies**: `id`, `name`, `address`, `phone`, `latitude`, `longitude` **pharmacy_medicines**: `id`, `pharmacy_id`, `medicine_nregistro`, `medicine_name`, `price`, `stock` **users**: `id`, `username`, `password_hash`, `created_at` ### Redis Cache - `medicines:search:{query}` - Search results (TTL: 1h) - `medicine:{nregistro}` - Medicine details (TTL: 24h) ## Mobile App Setup ### Prerequisites - Node.js v20+ - Expo CLI: `npm install -g expo-cli` - EAS CLI: `npm install -g eas-cli` - iOS: Xcode + CocoaPods (Mac only) - Android: Android Studio + SDK ### Development ```bash # Install dependencies (already done via npm install at root) # Start mobile dev server npx turbo run dev --filter=frontend-mobile # Scan QR code with Expo Go app ``` ### Native Features | Feature | Implementation | |---------|---------------| | Barcode Scanner | `expo-camera` with `CameraView` | | Push Notifications | `expo-notifications` | | Biometrics | `expo-local-authentication` | | Maps | `react-native-maps` | | Secure Storage | `expo-secure-store` | ### EAS Build ```bash cd apps/frontend-mobile # Development build eas build --profile development --platform ios eas build --profile development --platform android # Production build eas build --profile production --platform android eas build --profile production --platform ios # Submit to stores eas submit --profile production --platform android eas submit --profile production --platform ios ``` ### Environment Configuration ```typescript // apps/frontend-mobile/constants/config.ts const ENV = { development: { API_BASE_URL: 'http://localhost:3001/api' }, production: { API_BASE_URL: 'https://your-production-api.com/api' }, }; ``` ## N8N Workflow Automation N8N handles automated scraping of parapharmacy products. ### Access - **URL**: http://localhost:5678 - **Email**: admin@farmafinder.com - **Password**: change-me (change in `.env`) ### Workflows | Workflow | Trigger | Description | |----------|---------|-------------| | Parapharmacy Scraper | Every 3 days at 2am | Automatic scraping (inactive by default) | | Parapharmacy Manual Scraper | POST `/webhook/scrape-parapharmacy` | On-demand scraping | ### Manual Scraping ```bash curl -X POST http://localhost:5678/webhook/scrape-parapharmacy ``` See [N8N Documentation](n8n/README.md) for details. --- ## Troubleshooting ### Redis Connection Issues ```bash redis-cli ping # Should respond: PONG redis-server # Start if not running redis-cli FLUSHALL # Clear cache ``` ### CIMA API Timeout - Check internet connection - CIMA API may be temporarily unavailable - App falls back to cached data ### Database Reset ```bash cd apps/backend rm database.sqlite npm run seed npm run create-admin ``` ### Turborepo Cache Issues ```bash npx turbo clean # Clear Turbo cache rm -rf node_modules # Full reset npm install ``` ## External Resources - [CIMA API](https://cima.aemps.es/) - [Turborepo](https://turbo.build/repo) - [Redis](https://redis.io/documentation) - [React](https://react.dev) - [Express](https://expressjs.com) - [Expo](https://docs.expo.dev) ## License ISC