Skip to content

Commit c2ede24

Browse files
authored
ft(#1): app onboarding (#26)
ch: format files
1 parent cf48c32 commit c2ede24

File tree

14 files changed

+160
-40
lines changed

14 files changed

+160
-40
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ yarn-error.log*
2626

2727
expo-env.d.ts
2828

29-
coverage/**/*
29+
coverage/**/*
30+
__tests__/_snapshots__/**/*
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import AppOnboarding from '@/app/(onboarding)';
2+
import { render } from '@testing-library/react-native';
3+
4+
import React from 'react';
5+
6+
describe('<AppOnboarding />', () => {
7+
test('Text renders correctly on AppOnboarding', () => {
8+
const { getByText } = render(<AppOnboarding />);
9+
10+
getByText("Optimize your organization's potential with Performance Management/Analytics.");
11+
12+
getByText('Identify top performers, discover hidden talent, and optimize your workforce.');
13+
14+
getByText('Unlock the potential of a Continuous & Tight Feedback Loop.');
15+
16+
getByText('Get Started');
17+
});
18+
});

app.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"output": "static",
2828
"favicon": "./assets/images/favicon.png"
2929
},
30-
"plugins": ["expo-router"],
30+
"plugins": ["expo-router", "expo-font"],
3131
"experiments": {
3232
"typedRoutes": true
3333
},

app/(onboarding)/_layout.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { View } from '@/components/Themed';
2+
import { Slot } from 'expo-router';
3+
import React from 'react';
4+
import { useColorScheme } from 'react-native';
5+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
6+
7+
export default function AppOnboardingLayout({ children }: { children: React.ReactNode }) {
8+
const colorScheme = useColorScheme();
9+
10+
const insets = useSafeAreaInsets();
11+
12+
const bgColor = () => (colorScheme === 'dark' ? 'bg-[#020917]' : 'bg-[#E0E7FF]');
13+
14+
return (
15+
<View
16+
className={`flex-1 ${bgColor()}`}
17+
style={{ paddingTop: insets.top, paddingBottom: insets.bottom }}
18+
>
19+
<Slot />
20+
</View>
21+
);
22+
}

app/(onboarding)/index.tsx

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { Text, View } from '@/components/Themed';
2+
import { Image } from 'expo-image';
3+
import React, { useEffect, useRef, useState } from 'react';
4+
import { TouchableOpacity, useColorScheme } from 'react-native';
5+
import PagerView from 'react-native-pager-view';
6+
7+
type Page = {
8+
image: any;
9+
content: string;
10+
};
11+
12+
const pages: Page[] = [
13+
{
14+
image: require('@/assets/images/onboarding/1.png'),
15+
content: "Optimize your organization's potential with Performance Management/Analytics.",
16+
},
17+
{
18+
image: require('@/assets/images/onboarding/2.png'),
19+
content: 'Identify top performers, discover hidden talent, and optimize your workforce.',
20+
},
21+
{
22+
image: require('@/assets/images/onboarding/3.png'),
23+
content: 'Unlock the potential of a Continuous & Tight Feedback Loop.',
24+
},
25+
];
26+
27+
export default function AppOnboarding() {
28+
const colorScheme = useColorScheme();
29+
const pagerViewRef = useRef<PagerView>(null);
30+
const [page, setPage] = useState<number>(0);
31+
32+
const textColor = colorScheme === 'dark' ? 'bg-gray-100' : 'bg-gray-800';
33+
const bgColor = colorScheme === 'dark' ? 'bg-primary-dark' : 'bg-primary-light';
34+
35+
const getDotColor = (index: number) => (index === page ? 'bg-action-500' : 'bg-white');
36+
37+
useEffect(() => {
38+
const interval = setInterval(() => {
39+
setPage(page === 2 ? 0 : page + 1);
40+
}, 6000);
41+
42+
return () => clearInterval(interval);
43+
}, [page]);
44+
45+
useEffect(() => {
46+
pagerViewRef.current?.setPage(page);
47+
}, [page]);
48+
49+
return (
50+
<>
51+
<PagerView
52+
initialPage={page}
53+
style={{ minHeight: 580 }}
54+
onPageSelected={(p) => setPage(p.nativeEvent.position)}
55+
ref={pagerViewRef}
56+
>
57+
{pages.map((page, index) => (
58+
<View key={index} className={`flex-1 px-8 py-12 ${bgColor}`}>
59+
<Image
60+
source={page.image}
61+
contentFit="contain"
62+
className="mb-6 justify-center items-end"
63+
style={{ width: '100%', flex: 1 }}
64+
/>
65+
<Text
66+
style={{
67+
color: textColor,
68+
fontSize: 24,
69+
textAlign: 'center',
70+
}}
71+
className="font-Inter-SemiBold leading-9"
72+
>
73+
{page.content}
74+
</Text>
75+
</View>
76+
))}
77+
</PagerView>
78+
<View className={`flex-1 flex-row justify-center items-center gap-3 ${bgColor}`}>
79+
<View className={`rounded-full bg-action-500 w-4 h-4 ${getDotColor(0)}`}></View>
80+
<View className={`rounded-full w-4 h-4 ${getDotColor(1)}`}></View>
81+
<View className={`rounded-full w-4 h-4 ${getDotColor(2)}`}></View>
82+
</View>
83+
<View className={`flex-1 flex-row justify-center items-center ${bgColor}`}>
84+
<TouchableOpacity>
85+
<Text className="text-lg font-Inter-Medium">Get Started</Text>
86+
</TouchableOpacity>
87+
</View>
88+
</>
89+
);
90+
}

