Skip to content

Commit 304bf7f

Browse files
committed
add test project app side
1 parent a3733d0 commit 304bf7f

33 files changed

+1034
-3
lines changed

__fixtures__/test-project/.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,18 @@ api/src/lib/generateGraphiQLHeader.*
2222
!.yarn/releases
2323
!.yarn/sdks
2424
!.yarn/versions
25+
26+
# Expo
27+
.expo
28+
web-build
29+
expo-env.d.ts
30+
.kotlin/
31+
*.orig.*
32+
*.jks
33+
*.p8
34+
*.p12
35+
*.key
36+
*.mobileprovision
37+
.metro-health-check*
38+
*.pem
39+
*.tsbuildinfo
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# EXPO_PUBLIC_RWJS_API_GRAPHQL_URL=http://localhost:8911/graphql
2+
# EXPO_PUBLIC_API_URL=http://localhost:8911
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/* eslint-disable no-var */
2+
3+
declare global {
4+
/**
5+
* FQDN or absolute path to the GraphQL serverless function, without the trailing slash.
6+
* Example: `./redwood/functions/graphql` or `https://api.redwoodjs.com/graphql`
7+
*/
8+
var RWJS_API_GRAPHQL_URL: string
9+
10+
/**
11+
* URL or absolute path to serverless functions, without the trailing slash.
12+
* Example: `./redwood/functions/` or `https://api.redwoodjs.com/`
13+
**/
14+
var RWJS_API_URL: string
15+
16+
// Provided by Vite.config in the user's project
17+
var RWJS_ENV: {
18+
RWJS_API_GRAPHQL_URL: string
19+
/** URL or absolute path to serverless functions */
20+
RWJS_API_URL: string
21+
}
22+
23+
namespace NodeJS {
24+
interface Global {
25+
/** URL or absolute path to the GraphQL serverless function */
26+
RWJS_API_GRAPHQL_URL: string
27+
/** URL or absolute path to serverless functions */
28+
RWJS_API_URL: string
29+
}
30+
}
31+
}
32+
33+
export {}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"expo": {
3+
"name": "app",
4+
"slug": "app",
5+
"version": "1.0.0",
6+
"orientation": "portrait",
7+
"icon": "./assets/images/icon.png",
8+
"scheme": "app",
9+
"userInterfaceStyle": "automatic",
10+
"newArchEnabled": true,
11+
"ios": {
12+
"supportsTablet": true
13+
},
14+
"android": {
15+
"adaptiveIcon": {
16+
"foregroundImage": "./assets/images/adaptive-icon.png",
17+
"backgroundColor": "#ffffff"
18+
},
19+
"edgeToEdgeEnabled": true
20+
},
21+
"web": {
22+
"bundler": "metro",
23+
"output": "static",
24+
"favicon": "./assets/images/favicon.png"
25+
},
26+
"plugins": [
27+
"expo-router",
28+
[
29+
"expo-splash-screen",
30+
{
31+
"image": "./assets/images/splash-icon.png",
32+
"imageWidth": 200,
33+
"resizeMode": "contain",
34+
"backgroundColor": "#ffffff"
35+
}
36+
]
37+
],
38+
"experiments": {
39+
"typedRoutes": true
40+
}
41+
}
42+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import React from 'react'
2+
3+
import MaterialIcons from '@expo/vector-icons/MaterialIcons'
4+
import { Link, Tabs } from 'expo-router'
5+
import { Button, Platform, View } from 'react-native'
6+
7+
import { HapticTab } from '@/components/HapticTab'
8+
import TabBarBackground from '@/components/ui/TabBarBackground'
9+
import { Colors } from '@/constants/Colors'
10+
import { useAuth } from '@/context/auth'
11+
import { useColorScheme } from '@/hooks/useColorScheme'
12+
13+
export default function TabLayout() {
14+
const colorScheme = useColorScheme()
15+
const { isAuthenticated, logOut } = useAuth()
16+
17+
return (
18+
<Tabs
19+
screenOptions={{
20+
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
21+
tabBarButton: HapticTab,
22+
tabBarBackground: TabBarBackground,
23+
tabBarStyle: Platform.select({
24+
ios: {
25+
// Use a transparent background on iOS to show the blur effect
26+
position: 'absolute',
27+
},
28+
default: {},
29+
}),
30+
headerRight: () => (
31+
<View style={{ marginRight: 16 }}>
32+
{isAuthenticated ? (
33+
<Button onPress={logOut} title="Logout" color="red" />
34+
) : (
35+
<Link href="/modal">Login</Link>
36+
)}
37+
</View>
38+
),
39+
}}
40+
>
41+
<Tabs.Screen
42+
name="index"
43+
options={{
44+
title: 'Posts',
45+
tabBarIcon: ({ color }) => (
46+
<MaterialIcons name="article" size={28} color={color} />
47+
),
48+
}}
49+
/>
50+
<Tabs.Screen
51+
name="admin"
52+
options={{
53+
title: 'Admin',
54+
tabBarIcon: ({ color }) => (
55+
<MaterialIcons
56+
name="admin-panel-settings"
57+
size={28}
58+
color={color}
59+
/>
60+
),
61+
}}
62+
/>
63+
</Tabs>
64+
)
65+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react'
2+
3+
import { gql, useQuery } from '@apollo/client'
4+
5+
import { Post, PostProps } from '@/components/Post'
6+
import ThemedScrollView from '@/components/ThemedScrollView'
7+
8+
export const FIND_POSTS_QUERY = gql`
9+
query FindPosts {
10+
posts {
11+
id
12+
title
13+
body
14+
author {
15+
email
16+
fullName
17+
}
18+
createdAt
19+
}
20+
}
21+
`
22+
23+
export default function AdminScreen() {
24+
const { data } = useQuery<{ posts: PostProps['post'][] }>(FIND_POSTS_QUERY)
25+
26+
const posts = data?.posts ?? []
27+
28+
return (
29+
<ThemedScrollView>
30+
{posts.map((post) => (
31+
<Post key={post.id} post={post} />
32+
))}
33+
</ThemedScrollView>
34+
)
35+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import React from 'react'
2+
3+
import { gql, useQuery } from '@apollo/client'
4+
5+
import { BlogPost, BlogPostProps } from '@/components/BlogPost'
6+
import ThemedScrollView from '@/components/ThemedScrollView'
7+
import { ThemedView } from '@/components/ThemedView'
8+
9+
const QUERY = gql`
10+
query BlogPostsQuery {
11+
blogPosts: posts {
12+
id
13+
title
14+
body
15+
author {
16+
email
17+
fullName
18+
}
19+
createdAt
20+
}
21+
}
22+
`
23+
24+
export default function HomeScreen() {
25+
const { data } = useQuery(QUERY)
26+
27+
const blogPosts: BlogPostProps['blogPost'][] = data?.blogPosts ?? []
28+
29+
return (
30+
<ThemedScrollView>
31+
<ThemedView>
32+
{blogPosts.map((blogPost, index) => (
33+
<BlogPost
34+
key={blogPost.id}
35+
blogPost={blogPost}
36+
isLast={index === blogPosts.length - 1}
37+
/>
38+
))}
39+
</ThemedView>
40+
</ThemedScrollView>
41+
)
42+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React from 'react'
2+
3+
import { Link, Stack } from 'expo-router'
4+
import { StyleSheet } from 'react-native'
5+
6+
import { ThemedText } from '@/components/ThemedText'
7+
import { ThemedView } from '@/components/ThemedView'
8+
9+
export default function NotFoundScreen() {
10+
return (
11+
<>
12+
<Stack.Screen options={{ title: 'Oops!' }} />
13+
<ThemedView style={styles.container}>
14+
<ThemedText type="title">This screen does not exist.</ThemedText>
15+
<Link href="/" style={styles.link}>
16+
<ThemedText type="link">Go to home screen!</ThemedText>
17+
</Link>
18+
</ThemedView>
19+
</>
20+
)
21+
}
22+
23+
const styles = StyleSheet.create({
24+
container: {
25+
flex: 1,
26+
alignItems: 'center',
27+
justifyContent: 'center',
28+
padding: 20,
29+
},
30+
link: {
31+
marginTop: 15,
32+
paddingVertical: 15,
33+
},
34+
})
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import React from 'react'
2+
3+
import {
4+
DarkTheme,
5+
DefaultTheme,
6+
ThemeProvider,
7+
} from '@react-navigation/native'
8+
import { useFonts } from 'expo-font'
9+
import { Stack } from 'expo-router'
10+
import { StatusBar } from 'expo-status-bar'
11+
12+
import { RedwoodApolloProvider } from '@cedarjs/web/apollo'
13+
14+
import { AuthProvider, useAuth } from '@/context/auth'
15+
import { useColorScheme } from '@/hooks/useColorScheme'
16+
17+
import 'react-native-reanimated'
18+
19+
export default function RootLayout() {
20+
const colorScheme = useColorScheme()
21+
const [loaded] = useFonts({
22+
SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
23+
})
24+
25+
if (!loaded) {
26+
// Async font loading only occurs in development.
27+
return null
28+
}
29+
30+
return (
31+
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
32+
<AuthProvider>
33+
<RedwoodApolloProvider
34+
useAuth={useAuth}
35+
graphQLClientConfig={{ uri: process.env.EXPO_PUBLIC_API_URL! }}
36+
>
37+
<Stack>
38+
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
39+
<Stack.Screen name="+not-found" />
40+
<Stack.Screen
41+
name="modal"
42+
options={{ presentation: 'modal', title: 'Login' }}
43+
/>
44+
</Stack>
45+
<StatusBar style="auto" />
46+
</RedwoodApolloProvider>
47+
</AuthProvider>
48+
</ThemeProvider>
49+
)
50+
}

0 commit comments

Comments
 (0)