Merge fixing things
Build & Push Docker Images / Detect Changes (push) Successful in 7s
Build & Push Docker Images / Backend Tests (push) Successful in 1m47s
Build & Push Docker Images / Frontend Tests (push) Has been skipped
Build & Push Docker Images / Build Backend (push) Successful in 26s
Build & Push Docker Images / Build Frontend (push) Has been skipped
Build & Push Docker Images / Deploy (push) Successful in 23s
Build & Push Docker Images / Detect Changes (push) Successful in 7s
Build & Push Docker Images / Backend Tests (push) Successful in 1m47s
Build & Push Docker Images / Frontend Tests (push) Has been skipped
Build & Push Docker Images / Build Backend (push) Successful in 26s
Build & Push Docker Images / Build Frontend (push) Has been skipped
Build & Push Docker Images / Deploy (push) Successful in 23s
This commit was merged in pull request #26.
This commit is contained in:
@@ -1 +1 @@
|
||||
{"pid":233628,"startedAt":1783590885727}
|
||||
{"pid":10782,"startedAt":1783578681151}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
# Plan: Dark Mode para FarmaFinder Mobile
|
||||
|
||||
## Objetivo
|
||||
Añadir soporte de modo oscuro a la app móvil con:
|
||||
- Detección automática del modo oscuro del sistema
|
||||
- Toggle manual en la pantalla de perfil (Configuración)
|
||||
- Persistencia de la preferencia del usuario
|
||||
|
||||
## Arquitectura
|
||||
|
||||
### 1. Theme Store (Zustand + AsyncStorage)
|
||||
**Nuevo archivo: `store/themeStore.ts`**
|
||||
|
||||
- Estado: `mode: 'light' | 'dark' | 'system'`
|
||||
- Persistencia con `@react-native-async-storage/async-storage`
|
||||
- Acciones: `setMode()`, `init()` (carga del storage al arrancar)
|
||||
- Por defecto: `'system'` (respeta el dispositivo)
|
||||
|
||||
### 2. Hook `useThemeColor`
|
||||
**Nuevo archivo: `hooks/useThemeColor.ts`**
|
||||
|
||||
- Usa `useColorScheme()` de React Native para detectar el color del sistema
|
||||
- Combina con el `mode` del themeStore para determinar el tema efectivo
|
||||
- Retorna el objeto `colors` apropiado (light o dark)
|
||||
- Los componentes consumirán este hook en vez de importar `colors` directamente
|
||||
|
||||
### 3. Paleta de colores oscura
|
||||
**Modificar: `constants/theme.ts`**
|
||||
|
||||
Añadir exportación `darkColors` con la paleta oscura:
|
||||
|
||||
| Token | Light (actual) | Dark (nuevo) |
|
||||
|---|---|---|
|
||||
| `background` | `#fbfbfb` | `#121212` |
|
||||
| `card` | `#ffffff` | `#1e1e1e` |
|
||||
| `surfaceLow` | `#f2f4f5` | `#2a2a2a` |
|
||||
| `surface` | `#eceeef` | `#333333` |
|
||||
| `surfaceHigh` | `#e6e8e9` | `#3a3a3a` |
|
||||
| `border` | `#c0c9bb` | `#3a3a3a` |
|
||||
| `separator` | `#c0c9bb` | `#3a3a3a` |
|
||||
| `text` | `#111417` | `#f0f0f0` |
|
||||
| `textSecondary` | `#41493e` | `#a0a0a0` |
|
||||
| `textInverse` | `#ffffff` | `#111417` |
|
||||
| `primaryContainer` | `#cfead0` | `#1a3a1c` |
|
||||
| `onPrimaryContainer` | `#0d2b12` | `#cfead0` |
|
||||
| `secondaryContainer` | `#dbe7ff` | `#1a2a4a` |
|
||||
| `tertiaryContainer` | `#efe7ff` | `#2a1a4a` |
|
||||
| `dangerContainer` | `#feecec` | `#3a1a1a` |
|
||||
| `accentWarm` | `#f5a97a` | `#f5a97a` (sin cambio) |
|
||||
| `primary`, `secondary`, `tertiary`, `scanButton`, `success`, `danger`, `warning` | (sin cambios) | (sin cambios) |
|
||||
|
||||
### 4. Provider wrapper
|
||||
**Nuevo archivo: `components/ThemeProvider.tsx`**
|
||||
|
||||
- Lee el `mode` del themeStore y el `useColorScheme()` del sistema
|
||||
- Calcula el tema efectivo (`light` o `dark`)
|
||||
- Provee `colors` y `isDark` vía React Context
|
||||
- Carga la preferencia guardada en AsyncStorage al montar
|
||||
|
||||
### 5. Integración en Root Layout
|
||||
**Modificar: `app/_layout.tsx`**
|
||||
|
||||
- Envolver toda la app con `<ThemeProvider>`
|
||||
- El `StatusBar` se ajusta: `style={isDark ? 'light' : 'auto'}`
|
||||
- Los colores del Stack header se leen del contexto
|
||||
|
||||
### 6. Toggle en el perfil
|
||||
**Modificar: `app/(tabs)/profile.tsx`**
|
||||
|
||||
Añadir en la pantalla de perfil (antes de "Configuración") un nuevo item de menú:
|
||||
- Icono: `moon-outline` / `sunny-outline` según el tema actual
|
||||
- Texto: "Modo de pantalla"
|
||||
- Al pulsar, mostrar un picker/modal con 3 opciones:
|
||||
- **Sistema** (icono: phone-portrait) - respeta el SO
|
||||
- **Claro** (icono: sunny) - fuerza light
|
||||
- **Oscuro** (icono: moon) - fuerza dark
|
||||
- El toggle se muestra inline (sin modal extra) tipo Segmented Control
|
||||
|
||||
### 7. Actualizar todos los screens y components
|
||||
|
||||
Cada archivo que importa `colors` debe cambiar a usar el hook `useThemeColor()`:
|
||||
|
||||
| Archivo | Cambio |
|
||||
|---|---|
|
||||
| `app/_layout.tsx` | Usa ThemeProvider + context para header colors |
|
||||
| `app/(tabs)/_layout.tsx` | Tab bar y header leen colors del context |
|
||||
| `app/(tabs)/index.tsx` | `const { colors } = useThemeColor()` |
|
||||
| `app/(tabs)/search.tsx` | `const { colors } = useThemeColor()` |
|
||||
| `app/(tabs)/scan.tsx` | `const { colors } = useThemeColor()` |
|
||||
| `app/(tabs)/alerts.tsx` | `const { colors } = useThemeColor()` |
|
||||
| `app/(tabs)/profile.tsx` | `const { colors, isDark } = useThemeColor()` |
|
||||
| `app/(tabs)/map.tsx` | `const { colors } = useThemeColor()` |
|
||||
| `app/medicine/[id].tsx` | `const { colors } = useThemeColor()` |
|
||||
| `app/pharmacy/[id].tsx` | `const { colors } = useThemeColor()` |
|
||||
| `app/auth/login.tsx` | `const { colors } = useThemeColor()` |
|
||||
| `app/auth/register.tsx` | `const { colors } = useThemeColor()` |
|
||||
| `components/SearchBar.tsx` | `const { colors } = useThemeColor()` |
|
||||
| `components/MedicineCard.tsx` | `const { colors } = useThemeColor()` |
|
||||
| `components/LoadingSpinner.tsx` | `const { colors } = useThemeColor()` |
|
||||
| `components/StockBadge.tsx` | Añade colores dark para badges |
|
||||
| `components/BarcodeScanner.tsx` | `const { colors } = useThemeColor()` |
|
||||
|
||||
**Nota sobre StyleSheet**: Los `StyleSheet.create()` se ejecutan una vez. Para que los estilos se actualicen con el tema, las propiedades que dependen de `colors` deben aplicarse vía `style` inline o moverse a funciones que retornen estilos dinámicos. La estrategia más limpia es:
|
||||
- Los colores de fondo/texto van como inline styles
|
||||
- Las estructuras (flex, padding, borderRadius) se quedan en `StyleSheet.create`
|
||||
|
||||
### 8. Colores hardcodeados
|
||||
Los siguientes archivos tienen colores inline hardcodeados que necesitan variante dark:
|
||||
|
||||
- **`StockBadge.tsx`**: `#eaf7ec`, `#fff3cd`, `#feecec` → añadir tokens al tema
|
||||
- **`search.tsx`**: suggestions con `#ffffff`, `#f0f7ff`, etc. → usar colores del tema
|
||||
- **`profile.tsx`**: feedback `#eaf7ec`, `#cfead0`, `#fecaca` → usar colores del tema
|
||||
- **`home/index.tsx`**: `rgba(255,255,255,0.2/0.3)` para iconos → ajustar opacidad
|
||||
|
||||
### 9. app.json
|
||||
**Modificar: `app.json`**
|
||||
|
||||
Cambiar `"userInterfaceStyle": "light"` → `"userInterfaceStyle": "automatic"`
|
||||
|
||||
## Orden de ejecución
|
||||
|
||||
1. `store/themeStore.ts` (nuevo)
|
||||
2. `hooks/useThemeColor.ts` (nuevo)
|
||||
3. `constants/theme.ts` (añadir `darkColors`)
|
||||
4. `components/ThemeProvider.tsx` (nuevo)
|
||||
5. `app/_layout.tsx` (envolver con ThemeProvider)
|
||||
6. `app/(tabs)/_layout.tsx` (colores dinámicos)
|
||||
7. `app/(tabs)/profile.tsx` (toggle de tema)
|
||||
8. Todos los screens y components (migrar a hook)
|
||||
9. `app.json` (userInterfaceStyle: automatic)
|
||||
10. Corregir colores hardcodeados
|
||||
|
||||
## Verificación
|
||||
|
||||
1. Ejecutar `npx expo start` y verificar que la app arranca sin errores
|
||||
2. Probar en iOS/Android: el tema respeta la configuración del sistema
|
||||
3. Ir a Perfil > Modo de pantalla y cambiar entre Claro/Oscuro/Sistema
|
||||
4. Verificar que el cambio es inmediato sin recargar la app
|
||||
5. Cerrar y reabrir la app → la preferencia persiste
|
||||
6. Verificar que todos los screens se ven bien en ambos modos (sin texto invisible, sin fondos transparentes)
|
||||
7. Probar tablets ( responsive)
|
||||
Reference in New Issue
Block a user