feat: Integrate Expo mobile application into monorepo (#16)

- Add mobile/ directory with Expo React Native project
- Create API client with JWT auth and token refresh using AsyncStorage
- Implement AuthContext for login/register/logout flow
- Add screens: Login, Register, Library, Search, Settings
- Set up React Navigation with AuthStack and MainTabs
- Create packages/shared/ with shared types and utilities
- Add shared validation utilities (email, password strength)
- Update root package.json workspaces to include mobile + shared
- Add spec document docs/backend/009-expo-integration.md
This commit is contained in:
Marko (Hermes Implementer)
2026-05-29 02:50:09 +00:00
parent 332b539880
commit fa82fab44a
36 changed files with 2051 additions and 4 deletions
+68
View File
@@ -0,0 +1,68 @@
import React from "react";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { Text } from "react-native";
import LibraryScreen from "../screens/LibraryScreen";
import SearchScreen from "../screens/SearchScreen";
import SettingsScreen from "../screens/SettingsScreen";
export type MainTabParamList = {
Library: undefined;
Search: undefined;
Settings: undefined;
};
const Tab = createBottomTabNavigator<MainTabParamList>();
function TabIcon({ label, focused }: { label: string; focused: boolean }) {
const icons: Record<string, string> = {
Library: "📚",
Search: "🔍",
Settings: "⚙️",
};
return (
<Text style={{ fontSize: 22, opacity: focused ? 1 : 0.5 }}>
{icons[label] ?? "●"}
</Text>
);
}
export function MainNavigator() {
return (
<Tab.Navigator
screenOptions={{
headerStyle: { backgroundColor: "#fff" },
headerTitleStyle: { fontWeight: "600", color: "#1a1a2e" },
tabBarActiveTintColor: "#4a6cf7",
tabBarInactiveTintColor: "#999",
}}
>
<Tab.Screen
name="Library"
component={LibraryScreen}
options={{
tabBarIcon: ({ focused }) => (
<TabIcon label="Library" focused={focused} />
),
}}
/>
<Tab.Screen
name="Search"
component={SearchScreen}
options={{
tabBarIcon: ({ focused }) => (
<TabIcon label="Search" focused={focused} />
),
}}
/>
<Tab.Screen
name="Settings"
component={SettingsScreen}
options={{
tabBarIcon: ({ focused }) => (
<TabIcon label="Settings" focused={focused} />
),
}}
/>
</Tab.Navigator>
);
}