From a804a82512ae07be517f3edbd19d87b757493da7 Mon Sep 17 00:00:00 2001 From: Sergei Date: Fri, 12 Dec 2025 12:58:15 -0800 Subject: [PATCH] Implement Auth, Patients List, and Dashboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Features: - Login screen with API integration (credentials endpoint) - SecureStore for token management - Patients list with health data display - Patient dashboard with stats and quick actions - AI Chat screen (voice_ask API integration) - Profile screen with logout - Full error handling and loading states - WellNuo brand colors and UI components API Integration: - Base URL: eluxnetworks.net/function/well-api/api - Auth: function=credentials - Chat: function=voice_ask 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .gitignore | 1 + app/(auth)/_layout.tsx | 15 ++ app/(auth)/login.tsx | 210 +++++++++++++++++ app/(tabs)/_layout.tsx | 43 +++- app/(tabs)/chat.tsx | 321 ++++++++++++++++++++++++++ app/(tabs)/index.tsx | 379 ++++++++++++++++++++++++------- app/(tabs)/profile.tsx | 314 +++++++++++++++++++++++++ app/_layout.tsx | 50 +++- app/patients/[id]/index.tsx | 371 ++++++++++++++++++++++++++++++ app/patients/_layout.tsx | 15 ++ components/ui/Button.tsx | 137 +++++++++++ components/ui/ErrorMessage.tsx | 141 ++++++++++++ components/ui/Input.tsx | 143 ++++++++++++ components/ui/LoadingSpinner.tsx | 50 ++++ constants/theme.ts | 87 ++++++- contexts/AuthContext.tsx | 136 +++++++++++ package-lock.json | 58 +++++ package.json | 10 +- services/api.ts | 194 ++++++++++++++++ types/index.ts | 70 ++++++ 20 files changed, 2634 insertions(+), 111 deletions(-) create mode 100644 app/(auth)/_layout.tsx create mode 100644 app/(auth)/login.tsx create mode 100644 app/(tabs)/chat.tsx create mode 100644 app/(tabs)/profile.tsx create mode 100644 app/patients/[id]/index.tsx create mode 100644 app/patients/_layout.tsx create mode 100644 components/ui/Button.tsx create mode 100644 components/ui/ErrorMessage.tsx create mode 100644 components/ui/Input.tsx create mode 100644 components/ui/LoadingSpinner.tsx create mode 100644 contexts/AuthContext.tsx create mode 100644 services/api.ts create mode 100644 types/index.ts diff --git a/.gitignore b/.gitignore index f8c6c2e..2a6edee 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ app-example # generated native folders /ios /android +.git-credentials diff --git a/app/(auth)/_layout.tsx b/app/(auth)/_layout.tsx new file mode 100644 index 0000000..9ac3ffe --- /dev/null +++ b/app/(auth)/_layout.tsx @@ -0,0 +1,15 @@ +import { Stack } from 'expo-router'; +import { AppColors } from '@/constants/theme'; + +export default function AuthLayout() { + return ( + + + + ); +} diff --git a/app/(auth)/login.tsx b/app/(auth)/login.tsx new file mode 100644 index 0000000..ed77ae5 --- /dev/null +++ b/app/(auth)/login.tsx @@ -0,0 +1,210 @@ +import React, { useState, useCallback } from 'react'; +import { + View, + Text, + StyleSheet, + KeyboardAvoidingView, + Platform, + ScrollView, + TouchableOpacity, + Image, +} from 'react-native'; +import { router } from 'expo-router'; +import { useAuth } from '@/contexts/AuthContext'; +import { Button } from '@/components/ui/Button'; +import { Input } from '@/components/ui/Input'; +import { ErrorMessage } from '@/components/ui/ErrorMessage'; +import { AppColors, BorderRadius, FontSizes, Spacing } from '@/constants/theme'; + +export default function LoginScreen() { + const { login, isLoading, error, clearError } = useAuth(); + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + const [validationError, setValidationError] = useState(null); + + const handleLogin = useCallback(async () => { + // Clear previous errors + clearError(); + setValidationError(null); + + // Validate + if (!username.trim()) { + setValidationError('Username is required'); + return; + } + if (!password.trim()) { + setValidationError('Password is required'); + return; + } + + const success = await login({ username: username.trim(), password }); + + if (success) { + router.replace('/(tabs)'); + } + }, [username, password, login, clearError]); + + const displayError = validationError || error?.message; + + return ( + + + {/* Logo / Header */} + + + WellNuo + + Welcome Back + Sign in to continue monitoring your loved ones + + + {/* Form */} + + {displayError && ( + { + clearError(); + setValidationError(null); + }} + /> + )} + + { + setUsername(text); + setValidationError(null); + }} + autoCapitalize="none" + autoCorrect={false} + editable={!isLoading} + /> + + { + setPassword(text); + setValidationError(null); + }} + editable={!isLoading} + onSubmitEditing={handleLogin} + returnKeyType="done" + /> + + + Forgot Password? + + +