initial commit
22
ev_station/.gitignore
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
node_modules/
|
||||
.expo/
|
||||
dist/
|
||||
npm-debug.*
|
||||
*.jks
|
||||
*.p8
|
||||
*.p12
|
||||
*.key
|
||||
*.mobileprovision
|
||||
*.orig.*
|
||||
web-build/
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
||||
# @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb
|
||||
# The following patterns were generated by expo-cli
|
||||
|
||||
expo-env.d.ts
|
||||
# @end expo-cli
|
||||
|
||||
.env
|
50
ev_station/README.md
Normal file
|
@ -0,0 +1,50 @@
|
|||
# Welcome to your Expo app 👋
|
||||
|
||||
This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
|
||||
|
||||
## Get started
|
||||
|
||||
1. Install dependencies
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
2. Start the app
|
||||
|
||||
```bash
|
||||
npx expo start
|
||||
```
|
||||
|
||||
In the output, you'll find options to open the app in a
|
||||
|
||||
- [development build](https://docs.expo.dev/develop/development-builds/introduction/)
|
||||
- [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/)
|
||||
- [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/)
|
||||
- [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo
|
||||
|
||||
You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction).
|
||||
|
||||
## Get a fresh project
|
||||
|
||||
When you're ready, run:
|
||||
|
||||
```bash
|
||||
npm run reset-project
|
||||
```
|
||||
|
||||
This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing.
|
||||
|
||||
## Learn more
|
||||
|
||||
To learn more about developing your project with Expo, look at the following resources:
|
||||
|
||||
- [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides).
|
||||
- [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web.
|
||||
|
||||
## Join the community
|
||||
|
||||
Join our community of developers creating universal apps.
|
||||
|
||||
- [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute.
|
||||
- [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions.
|
42
ev_station/app.json
Normal file
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"expo": {
|
||||
"name": "ev_station",
|
||||
"slug": "ev_station",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/images/icon.png",
|
||||
"scheme": "myapp",
|
||||
"userInterfaceStyle": "automatic",
|
||||
"splash": {
|
||||
"image": "./assets/images/splash.png",
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"ios": {
|
||||
"supportsTablet": true
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/images/adaptive-icon.png",
|
||||
"backgroundColor": "#ffffff"
|
||||
}
|
||||
},
|
||||
"web": {
|
||||
"bundler": "metro",
|
||||
"output": "static",
|
||||
"favicon": "./assets/images/favicon.png"
|
||||
},
|
||||
"plugins": [
|
||||
[
|
||||
"expo-location",
|
||||
{
|
||||
"locationAlwaysAndWhenInUsePermission": "Allow ev_station to use your location."
|
||||
}
|
||||
],
|
||||
"expo-router"
|
||||
],
|
||||
"experiments": {
|
||||
"typedRoutes": true
|
||||
}
|
||||
}
|
||||
}
|
3
ev_station/app/Context/UserLocationContext.jsx
Normal file
|
@ -0,0 +1,3 @@
|
|||
import { createContext } from "react";
|
||||
|
||||
export const UserLocationContext = createContext(null);
|
60
ev_station/app/Navigation/HomeNavigator.jsx
Normal file
|
@ -0,0 +1,60 @@
|
|||
import { View, Text, StyleSheet } from 'react-native'
|
||||
import React from 'react'
|
||||
import {createBottomTabNavigator} from "@react-navigation/bottom-tabs";
|
||||
import HomeScreen from "../screen/HomeScreen"
|
||||
import SaveScreen from "../screen/SaveScreen"
|
||||
import ProfileScreen from "../screen/ProfileScreen"
|
||||
import {Entypo, MaterialIcons, AntDesign} from '@expo/vector-icons';
|
||||
|
||||
|
||||
const Tab = createBottomTabNavigator();
|
||||
|
||||
const HomeNavigator = () => {
|
||||
return (
|
||||
<Tab.Navigator screenOptions={{headerShown: false, tabBarHideOnKeyboard: true}}>
|
||||
<Tab.Screen name='home' component={HomeScreen}
|
||||
options={{
|
||||
tabBarLabel: "Home",
|
||||
tabBarActiveTintColor: '#379777',
|
||||
tabBarInactiveTintColor: 'gray',
|
||||
tabBarIcon:({focused}) =>
|
||||
focused? (
|
||||
<Entypo name="home" size={26} color="#379777" style={{marginTop: 5, marginBottom: 5}}/>
|
||||
) : (
|
||||
<Entypo name="home" size={26} color="gray" style={{marginTop: 5, marginBottom: 5}}/>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Tab.Screen name='save' component={SaveScreen}
|
||||
options={{
|
||||
tabBarLabel: "Save",
|
||||
tabBarActiveTintColor: '#379777',
|
||||
tabBarInactiveTintColor: 'gray',
|
||||
tabBarIcon:({focused}) =>
|
||||
focused? (
|
||||
<MaterialIcons name="data-saver-on" size={26} color="#379777" style={{marginTop: 5, marginBottom: 5}}/>
|
||||
) : (
|
||||
<MaterialIcons name="data-saver-on" size={26} color="gray" style={{marginTop: 5, marginBottom: 5}}/>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Tab.Screen name='profile' component={ProfileScreen}
|
||||
options={{
|
||||
tabBarLabel: "Profile",
|
||||
tabBarActiveTintColor: '#379777',
|
||||
tabBarInactiveTintColor: 'gray',
|
||||
tabBarIcon:({focused}) =>
|
||||
focused? (
|
||||
<AntDesign name="user" size={26} color="#379777" style={{marginTop: 5, marginBottom: 5}}/>
|
||||
) : (
|
||||
<AntDesign name="user" size={26} color="gray" style={{marginTop: 5, marginBottom: 5}}/>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Tab.Navigator>
|
||||
)
|
||||
}
|
||||
|
||||
export default HomeNavigator
|
||||
|
||||
const styles = StyleSheet.create({})
|
76
ev_station/app/index.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
import { StatusBar } from "expo-status-bar";
|
||||
import { View, Text } from "react-native";
|
||||
import Login from "./screen/loginScreen/Login";
|
||||
import { ClerkProvider, SignedIn, SignedOut } from '@clerk/clerk-expo';
|
||||
import *as SecureStore from "expo-secure-store";
|
||||
import * as Location from 'expo-location';
|
||||
import { NavigationContainer } from "@react-navigation/native";
|
||||
import HomeNavigator from "./Navigation/HomeNavigator";
|
||||
import { useEffect, useState } from "react";
|
||||
import { UserLocationContext } from "../app/Context/UserLocationContext";
|
||||
|
||||
|
||||
const tokenCache = {
|
||||
async getToken(key){
|
||||
try {
|
||||
return SecureStore.getItemAsync(key);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async saveToken(key, value){
|
||||
try {
|
||||
return SecureStore.setItemAsync(key, value);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
export default function Index() {
|
||||
const PUBLIC_KEY = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY;
|
||||
|
||||
//use current location
|
||||
const [location, setLocation] = useState(null);
|
||||
const [errorMsg, setErrorMsg] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
|
||||
let { status } = await Location.requestForegroundPermissionsAsync();
|
||||
if (status !== 'granted') {
|
||||
setErrorMsg('Permission to access location was denied');
|
||||
return;
|
||||
}
|
||||
|
||||
let location = await Location.getCurrentPositionAsync({});
|
||||
setLocation(location.coords);
|
||||
})();
|
||||
}, []);
|
||||
|
||||
let text = 'Waiting..';
|
||||
if (errorMsg) {
|
||||
text = errorMsg;
|
||||
} else if (location) {
|
||||
text = JSON.stringify(location);
|
||||
}
|
||||
|
||||
return (
|
||||
<ClerkProvider tokenCache={tokenCache} publishableKey={PUBLIC_KEY}>
|
||||
<UserLocationContext.Provider value={{location, setLocation}}>
|
||||
<View style={{flex: 1, backgroundColor: 'white'}}>
|
||||
<StatusBar style="auto"/>
|
||||
<SignedIn>
|
||||
<NavigationContainer independent={true}>
|
||||
<HomeNavigator />
|
||||
</NavigationContainer>
|
||||
</SignedIn>
|
||||
<SignedOut>
|
||||
<Login/>
|
||||
</SignedOut>
|
||||
</View>
|
||||
</UserLocationContext.Provider>
|
||||
</ClerkProvider>
|
||||
);
|
||||
}
|
19
ev_station/app/screen/HomeHeader.jsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { Image, StyleSheet, Text, View } from 'react-native'
|
||||
import React from 'react'
|
||||
import { useUser } from '@clerk/clerk-expo';
|
||||
|
||||
const HomeHeader = () => {
|
||||
const {user} = useUser();
|
||||
return (
|
||||
<View style={{backgroundColor: 'white', paddingHorizontal: 20, paddingVertical: 10}}>
|
||||
<View style={{flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
|
||||
<Image source={require('../../assets/images/ev_images/EV.png')} style={{width: 120, height: 60, objectFit: 'contain'}}/>
|
||||
<Image source={{uri: user?.imageUrl}} style={{width: 40, height: 40, borderRadius: '50%'}}/>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default HomeHeader
|
||||
|
||||
const styles = StyleSheet.create({})
|
24
ev_station/app/screen/HomeScreen.jsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { Image, Pressable, StyleSheet, Text, View } from 'react-native';
|
||||
import React from 'react';
|
||||
import MapViewScreen from "../screen/mapView/MapViewScreen";
|
||||
|
||||
import HomeHeader from './HomeHeader';
|
||||
import HomeSearch from './HomeSearch';
|
||||
|
||||
const HomeScreen = () => {
|
||||
|
||||
return (
|
||||
<View style={{flex: 1, backgroundColor: 'white'}}>
|
||||
<View style={{position: 'absolute', zIndex: 10, width: '100%'}}>
|
||||
<HomeHeader />
|
||||
<HomeSearch searchedLocation={(location) => console.log(location)}/>
|
||||
</View>
|
||||
<MapViewScreen />
|
||||
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default HomeScreen
|
||||
|
||||
const styles = StyleSheet.create({})
|
34
ev_station/app/screen/HomeSearch.jsx
Normal file
|
@ -0,0 +1,34 @@
|
|||
import { StyleSheet, Text, View } from 'react-native'
|
||||
import React from 'react'
|
||||
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
|
||||
|
||||
|
||||
const mapApiKey = process.env.EXPO_PUBLIC_GOOGLE_PLACE_API_KEY;
|
||||
|
||||
const HomeSearch = ({searchedLocation}) => {
|
||||
|
||||
return (
|
||||
<View style={{marginVertical: 10, marginHorizontal: 10, borderRadius: 5}}>
|
||||
<GooglePlacesAutocomplete
|
||||
placeholder='Search EV charging station'
|
||||
textInputProps={{
|
||||
placeholderTextColor: '#45474B'
|
||||
}}
|
||||
enablePoweredByContainer={false}
|
||||
fetchDetails={true}
|
||||
onPress={(data, details = null) => {
|
||||
searchedLocation(details?.geometry?.location)
|
||||
}}
|
||||
query={{
|
||||
key: mapApiKey,
|
||||
language: 'en',
|
||||
}}
|
||||
onFail={error => console.error(error)}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default HomeSearch
|
||||
|
||||
const styles = StyleSheet.create({})
|
16
ev_station/app/screen/ProfileScreen.jsx
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { StyleSheet, Text, View } from 'react-native'
|
||||
import React from 'react'
|
||||
|
||||
const ProfileScreen = () => {
|
||||
return (
|
||||
<View style={{flex: 1, backgroundColor: 'white'}}>
|
||||
<View style={{margin: 20}}>
|
||||
<Text>ProfileScreen</Text>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProfileScreen
|
||||
|
||||
const styles = StyleSheet.create({})
|
16
ev_station/app/screen/SaveScreen.jsx
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { StyleSheet, Text, View } from 'react-native'
|
||||
import React from 'react'
|
||||
|
||||
const SaveScreen = () => {
|
||||
return (
|
||||
<View style={{flex: 1, backgroundColor: 'white'}}>
|
||||
<View style={{margin: 20}}>
|
||||
<Text>SaveScreen</Text>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default SaveScreen
|
||||
|
||||
const styles = StyleSheet.create({})
|
42
ev_station/app/screen/loginScreen/Login.jsx
Normal file
|
@ -0,0 +1,42 @@
|
|||
import { Image, Pressable, StyleSheet, Text, View } from 'react-native'
|
||||
import React from 'react';
|
||||
import *as WebBrowser from "expo-web-browser";
|
||||
import { useOAuth } from '@clerk/clerk-expo';
|
||||
import { useWarmUpBrowser } from '../../../hooks/warmUpBrowser'
|
||||
|
||||
|
||||
WebBrowser.maybeCompleteAuthSession();
|
||||
const Login = () => {
|
||||
useWarmUpBrowser();
|
||||
const {startOAuthFlow} = useOAuth({strategy: "oauth_google"})
|
||||
|
||||
const loginHandler = async() => {
|
||||
try {
|
||||
const {createdSessionId, signIn, signUp, setActive} = await startOAuthFlow();
|
||||
if(createdSessionId){
|
||||
setActive({session: createdSessionId});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("oAuth error");
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={{flex:1, justifyContent: 'center', alignItems: 'center'}}>
|
||||
<Image source={require('../../../assets/images/ev_images/EV.png')}/>
|
||||
<View style={{padding: 20, marginVertical: 10}}>
|
||||
<Text style={{fontSize: 24, textAlign: 'center', paddingHorizontal: 5, fontWeight: 600, color: '#45474B'}}>Find reliable EV charging stations near you just one click</Text>
|
||||
<Pressable onPress={loginHandler} style={{marginVertical: 50}}>
|
||||
<View style={{justifyContent: 'center', alignItems: 'center', padding: 10, backgroundColor: '#379777', marginHorizontal: 100, borderRadius: 5}}>
|
||||
<Text style={{fontSize: 20, fontWeight: 500, color: 'white'}}>Start</Text>
|
||||
</View>
|
||||
</Pressable>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default Login
|
||||
|
||||
const styles = StyleSheet.create({})
|
33
ev_station/app/screen/mapView/MapViewScreen.jsx
Normal file
|
@ -0,0 +1,33 @@
|
|||
import { Image, StyleSheet, Text, View } from 'react-native';
|
||||
import React, { useContext } from 'react';
|
||||
import MapView, { Marker, PROVIDER_DEFAULT} from 'react-native-maps';
|
||||
import { UserLocationContext } from '@/app/Context/UserLocationContext';
|
||||
|
||||
|
||||
const MapViewScreen = () => {
|
||||
const {location, setLocation} = useContext(UserLocationContext)
|
||||
|
||||
|
||||
return location?.latitude &&(
|
||||
<View>
|
||||
<MapView style={{width: '100%', height: '100%'}}
|
||||
provider={PROVIDER_DEFAULT}
|
||||
showsUserLocation={true}
|
||||
region={{
|
||||
latitude: location?.latitude,
|
||||
longitude: location?.longitude,
|
||||
latitudeDelta: 0.05,
|
||||
longitudeDelta: 0.05
|
||||
}}
|
||||
>
|
||||
<Marker coordinate={{latitude: location?.latitude, longitude: location?.longitude}}>
|
||||
<Image source={require('../../../assets/images/ev_images/car.png')} style={{width: 70, height: 70}}/>
|
||||
</Marker>
|
||||
</MapView>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default MapViewScreen
|
||||
|
||||
const styles = StyleSheet.create({})
|
BIN
ev_station/assets/fonts/SpaceMono-Regular.ttf
Executable file
BIN
ev_station/assets/images/adaptive-icon.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
ev_station/assets/images/ev_images/EV.png
Normal file
After Width: | Height: | Size: 8 KiB |
BIN
ev_station/assets/images/ev_images/car.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
ev_station/assets/images/ev_images/charging-station.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
ev_station/assets/images/favicon.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
ev_station/assets/images/icon.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
ev_station/assets/images/partial-react-logo.png
Normal file
After Width: | Height: | Size: 5 KiB |
BIN
ev_station/assets/images/react-logo.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
ev_station/assets/images/react-logo@2x.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
ev_station/assets/images/react-logo@3x.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
ev_station/assets/images/splash.png
Normal file
After Width: | Height: | Size: 46 KiB |
6
ev_station/babel.config.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
module.exports = function (api) {
|
||||
api.cache(true);
|
||||
return {
|
||||
presets: ['babel-preset-expo'],
|
||||
};
|
||||
};
|
11
ev_station/hooks/warmUpBrowser.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import *as WebBrowser from "expo-web-browser";
|
||||
|
||||
export const useWarmUpBrowser = () => {
|
||||
React.useEffect(() => {
|
||||
void WebBrowser.warmUpAsync();
|
||||
return() => {
|
||||
void WebBrowser.coolDownAsync();
|
||||
}
|
||||
}, [])
|
||||
};
|
18742
ev_station/package-lock.json
generated
Normal file
55
ev_station/package.json
Normal file
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"name": "ev_station",
|
||||
"main": "expo-router/entry",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
"reset-project": "node ./scripts/reset-project.js",
|
||||
"android": "expo start --android",
|
||||
"ios": "expo start --ios",
|
||||
"web": "expo start --web",
|
||||
"test": "jest --watchAll",
|
||||
"lint": "expo lint"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "jest-expo"
|
||||
},
|
||||
"dependencies": {
|
||||
"@clerk/clerk-expo": "^2.0.0",
|
||||
"@expo/vector-icons": "^14.0.2",
|
||||
"@react-navigation/native": "^6.1.18",
|
||||
"expo": "~51.0.22",
|
||||
"expo-constants": "~16.0.2",
|
||||
"expo-font": "~12.0.9",
|
||||
"expo-linking": "~6.3.1",
|
||||
"expo-location": "~17.0.1",
|
||||
"expo-router": "~3.5.18",
|
||||
"expo-secure-store": "^13.0.2",
|
||||
"expo-splash-screen": "~0.27.5",
|
||||
"expo-status-bar": "~1.12.1",
|
||||
"expo-system-ui": "~3.0.7",
|
||||
"expo-web-browser": "~13.0.3",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-native": "0.74.3",
|
||||
"react-native-gesture-handler": "~2.16.1",
|
||||
"react-native-google-places-autocomplete": "^2.5.6",
|
||||
"react-native-maps": "1.14.0",
|
||||
"react-native-places-input": "^1.1.7",
|
||||
"react-native-reanimated": "~3.10.1",
|
||||
"react-native-safe-area-context": "4.10.5",
|
||||
"react-native-screens": "3.31.1",
|
||||
"react-native-web": "~0.19.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/react": "~18.2.45",
|
||||
"@types/react-test-renderer": "^18.0.7",
|
||||
"jest": "^29.2.1",
|
||||
"jest-expo": "~51.0.3",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"typescript": "~5.3.3"
|
||||
},
|
||||
"private": true
|
||||
}
|
73
ev_station/scripts/reset-project.js
Executable file
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* This script is used to reset the project to a blank state.
|
||||
* It moves the /app directory to /app-example and creates a new /app directory with an index.tsx and _layout.tsx file.
|
||||
* You can remove the `reset-project` script from package.json and safely delete this file after running it.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const root = process.cwd();
|
||||
const oldDirPath = path.join(root, 'app');
|
||||
const newDirPath = path.join(root, 'app-example');
|
||||
const newAppDirPath = path.join(root, 'app');
|
||||
|
||||
const indexContent = `import { Text, View } from "react-native";
|
||||
|
||||
export default function Index() {
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Text>Edit app/index.tsx to edit this screen.</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
`;
|
||||
|
||||
const layoutContent = `import { Stack } from "expo-router";
|
||||
|
||||
export default function RootLayout() {
|
||||
return (
|
||||
<Stack>
|
||||
<Stack.Screen name="index" />
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
`;
|
||||
|
||||
fs.rename(oldDirPath, newDirPath, (error) => {
|
||||
if (error) {
|
||||
return console.error(`Error renaming directory: ${error}`);
|
||||
}
|
||||
console.log('/app moved to /app-example.');
|
||||
|
||||
fs.mkdir(newAppDirPath, { recursive: true }, (error) => {
|
||||
if (error) {
|
||||
return console.error(`Error creating new app directory: ${error}`);
|
||||
}
|
||||
console.log('New /app directory created.');
|
||||
|
||||
const indexPath = path.join(newAppDirPath, 'index.tsx');
|
||||
fs.writeFile(indexPath, indexContent, (error) => {
|
||||
if (error) {
|
||||
return console.error(`Error creating index.tsx: ${error}`);
|
||||
}
|
||||
console.log('app/index.tsx created.');
|
||||
|
||||
const layoutPath = path.join(newAppDirPath, '_layout.tsx');
|
||||
fs.writeFile(layoutPath, layoutContent, (error) => {
|
||||
if (error) {
|
||||
return console.error(`Error creating _layout.tsx: ${error}`);
|
||||
}
|
||||
console.log('app/_layout.tsx created.');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
17
ev_station/tsconfig.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "expo/tsconfig.base",
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".expo/types/**/*.ts",
|
||||
"expo-env.d.ts"
|
||||
, "app/index.js" ]
|
||||
}
|