app/_layout.tsx

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,25 @@
1-
import FontAwesome from '@expo/vector-icons/FontAwesome';
2-
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
3-
import { useFonts } from 'expo-font';
4-
import { Stack } from 'expo-router';
5-
import * as SplashScreen from 'expo-splash-screen';
6-
import { useEffect } from 'react';
7-
import 'react-native-reanimated';
8-
import '@/global.css';
91
import { useColorScheme } from '@/components/useColorScheme';
2+
import '@/global.css';
103
import {
114
Inter_400Regular,
125
Inter_500Medium,
136
Inter_600SemiBold,
147
Inter_700Bold,
158
} from '@expo-google-fonts/inter';
16-
import React from 'react';
9+
import FontAwesome from '@expo/vector-icons/FontAwesome';
10+
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
11+
import { useFonts } from 'expo-font';
12+
import { Stack } from 'expo-router';
13+
import * as SplashScreen from 'expo-splash-screen';
14+
import React, { useEffect } from 'react';
15+
import 'react-native-reanimated';
1716

18-
export {
19-
// Catch any errors thrown by the Layout component.
20-
ErrorBoundary,
21-
} from 'expo-router';
17+
export { ErrorBoundary } from 'expo-router';
2218

2319
export const unstable_settings = {
24-
// Ensure that reloading on `/modal` keeps a back button present.
25-
initialRouteName: '(tabs)',
20+
initialRouteName: '(onboarding)',
2621
};
2722

28-
// Prevent the splash screen from auto-hiding before asset loading is complete.
2923
SplashScreen.preventAutoHideAsync();
3024

3125
export default function RootLayout() {
@@ -37,7 +31,6 @@ export default function RootLayout() {
3731
...FontAwesome.font,
3832
});
3933

40-
// Expo Router uses Error Boundaries to catch errors in the navigation tree.
4134
useEffect(() => {
4235
if (error) throw error;
4336
}, [error]);
@@ -60,7 +53,9 @@ function RootLayoutNav() {
6053

6154
return (
6255
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
63-
<Stack></Stack>
56+
<Stack>
57+
<Stack.Screen name="(onboarding)" options={{ headerShown: false }} />
58+
</Stack>
6459
</ThemeProvider>
6560
);
6661
}

assets/images/logo-dark.png

3.94 KB
Loading

assets/images/logo-light.png

4 KB
Loading

assets/images/onboarding/1.png

37.6 KB
Loading

assets/images/onboarding/2.png

29.1 KB
Loading

0 commit comments

Comments
 (0)