diff --git a/apps/frontend-mobile/app/(tabs)/_layout.tsx b/apps/frontend-mobile/app/(tabs)/_layout.tsx
index f95d92c..fc4334c 100644
--- a/apps/frontend-mobile/app/(tabs)/_layout.tsx
+++ b/apps/frontend-mobile/app/(tabs)/_layout.tsx
@@ -1,14 +1,40 @@
import { Tabs } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
+import { View, StyleSheet, Platform } from 'react-native';
+import { colors, shadows } from '../../constants/theme';
+
+function ScanIcon({ color, size }: { color: string; size: number }) {
+ return (
+
+
+
+
+
+ );
+}
export default function TabLayout() {
return (
+ (
+
+ ),
+ }}
+ />
+ ,
+ tabBarLabel: () => null,
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
(
-
- ),
+ href: null,
}}
/>
);
}
+
+const styles = StyleSheet.create({
+ tabBar: {
+ backgroundColor: colors.card,
+ borderTopColor: colors.border,
+ height: Platform.OS === 'ios' ? 88 : 64,
+ paddingBottom: Platform.OS === 'ios' ? 24 : 8,
+ paddingTop: 8,
+ },
+ tabBarLabel: {
+ fontSize: 11,
+ fontWeight: '500',
+ },
+ header: {
+ backgroundColor: colors.card,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.05,
+ shadowRadius: 4,
+ elevation: 1,
+ },
+ headerTitle: {
+ color: colors.text,
+ fontWeight: '600',
+ fontSize: 17,
+ },
+ fabContainer: {
+ position: 'absolute',
+ top: -16,
+ alignItems: 'center',
+ },
+ fab: {
+ width: 52,
+ height: 52,
+ borderRadius: 26,
+ backgroundColor: colors.scanButton,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+});
diff --git a/apps/frontend-mobile/app/(tabs)/alerts.tsx b/apps/frontend-mobile/app/(tabs)/alerts.tsx
new file mode 100644
index 0000000..0b9b7ea
--- /dev/null
+++ b/apps/frontend-mobile/app/(tabs)/alerts.tsx
@@ -0,0 +1,284 @@
+import React, { useEffect, useState } from 'react';
+import { View, Text, StyleSheet, FlatList, TouchableOpacity, Alert } from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import { colors, spacing, borderRadius, shadows } from '../../constants/theme';
+import { LoadingSpinner } from '../../components/LoadingSpinner';
+
+interface NotificationItem {
+ scope: string;
+ id: number;
+ medicine_name?: string;
+ medicine_nregistro?: string;
+ pharmacy_name?: string;
+ pharmacy_id?: number;
+ pharmacy_address?: string;
+ created_at?: string;
+}
+
+export default function AlertsScreen() {
+ const [items, setItems] = useState([]);
+ const [isLoading, setIsLoading] = useState(true);
+ const [error, setError] = useState(null);
+ const [deletingId, setDeletingId] = useState(null);
+
+ useEffect(() => {
+ loadNotifications();
+ }, []);
+
+ async function loadNotifications() {
+ setIsLoading(true);
+ setError(null);
+ try {
+ const res = await fetch('/api/notifications/mine', { credentials: 'include' });
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
+ const data = await res.json();
+ const merged = [
+ ...(data.pharmacy || []),
+ ...(data.global || []),
+ ].sort((a: NotificationItem, b: NotificationItem) =>
+ (b.created_at || '').localeCompare(a.created_at || '')
+ );
+ setItems(merged);
+ } catch (err: any) {
+ setError(err.message || 'No se pudieron cargar las notificaciones');
+ } finally {
+ setIsLoading(false);
+ }
+ }
+
+ async function handleDelete(item: NotificationItem) {
+ const key = `${item.scope}:${item.id}`;
+ Alert.alert(
+ 'Eliminar notificación',
+ `¿Eliminar la notificación de ${item.medicine_name || item.medicine_nregistro}?`,
+ [
+ { text: 'Cancelar', style: 'cancel' },
+ {
+ text: 'Eliminar',
+ style: 'destructive',
+ onPress: async () => {
+ setDeletingId(key);
+ try {
+ const res = await fetch('/api/notifications/mine', {
+ method: 'DELETE',
+ headers: { 'Content-Type': 'application/json' },
+ credentials: 'include',
+ body: JSON.stringify({ scope: item.scope, id: item.id }),
+ });
+ if (!res.ok && res.status !== 204) throw new Error(`HTTP ${res.status}`);
+ setItems(prev => prev.filter(i => !(i.scope === item.scope && i.id === item.id)));
+ } catch (err: any) {
+ Alert.alert('Error', err.message || 'No se pudo eliminar');
+ } finally {
+ setDeletingId(null);
+ }
+ },
+ },
+ ]
+ );
+ }
+
+ function renderItem({ item }: { item: NotificationItem }) {
+ const key = `${item.scope}:${item.id}`;
+ return (
+
+
+
+ {item.medicine_name || item.medicine_nregistro}
+
+
+
+
+
+ {item.scope === 'pharmacy'
+ ? item.pharmacy_name || `Farmacia #${item.pharmacy_id}`
+ : 'Cualquier farmacia'}
+
+
+ {item.pharmacy_address && (
+
+ {item.pharmacy_address}
+
+ )}
+
+
+ handleDelete(item)}
+ disabled={deletingId === key}
+ >
+ {deletingId === key ? (
+
+ ) : (
+
+ )}
+
+
+ );
+ }
+
+ if (isLoading) {
+ return ;
+ }
+
+ return (
+
+
+ Notificaciones Guardadas
+
+ Recibe avisos cuando medicamentos sin stock se repongan
+
+
+
+ {error && (
+
+ {error}
+
+ Reintentar
+
+
+ )}
+
+ {!error && items.length === 0 && (
+
+
+ Sin notificaciones
+
+ Toca la campana en una farmacia sin stock para recibir notificaciones cuando se reponga.
+
+
+ )}
+
+ {!error && items.length > 0 && (
+ `${item.scope}:${item.id}`}
+ renderItem={renderItem}
+ contentContainerStyle={styles.list}
+ showsVerticalScrollIndicator={false}
+ />
+ )}
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: colors.background,
+ },
+ header: {
+ paddingHorizontal: spacing.lg,
+ paddingTop: spacing.lg,
+ paddingBottom: spacing.md,
+ },
+ title: {
+ fontSize: 22,
+ fontWeight: 'bold',
+ color: colors.text,
+ },
+ subtitle: {
+ fontSize: 14,
+ color: colors.textSecondary,
+ marginTop: spacing.xs,
+ lineHeight: 20,
+ },
+ list: {
+ paddingHorizontal: spacing.lg,
+ paddingBottom: spacing.xl,
+ gap: spacing.sm,
+ },
+ item: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: colors.card,
+ borderRadius: borderRadius.lg,
+ padding: spacing.md,
+ ...shadows.card,
+ },
+ itemContent: {
+ flex: 1,
+ gap: spacing.xs,
+ },
+ itemName: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: colors.text,
+ lineHeight: 22,
+ },
+ itemMeta: {
+ gap: spacing.xs,
+ },
+ chip: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: spacing.xs,
+ backgroundColor: colors.primaryContainer,
+ borderRadius: borderRadius.full,
+ paddingHorizontal: spacing.sm,
+ paddingVertical: 3,
+ alignSelf: 'flex-start',
+ },
+ chipText: {
+ fontSize: 12,
+ fontWeight: '600',
+ color: colors.onPrimaryContainer,
+ },
+ itemAddress: {
+ fontSize: 12,
+ color: colors.textSecondary,
+ },
+ deleteButton: {
+ width: 36,
+ height: 36,
+ borderRadius: 18,
+ backgroundColor: colors.dangerContainer,
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginLeft: spacing.sm,
+ },
+ errorContainer: {
+ margin: spacing.lg,
+ padding: spacing.md,
+ backgroundColor: colors.dangerContainer,
+ borderRadius: borderRadius.lg,
+ alignItems: 'center',
+ gap: spacing.sm,
+ },
+ errorText: {
+ fontSize: 14,
+ color: colors.danger,
+ textAlign: 'center',
+ },
+ retryButton: {
+ paddingHorizontal: spacing.md,
+ paddingVertical: spacing.xs,
+ },
+ retryText: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: colors.primary,
+ },
+ emptyContainer: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ paddingHorizontal: spacing.xl,
+ gap: spacing.md,
+ },
+ emptyTitle: {
+ fontSize: 18,
+ fontWeight: '600',
+ color: colors.text,
+ },
+ emptyText: {
+ fontSize: 14,
+ color: colors.textSecondary,
+ textAlign: 'center',
+ lineHeight: 20,
+ },
+});
diff --git a/apps/frontend-mobile/app/(tabs)/home.tsx b/apps/frontend-mobile/app/(tabs)/home.tsx
new file mode 100644
index 0000000..d9f0c97
--- /dev/null
+++ b/apps/frontend-mobile/app/(tabs)/home.tsx
@@ -0,0 +1,137 @@
+import React from 'react';
+import { View, Text, StyleSheet, TouchableOpacity, Image } from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import { useRouter } from 'expo-router';
+import { colors, spacing, borderRadius, shadows } from '../../constants/theme';
+
+export default function HomeScreen() {
+ const router = useRouter();
+
+ return (
+
+
+
+ FarmaClic
+
+ Encuentra tus medicamentos en farmacias cercanas
+
+
+
+
+ router.push('/(tabs)')}
+ >
+
+
+
+
+ Buscar Medicamento
+
+
+
+
+ router.push('/scanner')}
+ >
+
+
+
+
+ Escanear TSI
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: colors.background,
+ alignItems: 'center',
+ justifyContent: 'center',
+ paddingHorizontal: spacing.lg,
+ gap: spacing.lg,
+ },
+ hero: {
+ alignItems: 'center',
+ gap: spacing.sm,
+ marginBottom: spacing.md,
+ },
+ logo: {
+ width: 120,
+ height: 120,
+ marginBottom: spacing.xs,
+ },
+ brandName: {
+ fontSize: 28,
+ fontWeight: 'bold',
+ color: colors.text,
+ letterSpacing: -0.5,
+ },
+ description: {
+ fontSize: 16,
+ color: colors.textSecondary,
+ textAlign: 'center',
+ maxWidth: 260,
+ lineHeight: 24,
+ },
+ cards: {
+ width: '100%',
+ maxWidth: 320,
+ gap: spacing.md,
+ },
+ card: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: spacing.md,
+ backgroundColor: colors.primaryContainer,
+ borderRadius: borderRadius.lg,
+ padding: spacing.md,
+ minHeight: 64,
+ ...shadows.card,
+ },
+ cardScan: {
+ backgroundColor: colors.scanButton,
+ },
+ cardIcon: {
+ width: 48,
+ height: 48,
+ borderRadius: borderRadius.md,
+ backgroundColor: 'rgba(255, 255, 255, 0.2)',
+ alignItems: 'center',
+ justifyContent: 'center',
+ flexShrink: 0,
+ },
+ cardIconSearch: {
+ backgroundColor: 'rgba(255, 255, 255, 0.3)',
+ },
+ cardIconScan: {
+ backgroundColor: 'rgba(255, 255, 255, 0.2)',
+ },
+ cardContent: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ },
+ cardLabel: {
+ fontSize: 18,
+ fontWeight: '700',
+ color: colors.onPrimaryContainer,
+ lineHeight: 24,
+ },
+ cardLabelScan: {
+ color: '#ffffff',
+ },
+});
diff --git a/apps/frontend-mobile/app/(tabs)/index.tsx b/apps/frontend-mobile/app/(tabs)/index.tsx
index 0db711b..ebe19f3 100644
--- a/apps/frontend-mobile/app/(tabs)/index.tsx
+++ b/apps/frontend-mobile/app/(tabs)/index.tsx
@@ -55,11 +55,11 @@ export default function HomeScreen() {
value={query}
onChangeText={setQuery}
/>
- router.push('/scanner')}
>
-
+
@@ -96,25 +96,34 @@ const styles = StyleSheet.create({
searchContainer: {
flexDirection: 'row',
alignItems: 'center',
+ paddingRight: spacing.lg,
},
scannerButton: {
- marginRight: spacing.md,
- padding: spacing.sm,
- backgroundColor: colors.card,
- borderRadius: borderRadius.md,
+ width: 44,
+ height: 44,
+ borderRadius: 22,
+ backgroundColor: colors.scanButton,
+ alignItems: 'center',
+ justifyContent: 'center',
+ shadowColor: '#2b5bb5',
+ shadowOffset: { width: 0, height: 4 },
+ shadowOpacity: 0.3,
+ shadowRadius: 12,
+ elevation: 6,
},
list: {
paddingBottom: spacing.xl,
},
errorContainer: {
padding: spacing.md,
- marginHorizontal: spacing.md,
- backgroundColor: '#F8D7DA',
- borderRadius: 8,
+ marginHorizontal: spacing.lg,
+ backgroundColor: colors.dangerContainer,
+ borderRadius: borderRadius.lg,
},
errorText: {
- color: '#721C24',
+ color: colors.danger,
textAlign: 'center',
+ fontSize: 14,
},
emptyContainer: {
padding: spacing.xl,
diff --git a/apps/frontend-mobile/app/(tabs)/map.tsx b/apps/frontend-mobile/app/(tabs)/map.tsx
index e663741..33c49ae 100644
--- a/apps/frontend-mobile/app/(tabs)/map.tsx
+++ b/apps/frontend-mobile/app/(tabs)/map.tsx
@@ -92,14 +92,14 @@ const styles = StyleSheet.create({
left: spacing.md,
right: spacing.md,
backgroundColor: colors.card,
- borderRadius: 8,
- padding: spacing.sm,
+ borderRadius: borderRadius.lg,
+ padding: spacing.sm + 4,
alignItems: 'center',
shadowColor: '#000',
- shadowOffset: { width: 0, height: 2 },
- shadowOpacity: 0.25,
- shadowRadius: 4,
- elevation: 5,
+ shadowOffset: { width: 0, height: 4 },
+ shadowOpacity: 0.08,
+ shadowRadius: 20,
+ elevation: 4,
},
legendText: {
fontSize: 14,
diff --git a/apps/frontend-mobile/app/(tabs)/profile.tsx b/apps/frontend-mobile/app/(tabs)/profile.tsx
index afb33ae..5d6c3c6 100644
--- a/apps/frontend-mobile/app/(tabs)/profile.tsx
+++ b/apps/frontend-mobile/app/(tabs)/profile.tsx
@@ -830,7 +830,7 @@ const styles = StyleSheet.create({
width: 100,
height: 100,
borderRadius: 50,
- backgroundColor: colors.background,
+ backgroundColor: colors.primaryContainer,
justifyContent: 'center',
alignItems: 'center',
overflow: 'hidden',
@@ -846,7 +846,7 @@ const styles = StyleSheet.create({
left: 0,
right: 0,
bottom: 0,
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
+ backgroundColor: 'rgba(0, 0, 0, 0.4)',
justifyContent: 'center',
alignItems: 'center',
opacity: 0.8,
@@ -857,17 +857,17 @@ const styles = StyleSheet.create({
fontSize: 14,
},
infoSection: {
- padding: spacing.xl,
+ padding: spacing.lg,
backgroundColor: colors.card,
- marginTop: spacing.md,
+ marginTop: spacing.sm,
gap: spacing.md,
},
infoCard: {
- backgroundColor: colors.background,
+ backgroundColor: colors.surfaceLow,
padding: spacing.md,
- borderRadius: borderRadius.md,
+ borderRadius: borderRadius.lg,
borderWidth: 1,
- borderColor: colors.border || '#E0E0E0',
+ borderColor: colors.border,
},
infoLabel: {
fontSize: 12,
@@ -883,7 +883,7 @@ const styles = StyleSheet.create({
color: colors.text,
},
menuSection: {
- marginTop: spacing.md,
+ marginTop: spacing.sm,
backgroundColor: colors.card,
},
menuItem: {
@@ -891,7 +891,7 @@ const styles = StyleSheet.create({
alignItems: 'center',
padding: spacing.md,
borderBottomWidth: 1,
- borderBottomColor: colors.separator,
+ borderBottomColor: colors.border,
},
menuText: {
flex: 1,
@@ -901,9 +901,9 @@ const styles = StyleSheet.create({
},
searchHistorySection: {
padding: spacing.md,
- backgroundColor: colors.background,
+ backgroundColor: colors.surfaceLow,
borderBottomWidth: 1,
- borderBottomColor: colors.separator,
+ borderBottomColor: colors.border,
},
searchHistoryTitle: {
fontSize: 14,
@@ -916,7 +916,7 @@ const styles = StyleSheet.create({
justifyContent: 'space-between',
paddingVertical: spacing.sm,
borderBottomWidth: 1,
- borderBottomColor: colors.separator,
+ borderBottomColor: colors.border,
},
searchAddress: {
flex: 1,
@@ -928,7 +928,7 @@ const styles = StyleSheet.create({
},
button: {
backgroundColor: colors.primary,
- borderRadius: borderRadius.md,
+ borderRadius: borderRadius.lg,
paddingVertical: spacing.md,
paddingHorizontal: spacing.xl,
},
@@ -951,7 +951,7 @@ const styles = StyleSheet.create({
margin: spacing.xl,
padding: spacing.md,
backgroundColor: colors.card,
- borderRadius: borderRadius.md,
+ borderRadius: borderRadius.lg,
borderWidth: 1,
borderColor: colors.danger,
},
@@ -979,7 +979,7 @@ const styles = StyleSheet.create({
justifyContent: 'space-between',
padding: spacing.lg,
borderBottomWidth: 1,
- borderBottomColor: colors.separator,
+ borderBottomColor: colors.border,
},
modalTitle: {
fontSize: 18,
@@ -1000,26 +1000,26 @@ const styles = StyleSheet.create({
},
modalInput: {
borderWidth: 1,
- borderColor: colors.border || '#E0E0E0',
- borderRadius: borderRadius.md,
+ borderColor: colors.border,
+ borderRadius: borderRadius.lg,
padding: spacing.md,
fontSize: 16,
color: colors.text,
},
modalFeedback: {
padding: spacing.md,
- borderRadius: borderRadius.md,
+ borderRadius: borderRadius.lg,
marginBottom: spacing.md,
},
modalFeedbackOk: {
- backgroundColor: 'rgba(0, 69, 13, 0.1)',
+ backgroundColor: '#eaf7ec',
borderWidth: 1,
- borderColor: 'rgba(0, 69, 13, 0.2)',
+ borderColor: '#cfead0',
},
modalFeedbackErr: {
- backgroundColor: 'rgba(186, 26, 26, 0.1)',
+ backgroundColor: colors.dangerContainer,
borderWidth: 1,
- borderColor: 'rgba(186, 26, 26, 0.2)',
+ borderColor: '#fecaca',
},
modalFeedbackText: {
fontSize: 14,
@@ -1034,9 +1034,9 @@ const styles = StyleSheet.create({
modalCancelBtn: {
paddingVertical: spacing.md,
paddingHorizontal: spacing.lg,
- borderRadius: borderRadius.md,
+ borderRadius: borderRadius.lg,
borderWidth: 1,
- borderColor: colors.border || '#E0E0E0',
+ borderColor: colors.border,
},
modalCancelText: {
fontSize: 16,
@@ -1046,7 +1046,7 @@ const styles = StyleSheet.create({
backgroundColor: colors.primary,
paddingVertical: spacing.md,
paddingHorizontal: spacing.xl,
- borderRadius: borderRadius.md,
+ borderRadius: borderRadius.lg,
minWidth: 100,
alignItems: 'center',
},
@@ -1068,7 +1068,7 @@ const styles = StyleSheet.create({
tabContainer: {
flexDirection: 'row',
borderBottomWidth: 1,
- borderBottomColor: colors.separator,
+ borderBottomColor: colors.border,
},
tabButton: {
flex: 1,
@@ -1115,10 +1115,10 @@ const styles = StyleSheet.create({
flexDirection: 'row',
alignItems: 'center',
padding: spacing.md,
- backgroundColor: colors.background,
- borderRadius: borderRadius.md,
+ backgroundColor: colors.surfaceLow,
+ borderRadius: borderRadius.lg,
borderWidth: 1,
- borderColor: colors.border || '#E5E5EA',
+ borderColor: colors.border,
},
uploadIconContainer: {
width: 56,
@@ -1155,14 +1155,14 @@ const styles = StyleSheet.create({
alignItems: 'flex-start',
justifyContent: 'space-between',
padding: spacing.md,
- backgroundColor: colors.background,
- borderRadius: borderRadius.md,
+ backgroundColor: colors.surfaceLow,
+ borderRadius: borderRadius.lg,
borderWidth: 1,
- borderColor: colors.border || '#E0E0E0',
+ borderColor: colors.border,
},
addressItemDefault: {
borderColor: colors.primary,
- backgroundColor: 'rgba(0, 69, 13, 0.03)',
+ backgroundColor: '#eaf7ec',
},
addressItemInfo: {
flex: 1,
@@ -1181,7 +1181,7 @@ const styles = StyleSheet.create({
addressBadge: {
alignSelf: 'flex-start',
backgroundColor: colors.primary,
- borderRadius: 12,
+ borderRadius: borderRadius.full,
paddingHorizontal: spacing.sm,
paddingVertical: 2,
marginTop: 4,
@@ -1219,9 +1219,9 @@ const styles = StyleSheet.create({
padding: spacing.md,
marginTop: spacing.md,
borderWidth: 2,
- borderColor: colors.border || '#E0E0E0',
+ borderColor: colors.border,
borderStyle: 'dashed',
- borderRadius: borderRadius.md,
+ borderRadius: borderRadius.lg,
},
addressAddBtnText: {
fontSize: 15,
diff --git a/apps/frontend-mobile/app/(tabs)/scan.tsx b/apps/frontend-mobile/app/(tabs)/scan.tsx
new file mode 100644
index 0000000..831aced
--- /dev/null
+++ b/apps/frontend-mobile/app/(tabs)/scan.tsx
@@ -0,0 +1,81 @@
+import React from 'react';
+import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import { useRouter } from 'expo-router';
+import { colors, spacing, borderRadius, shadows } from '../../constants/theme';
+
+export default function ScanTabScreen() {
+ const router = useRouter();
+
+ return (
+
+
+
+
+
+ Escanear TSI
+
+ Escanea el código de barras de tu tarjeta sanitaria para encontrar tus medicamentos
+
+ router.push('/scanner')}
+ >
+
+ Iniciar escaneo
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: colors.background,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ content: {
+ alignItems: 'center',
+ paddingHorizontal: spacing.xl,
+ gap: spacing.md,
+ },
+ iconContainer: {
+ width: 100,
+ height: 100,
+ borderRadius: 50,
+ backgroundColor: colors.primaryContainer,
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginBottom: spacing.sm,
+ },
+ title: {
+ fontSize: 22,
+ fontWeight: 'bold',
+ color: colors.text,
+ },
+ description: {
+ fontSize: 15,
+ color: colors.textSecondary,
+ textAlign: 'center',
+ lineHeight: 22,
+ maxWidth: 280,
+ },
+ button: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: spacing.sm,
+ backgroundColor: colors.scanButton,
+ borderRadius: borderRadius.lg,
+ paddingVertical: spacing.md,
+ paddingHorizontal: spacing.xl,
+ marginTop: spacing.md,
+ },
+ buttonText: {
+ fontSize: 17,
+ fontWeight: '600',
+ color: '#ffffff',
+ },
+});
diff --git a/apps/frontend-mobile/app/_layout.tsx b/apps/frontend-mobile/app/_layout.tsx
index b8039f4..77f4f42 100644
--- a/apps/frontend-mobile/app/_layout.tsx
+++ b/apps/frontend-mobile/app/_layout.tsx
@@ -5,6 +5,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { useAuthStore } from '../store/authStore';
import { registerForPushNotifications, addNotificationListener, addNotificationResponseListener } from '../services/notifications';
+import { colors } from '../constants/theme';
const queryClient = new QueryClient();
@@ -35,20 +36,27 @@ export default function RootLayout() {
return (
-
+
+