Documentos + Homepage rediseñada
Build & Push Docker Images / test-backend (push) Successful in 24s
Build & Push Docker Images / test-frontend (push) Successful in 23s
Build & Push Docker Images / build-backend (push) Successful in 2m22s
Build & Push Docker Images / build-frontend (push) Successful in 57s
Build & Push Docker Images / test-backend (push) Successful in 24s
Build & Push Docker Images / test-frontend (push) Successful in 23s
Build & Push Docker Images / build-backend (push) Successful in 2m22s
Build & Push Docker Images / build-frontend (push) Successful in 57s
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
# FarmaFinder — TSI Barcode Scanning + Capacitor 8 Upgrade
|
||||
|
||||
## Overview
|
||||
|
||||
Two sequential phases:
|
||||
1. **Phase A** — Upgrade Capacitor 6 → 8 (prerequisite for latest barcode scanner plugin)
|
||||
2. **Phase B** — Implement real TSI barcode scanning with manual CIP entry fallback
|
||||
|
||||
---
|
||||
|
||||
## Phase A: Upgrade Capacitor 6 → 8
|
||||
|
||||
### A1. Upgrade Capacitor packages (root)
|
||||
|
||||
```bash
|
||||
npm install @capacitor/cli@latest @capacitor/core@latest \
|
||||
@capacitor/android@latest @capacitor/ios@latest \
|
||||
@capacitor/app@latest @capacitor/splash-screen@latest \
|
||||
@capacitor/status-bar@latest
|
||||
```
|
||||
|
||||
This bumps all `@capacitor/*` from `^6.x` to `^8.x` in `package.json`.
|
||||
|
||||
### A2. Update `android/variables.gradle`
|
||||
|
||||
Replace all 13 version variables to meet Capacitor 8 minimums:
|
||||
|
||||
| Variable | Current | New |
|
||||
|---|---|---|
|
||||
| `minSdkVersion` | 22 | **24** |
|
||||
| `compileSdkVersion` | 34 | **36** |
|
||||
| `targetSdkVersion` | 34 | **36** |
|
||||
| `androidxActivityVersion` | 1.8.0 | **1.11.0** |
|
||||
| `androidxAppCompatVersion` | 1.6.1 | **1.7.1** |
|
||||
| `androidxCoordinatorLayoutVersion` | 1.2.0 | **1.3.0** |
|
||||
| `androidxCoreVersion` | 1.12.0 | **1.17.0** |
|
||||
| `androidxFragmentVersion` | 1.6.2 | **1.8.9** |
|
||||
| `coreSplashScreenVersion` | 1.0.1 | **1.2.0** |
|
||||
| `androidxWebkitVersion` | 1.9.0 | **1.14.0** |
|
||||
| `junitVersion` | 4.13.2 | 4.13.2 (same) |
|
||||
| `androidxJunitVersion` | 1.1.5 | **1.3.0** |
|
||||
| `androidxEspressoCoreVersion` | 3.5.1 | **3.7.0** |
|
||||
| `cordovaAndroidVersion` | 10.1.1 | **14.0.1** |
|
||||
|
||||
### A3. Update `ios/App/Podfile`
|
||||
|
||||
- Line 3: Change `platform :ios, '13.0'` → `platform :ios, '15.0'`
|
||||
|
||||
### A4. Update `android/app/src/main/AndroidManifest.xml`
|
||||
|
||||
- Add `density` to `android:configChanges` on line 13:
|
||||
```
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|density"
|
||||
```
|
||||
|
||||
### A5. Update `android/build.gradle` (Gradle plugin)
|
||||
|
||||
- Update Android Gradle Plugin from `8.2.1` → `8.13.0`
|
||||
- Update Google Services plugin from `4.4.0` → `4.4.4`
|
||||
- Update Gradle wrapper to `8.14.3` in `android/gradle/wrapper/gradle-wrapper.properties`
|
||||
|
||||
### A6. Run Capacitor sync
|
||||
|
||||
```bash
|
||||
npx cap sync
|
||||
```
|
||||
|
||||
### A7. Verify build
|
||||
|
||||
- Open `android/` in Android Studio — confirm Gradle sync succeeds
|
||||
- Open `ios/App` in Xcode — confirm pod install succeeds and build compiles
|
||||
|
||||
---
|
||||
|
||||
## Phase B: Real TSI Barcode Scanning
|
||||
|
||||
### B1. Install barcode scanning plugin
|
||||
|
||||
From `frontend/`:
|
||||
```bash
|
||||
npm install @capacitor-mlkit/barcode-scanning@^8.1.0
|
||||
npm install barcode-detector # web polyfill for PWA browser fallback
|
||||
```
|
||||
|
||||
From root:
|
||||
```bash
|
||||
npx cap sync
|
||||
```
|
||||
|
||||
**Plugin:** `@capacitor-mlkit/barcode-scanning` v8.1.0 — Google ML Kit engine, 91K+ weekly npm downloads, supports Code 128 (TSI physical card barcode) and QR Code (virtual TSI card).
|
||||
|
||||
### B2. Native manifest verification (no changes expected)
|
||||
|
||||
| Platform | File | Required | Status |
|
||||
|---|---|---|---|
|
||||
| Android | `AndroidManifest.xml:44` | `CAMERA` permission | Already present |
|
||||
| iOS | `Info.plist:52-53` | `NSCameraUsageDescription` | Already present |
|
||||
|
||||
### B3. Rewrite `frontend/src/views/ScannerView.jsx`
|
||||
|
||||
**Remove:**
|
||||
- `MOCK_TSI_CARDS` array and all mock card state/UI
|
||||
- `navigator.mediaDevices.getUserMedia()` camera logic (lines 40-73)
|
||||
- Auto-scan `setTimeout` simulation (lines 98-105)
|
||||
- Simulated scan fallback panel (lines 170-198)
|
||||
- `selectedMockCard` state
|
||||
|
||||
**Add:**
|
||||
- Import `BarcodeScanner`, `BarcodeFormat`, `LensFacing` from `@capacitor-mlkit/barcode-scanning`
|
||||
- Import `Capacitor` from `@capacitor/core` (platform detection)
|
||||
- Import `barcode-detector/polyfill` at top (web fallback)
|
||||
|
||||
**New scan flow:**
|
||||
```
|
||||
1. Component mounts → show "Start Scanning" button + manual CIP input
|
||||
2. User taps "Start Scanning":
|
||||
a. Check BarcodeScanner.isSupported() → error if not
|
||||
b. Check/request camera permission via BarcodeScanner.checkPermissions() / requestPermissions()
|
||||
c. Call BarcodeScanner.scan({ formats: [BarcodeFormat.Code128, BarcodeFormat.QrCode], autoZoom: true })
|
||||
d. Extract barcodes[0].rawValue (NOTE: can be undefined per v8 breaking change — handle gracefully)
|
||||
e. Validate CIP format: /^[A-Z0-9]{16}$/i
|
||||
f. If valid → fetchPrescriptions(cip) → show prescriptions
|
||||
g. If invalid → show error "Invalid card barcode. Try manual entry."
|
||||
3. Manual CIP input:
|
||||
- Text input field with placeholder "Enter CIP code manually"
|
||||
- "Submit" button → validates format → fetchPrescriptions(cip)
|
||||
4. PWA/browser fallback:
|
||||
- Detect: !Capacitor.isNativePlatform()
|
||||
- Show message: "Barcode scanning requires the mobile app. Enter your CIP code manually below."
|
||||
- Show only the manual CIP input (no scan button)
|
||||
```
|
||||
|
||||
**Phases (simplified):**
|
||||
- `idle` — initial state, scan button + manual input visible
|
||||
- `scanning` — ML Kit native UI active (camera takes over)
|
||||
- `prescriptions` — results display (keep existing prescription card UI)
|
||||
- `error` — permission denied / unsupported / invalid barcode
|
||||
|
||||
**Keep unchanged:**
|
||||
- `playBeep()` function
|
||||
- `fetchPrescriptions(cip)` function
|
||||
- `handlePickPrescription(rx)` function
|
||||
- `handleBack()` function
|
||||
- Prescription display UI (lines 201-249)
|
||||
- `onSelectMedicine` callback prop
|
||||
|
||||
### B4. Rewrite `frontend/src/views/ScannerView.css`
|
||||
|
||||
**Remove:**
|
||||
- `.scanner-viewport-wrap`, `.scanner-camera-container`, `.scanner-video`, `.scanner-frame`, `.scanner-laser`, `.scanner-hint` (old camera overlay)
|
||||
- `.scanner-simulate-panel`, `.mock-cards-list`, `.mock-card-btn`, `.simulate-scan-btn`, `.simulate-label`, `.mock-card-icon`, `.mock-card-info` (mock card panel)
|
||||
- `.scanner-placeholder` with spinner (old loading state)
|
||||
|
||||
**Add:**
|
||||
- `.scan-start-btn` — large centered button with camera icon, teal background (`#0f766e`), full-width
|
||||
- `.manual-cip-section` — input group with text field + submit button
|
||||
- `.cip-input` — text input styled to match existing dark theme, monospace font
|
||||
- `.cip-submit-btn` — teal button matching scan button style
|
||||
- `.pwa-notice` — info banner for browser users
|
||||
- `.scan-error-panel` — error state with icon and retry button
|
||||
|
||||
### B5. No changes to other files
|
||||
|
||||
- `HomeView.jsx` — "Scan TSI Card" button still navigates to ScannerView
|
||||
- `PublicView.jsx` — screen routing and `onSelectMedicine` handoff unchanged
|
||||
- `backend/server.js` — user handles `/api/tsi/:cip/prescriptions`
|
||||
- `capacitor.config.json` — no scanner-specific config needed
|
||||
|
||||
---
|
||||
|
||||
## Files Modified (summary)
|
||||
|
||||
| File | Phase | Change |
|
||||
|---|---|---|
|
||||
| `package.json` | A1 | Bump all `@capacitor/*` to ^8.x |
|
||||
| `frontend/package.json` | B1 | Add `@capacitor-mlkit/barcode-scanning@^8.1.0` + `barcode-detector` |
|
||||
| `android/variables.gradle` | A2 | Update all 13 SDK/library versions |
|
||||
| `ios/App/Podfile` | A3 | iOS deployment target 13.0 → 15.0 |
|
||||
| `android/app/src/main/AndroidManifest.xml` | A4 | Add `density` to configChanges |
|
||||
| `android/build.gradle` | A5 | AGP 8.2.1 → 8.13.0, Google Services 4.4.0 → 4.4.4 |
|
||||
| `android/gradle/wrapper/gradle-wrapper.properties` | A5 | Gradle wrapper → 8.14.3 |
|
||||
| `frontend/src/views/ScannerView.jsx` | B3 | Full rewrite — real barcode scanning + manual input |
|
||||
| `frontend/src/views/ScannerView.css` | B4 | Remove old camera/mock styles, add new scan UI |
|
||||
|
||||
---
|
||||
|
||||
## Known Issues
|
||||
|
||||
- **Android NullPointerException bug** (GitHub capawesome-team/capacitor-mlkit #160/#324) — affects `startScan()` in v8.0.1. Workaround: use `scan()` method (built-in native UI) instead of `startScan()` (custom WebView mode). Plan uses `scan()`, so this shouldn't hit us.
|
||||
- **`rawValue` can be undefined** in v8.x — handle with null check before CIP validation.
|
||||
- **Capacitor 8 requires Xcode 26+** — must have latest Xcode installed.
|
||||
- **Gradle 8.14.3 requires JDK 21+** — confirm JDK 21 is available.
|
||||
- **`@capacitor-mlkit/barcode-scanning` v6.x.x is deprecated** — this is why we upgrade to Capacitor 8 first (v8.x.x plugin requires Cap 8).
|
||||
|
||||
---
|
||||
|
||||
## Implementation Order
|
||||
|
||||
| Step | Phase | Estimated Time |
|
||||
|---|---|---|
|
||||
| A1-A6 | Capacitor upgrade | ~30 min |
|
||||
| A7 | Verify build (Android + iOS) | ~30 min |
|
||||
| B1 | Install barcode plugin | ~5 min |
|
||||
| B3 | Rewrite ScannerView.jsx | ~2 hrs |
|
||||
| B4 | Update ScannerView.css | ~30 min |
|
||||
| B5 | Test on Android device | ~30 min |
|
||||
| B5 | Test on iOS device | ~30 min |
|
||||
|
||||
Total: ~4-5 hours
|
||||
Reference in New Issue
Block a user