fix(mobile): correct asset logo path depth and add expo-router app/ routes for web support

- Fix fatal crash: require('../../../assets/logo.png') in LoginScreen and
  WelcomeScreen resolved 3 levels above mobile/src/screens/ — outside the
  mobile/ directory. Changed to ../../assets/logo.png which correctly
  resolves to the existing mobile/assets/logo.png.
- Add expo-router app/ directory (root cause of missing welcome screen and
  web support): app/_layout.tsx, (auth)/, (tabs)/ with all route files
- Add WelcomeScreen.tsx: branded intro screen with feature highlights
- Update LoginScreen/WelcomeScreen to use useRouter() (expo-router style)
- Add react-native-web ~0.20.0 and react-dom 19.2.4 for web channel
- Add expo-device ~7.0.3 (was imported but missing from package.json)
- Remove android.googleServicesFile from app.json (file is gitignored;
  README documents how to restore it for Android FCM builds)
- Add web.bundler: metro and web.output: single to app.json
- Fix aria-hidden to explicit boolean value in WelcomeScreen

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-15 16:02:02 +00:00
parent a2de72ab72
commit 82d90b48e2
15 changed files with 467 additions and 179 deletions
+5 -9
View File
@@ -6,7 +6,7 @@
* AuthContext stores the API token and navigates to the main app.
*/
import type { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { useRouter } from "expo-router";
import React, { useState } from "react";
import {
ActivityIndicator,
@@ -21,14 +21,10 @@ import {
View,
} from "react-native";
import { useAuth } from "../context/AuthContext";
import type { AuthStackParamList } from "./WelcomeScreen";
type LoginScreenProps = {
navigation: NativeStackNavigationProp<AuthStackParamList, "Login">;
};
export default function LoginScreen({ navigation }: LoginScreenProps) {
export default function LoginScreen() {
const { signIn } = useAuth();
const router = useRouter();
const [serverUrl, setServerUrl] = useState("");
const [loading, setLoading] = useState(false);
@@ -62,7 +58,7 @@ export default function LoginScreen({ navigation }: LoginScreenProps) {
<View style={styles.card}>
<View style={styles.logoContainer}>
<Image
source={require("../../../assets/logo.png")}
source={require("../../assets/logo.png")}
style={styles.logoImage}
resizeMode="contain"
accessibilityLabel="DocuElevate logo"
@@ -105,7 +101,7 @@ export default function LoginScreen({ navigation }: LoginScreenProps) {
</Text>
<Pressable
onPress={() => navigation.navigate("Welcome")}
onPress={() => router.back()}
accessibilityRole="button"
accessibilityLabel="Back to welcome screen"
style={styles.backLink}
+6 -14
View File
@@ -5,7 +5,7 @@
* and a "Get Started" button that navigates to the LoginScreen.
*/
import type { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { useRouter } from "expo-router";
import React from "react";
import {
Image,
@@ -17,15 +17,6 @@ import {
View,
} from "react-native";
export type AuthStackParamList = {
Welcome: undefined;
Login: undefined;
};
type WelcomeScreenProps = {
navigation: NativeStackNavigationProp<AuthStackParamList, "Welcome">;
};
const FEATURES: { icon: string; title: string; description: string }[] = [
{
icon: "🔍",
@@ -44,7 +35,8 @@ const FEATURES: { icon: string; title: string; description: string }[] = [
},
];
export default function WelcomeScreen({ navigation }: WelcomeScreenProps) {
export default function WelcomeScreen() {
const router = useRouter();
return (
<SafeAreaView style={styles.safe}>
<ScrollView
@@ -55,7 +47,7 @@ export default function WelcomeScreen({ navigation }: WelcomeScreenProps) {
<View style={styles.hero}>
<View style={styles.logoContainer}>
<Image
source={require("../../../assets/logo.png")}
source={require("../../assets/logo.png")}
style={styles.logoImage}
resizeMode="contain"
accessibilityLabel="DocuElevate logo"
@@ -73,7 +65,7 @@ export default function WelcomeScreen({ navigation }: WelcomeScreenProps) {
<View style={styles.features}>
{FEATURES.map((feature) => (
<View key={feature.title} style={styles.featureRow}>
<Text style={styles.featureIcon} aria-hidden>{feature.icon}</Text>
<Text style={styles.featureIcon} aria-hidden={true}>{feature.icon}</Text>
<View style={styles.featureText}>
<Text style={styles.featureTitle}>{feature.title}</Text>
<Text style={styles.featureDescription}>{feature.description}</Text>
@@ -85,7 +77,7 @@ export default function WelcomeScreen({ navigation }: WelcomeScreenProps) {
{/* CTA */}
<Pressable
style={({ pressed }) => [styles.button, pressed && styles.buttonPressed]}
onPress={() => navigation.navigate("Login")}
onPress={() => router.push("/(auth)/login")}
accessibilityRole="button"
accessibilityLabel="Get started — connect to your DocuElevate server"
>