Scaffold React Native mobile project (Phase 6)

React Native CLI 0.79 with React 19, TypeScript, Metro monorepo config,
and React Native Paper + Navigation + Redux Toolkit + TanStack Query deps.
Native ios/ and android/ directories deferred to macOS environment.
This commit is contained in:
Adam Moussa 2026-05-17 15:09:06 -04:00
parent f051f74fde
commit 04d28cd793
8 changed files with 99 additions and 2 deletions

15
.gitignore vendored
View file

@ -41,5 +41,20 @@ Thumbs.db
coverage/ coverage/
TestResults/ TestResults/
# React Native / Mobile
mobile/ios/Pods/
mobile/ios/build/
mobile/android/.gradle/
mobile/android/app/build/
mobile/android/build/
*.xcworkspace
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
xcuserdata/
*.hmap
*.ipa
# Build artifacts # Build artifacts
*.zip *.zip

8
mobile/.env.example Normal file
View file

@ -0,0 +1,8 @@
# API
API_URL=https://api.proposals.seahaven.com/api
# Cognito (set after CDK deployment)
COGNITO_DOMAIN=proposal-system.auth.us-east-1.amazoncognito.com
COGNITO_CLIENT_ID=
COGNITO_USER_POOL_ID=
COGNITO_REDIRECT_URI=com.seahavenind.proposals://auth/callback

4
mobile/app.json Normal file
View file

@ -0,0 +1,4 @@
{
"name": "ProposalSystem",
"displayName": "Sea Haven Proposals"
}

3
mobile/babel.config.js Normal file
View file

@ -0,0 +1,3 @@
module.exports = {
presets: ['module:@react-native/babel-preset'],
};

5
mobile/index.js Normal file
View file

@ -0,0 +1,5 @@
import { AppRegistry } from 'react-native';
import App from './src/App';
import { name as appName } from './app.json';
AppRegistry.registerComponent(appName, () => App);

17
mobile/metro.config.js Normal file
View file

@ -0,0 +1,17 @@
const path = require('path');
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const projectRoot = __dirname;
const monorepoRoot = path.resolve(projectRoot, '..');
const config = {
watchFolders: [path.resolve(monorepoRoot, 'shared')],
resolver: {
nodeModulesPaths: [
path.resolve(projectRoot, 'node_modules'),
path.resolve(monorepoRoot, 'node_modules'),
],
},
};
module.exports = mergeConfig(getDefaultConfig(projectRoot), config);

View file

@ -4,13 +4,37 @@
"private": true, "private": true,
"scripts": { "scripts": {
"start": "react-native start", "start": "react-native start",
"ios": "react-native run-ios" "ios": "react-native run-ios",
"android": "react-native run-android",
"typecheck": "tsc --noEmit"
}, },
"dependencies": { "dependencies": {
"@proposal-system/api-contracts": "file:../shared/api-contracts",
"@react-native-async-storage/async-storage": "^2.1.0",
"@react-native-community/netinfo": "^11.4.0",
"@react-navigation/bottom-tabs": "^7.2.0",
"@react-navigation/native": "^7.0.0",
"@react-navigation/native-stack": "^7.2.0",
"@reduxjs/toolkit": "^2.11.2",
"@tanstack/react-query": "^5.100.10",
"axios": "^1.16.0",
"react": "^19.0.0", "react": "^19.0.0",
"react-native": "^0.76.0" "react-native": "^0.79.0",
"react-native-app-auth": "^8.0.0",
"react-native-document-picker": "^9.3.0",
"react-native-haptic-feedback": "^2.3.0",
"react-native-image-picker": "^7.2.0",
"react-native-keychain": "^9.2.0",
"react-native-paper": "^5.13.0",
"react-native-safe-area-context": "^5.0.0",
"react-native-screens": "^4.5.0",
"react-native-share": "^11.0.0",
"react-native-vector-icons": "^10.2.0",
"react-redux": "^9.2.0"
}, },
"devDependencies": { "devDependencies": {
"@react-native/babel-preset": "^0.79.0",
"@react-native/metro-config": "^0.79.0",
"@types/react": "^19.0.0", "@types/react": "^19.0.0",
"typescript": "~5.7.0" "typescript": "~5.7.0"
} }

21
mobile/tsconfig.json Normal file
View file

@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"jsx": "react-jsx",
"esModuleInterop": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"allowJs": true,
"outDir": "./dist",
"rootDir": ".",
"baseUrl": ".",
"paths": {
"@proposal-system/api-contracts": ["../shared/api-contracts/src"]
}
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}