create-better-t-stack 3.2.21 → 3.2.23-canary.2b547ed5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1 -1
- package/dist/{src-WIwtBCHf.js → src-ehteLbIu.js} +105 -65
- package/package.json +1 -1
- package/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs +5 -5
- package/templates/auth/better-auth/convex/backend/convex/http.ts.hbs +1 -1
- package/templates/auth/better-auth/convex/native/bare/components/sign-in.tsx.hbs +127 -0
- package/templates/auth/better-auth/convex/native/bare/components/sign-up.tsx.hbs +138 -0
- package/templates/auth/better-auth/convex/native/uniwind/components/sign-in.tsx.hbs +91 -0
- package/templates/auth/better-auth/convex/native/uniwind/components/sign-up.tsx.hbs +102 -0
- package/templates/auth/better-auth/native/bare/app/(drawer)/index.tsx.hbs +186 -0
- package/templates/auth/better-auth/native/bare/components/sign-in.tsx.hbs +131 -0
- package/templates/auth/better-auth/native/bare/components/sign-up.tsx.hbs +150 -0
- package/templates/auth/better-auth/native/unistyles/app/(drawer)/index.tsx.hbs +9 -1
- package/templates/auth/better-auth/native/unistyles/components/sign-in.tsx.hbs +5 -0
- package/templates/auth/better-auth/native/unistyles/components/sign-up.tsx.hbs +5 -0
- package/templates/auth/better-auth/native/uniwind/app/(drawer)/index.tsx.hbs +123 -0
- package/templates/auth/better-auth/native/uniwind/components/sign-in.tsx.hbs +90 -0
- package/templates/auth/better-auth/native/uniwind/components/sign-up.tsx.hbs +116 -0
- package/templates/auth/better-auth/server/base/src/index.ts.hbs +5 -5
- package/templates/examples/ai/native/bare/app/(drawer)/ai.tsx.hbs +287 -0
- package/templates/examples/ai/native/{nativewind → bare}/polyfills.js +1 -0
- package/templates/examples/ai/native/{nativewind → uniwind}/app/(drawer)/ai.tsx.hbs +52 -51
- package/templates/examples/ai/native/uniwind/polyfills.js +26 -0
- package/templates/examples/todo/native/bare/app/(drawer)/todos.tsx.hbs +430 -0
- package/templates/examples/todo/native/uniwind/app/(drawer)/todos.tsx.hbs +295 -0
- package/templates/extras/bunfig.toml.hbs +3 -3
- package/templates/frontend/native/bare/_gitignore +18 -0
- package/templates/frontend/native/{nativewind → bare}/app/(drawer)/(tabs)/_layout.tsx.hbs +7 -12
- package/templates/frontend/native/bare/app/(drawer)/(tabs)/index.tsx.hbs +43 -0
- package/templates/frontend/native/bare/app/(drawer)/(tabs)/two.tsx.hbs +43 -0
- package/templates/frontend/native/{nativewind → bare}/app/(drawer)/_layout.tsx.hbs +24 -1
- package/templates/frontend/native/bare/app/(drawer)/index.tsx.hbs +234 -0
- package/templates/frontend/native/bare/app/+not-found.tsx.hbs +65 -0
- package/templates/frontend/native/bare/app/_layout.tsx.hbs +163 -0
- package/templates/frontend/native/bare/app/modal.tsx.hbs +34 -0
- package/templates/frontend/native/{nativewind → bare}/app.json.hbs +1 -0
- package/templates/frontend/native/bare/components/container.tsx.hbs +25 -0
- package/templates/frontend/native/bare/components/header-button.tsx.hbs +47 -0
- package/templates/frontend/native/{nativewind → bare}/components/tabbar-icon.tsx.hbs +1 -0
- package/templates/frontend/native/{nativewind → bare}/lib/android-navigation-bar.tsx.hbs +1 -0
- package/templates/frontend/native/{nativewind → bare}/lib/constants.ts.hbs +1 -0
- package/templates/frontend/native/bare/lib/use-color-scheme.ts.hbs +20 -0
- package/templates/frontend/native/bare/metro.config.js.hbs +9 -0
- package/templates/frontend/native/{nativewind → bare}/package.json.hbs +1 -2
- package/templates/frontend/native/bare/tsconfig.json.hbs +11 -0
- package/templates/frontend/native/{nativewind → uniwind}/_gitignore +4 -8
- package/templates/frontend/native/uniwind/app/(drawer)/(tabs)/_layout.tsx.hbs +46 -0
- package/templates/frontend/native/uniwind/app/(drawer)/(tabs)/index.tsx.hbs +15 -0
- package/templates/frontend/native/uniwind/app/(drawer)/(tabs)/two.tsx.hbs +15 -0
- package/templates/frontend/native/uniwind/app/(drawer)/_layout.tsx.hbs +83 -0
- package/templates/frontend/native/uniwind/app/(drawer)/index.tsx.hbs +151 -0
- package/templates/frontend/native/uniwind/app/+not-found.tsx.hbs +32 -0
- package/templates/frontend/native/uniwind/app/_layout.tsx.hbs +131 -0
- package/templates/frontend/native/uniwind/app/modal.tsx.hbs +53 -0
- package/templates/frontend/native/uniwind/app.json.hbs +19 -0
- package/templates/frontend/native/uniwind/components/container.tsx.hbs +33 -0
- package/templates/frontend/native/uniwind/components/theme-toggle.tsx.hbs +35 -0
- package/templates/frontend/native/uniwind/contexts/app-theme-context.tsx.hbs +62 -0
- package/templates/frontend/native/uniwind/global.css +5 -0
- package/templates/frontend/native/uniwind/metro.config.js.hbs +13 -0
- package/templates/frontend/native/uniwind/package.json.hbs +54 -0
- package/templates/frontend/native/{nativewind → uniwind}/tsconfig.json.hbs +4 -8
- package/templates/frontend/react/tanstack-router/src/routes/__root.tsx.hbs +2 -8
- package/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs +3 -6
- package/templates/auth/better-auth/convex/native/nativewind/components/sign-in.tsx.hbs +0 -86
- package/templates/auth/better-auth/convex/native/nativewind/components/sign-up.tsx.hbs +0 -97
- package/templates/auth/better-auth/native/nativewind/app/(drawer)/index.tsx.hbs +0 -95
- package/templates/auth/better-auth/native/nativewind/components/sign-in.tsx.hbs +0 -93
- package/templates/auth/better-auth/native/nativewind/components/sign-up.tsx.hbs +0 -104
- package/templates/examples/todo/native/nativewind/app/(drawer)/todos.tsx.hbs +0 -295
- package/templates/frontend/native/nativewind/app/(drawer)/(tabs)/index.tsx.hbs +0 -19
- package/templates/frontend/native/nativewind/app/(drawer)/(tabs)/two.tsx.hbs +0 -19
- package/templates/frontend/native/nativewind/app/(drawer)/index.tsx.hbs +0 -178
- package/templates/frontend/native/nativewind/app/+not-found.tsx.hbs +0 -29
- package/templates/frontend/native/nativewind/app/_layout.tsx.hbs +0 -175
- package/templates/frontend/native/nativewind/app/modal.tsx.hbs +0 -14
- package/templates/frontend/native/nativewind/babel.config.js.hbs +0 -14
- package/templates/frontend/native/nativewind/components/container.tsx.hbs +0 -8
- package/templates/frontend/native/nativewind/components/header-button.tsx.hbs +0 -26
- package/templates/frontend/native/nativewind/global.css +0 -50
- package/templates/frontend/native/nativewind/lib/use-color-scheme.ts.hbs +0 -12
- package/templates/frontend/native/nativewind/metro.config.js.hbs +0 -12
- package/templates/frontend/native/nativewind/tailwind.config.js.hbs +0 -59
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const { getDefaultConfig } = require("expo/metro-config");
|
|
2
|
+
const { withUniwindConfig } = require("uniwind/metro");
|
|
3
|
+
|
|
4
|
+
/** @type {import('expo/metro-config').MetroConfig} */
|
|
5
|
+
const config = getDefaultConfig(__dirname);
|
|
6
|
+
|
|
7
|
+
const uniwindConfig = withUniwindConfig(config, {
|
|
8
|
+
cssEntryFile: "./global.css",
|
|
9
|
+
dtsFile: "./uniwind-types.d.ts",
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
module.exports = uniwindConfig;
|
|
13
|
+
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "native",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "expo-router/entry",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"start": "expo start",
|
|
7
|
+
"dev": "expo start --clear",
|
|
8
|
+
"android": "expo run:android",
|
|
9
|
+
"ios": "expo run:ios",
|
|
10
|
+
"prebuild": "expo prebuild",
|
|
11
|
+
"web": "expo start --web"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@expo/metro-runtime": "~6.1.2",
|
|
15
|
+
"@expo/vector-icons": "^15.0.3",
|
|
16
|
+
"@gorhom/bottom-sheet": "^5",
|
|
17
|
+
"@react-navigation/drawer": "^7.3.9",
|
|
18
|
+
"@react-navigation/elements": "^2.8.1",
|
|
19
|
+
{{#if (includes examples "ai")}}
|
|
20
|
+
"@stardazed/streams-text-encoding": "^1.0.2",
|
|
21
|
+
"@ungap/structured-clone": "^1.3.0",
|
|
22
|
+
{{/if}}
|
|
23
|
+
"expo": "^54.0.23",
|
|
24
|
+
"expo-constants": "~18.0.10",
|
|
25
|
+
"expo-font": "~14.0.9",
|
|
26
|
+
"expo-haptics": "^15.0.7",
|
|
27
|
+
"expo-linking": "~8.0.8",
|
|
28
|
+
"expo-router": "~6.0.14",
|
|
29
|
+
"expo-secure-store": "~15.0.7",
|
|
30
|
+
"expo-status-bar": "~3.0.8",
|
|
31
|
+
"heroui-native": "^1.0.0-beta.1",
|
|
32
|
+
"react": "19.1.0",
|
|
33
|
+
"react-dom": "19.1.0",
|
|
34
|
+
"react-native": "0.81.5",
|
|
35
|
+
"react-native-gesture-handler": "~2.28.0",
|
|
36
|
+
"react-native-keyboard-controller": "1.18.5",
|
|
37
|
+
"react-native-reanimated": "~4.1.0",
|
|
38
|
+
"react-native-safe-area-context": "5.6.0",
|
|
39
|
+
"react-native-screens": "~4.16.0",
|
|
40
|
+
"react-native-svg": "15.12.1",
|
|
41
|
+
"react-native-web": "^0.21.0",
|
|
42
|
+
"react-native-worklets": "0.5.1",
|
|
43
|
+
"tailwind-merge": "^3.3.1",
|
|
44
|
+
"tailwind-variants": "^3.1.0",
|
|
45
|
+
"tailwindcss": "~4.1.16",
|
|
46
|
+
"uniwind": "^1.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^24.10.0",
|
|
50
|
+
"@types/react": "~19.1.0",
|
|
51
|
+
"typescript": "~5.9.2"
|
|
52
|
+
},
|
|
53
|
+
"private": true
|
|
54
|
+
}
|
|
@@ -2,17 +2,13 @@
|
|
|
2
2
|
"extends": "expo/tsconfig.base",
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"strict": true,
|
|
5
|
+
"baseUrl": ".",
|
|
5
6
|
"paths": {
|
|
6
|
-
"@/*": [
|
|
7
|
-
"./*"
|
|
8
|
-
]
|
|
7
|
+
"@/*": ["./*"]
|
|
9
8
|
}
|
|
10
9
|
},
|
|
11
10
|
"include": [
|
|
12
11
|
"**/*.ts",
|
|
13
|
-
"**/*.tsx"
|
|
14
|
-
".expo/types/**/*.ts",
|
|
15
|
-
"expo-env.d.ts",
|
|
16
|
-
"nativewind-env.d.ts"
|
|
12
|
+
"**/*.tsx"
|
|
17
13
|
]
|
|
18
|
-
}
|
|
14
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import Header from "@/components/header";
|
|
2
|
-
import Loader from "@/components/loader";
|
|
3
2
|
import { ThemeProvider } from "@/components/theme-provider";
|
|
4
3
|
import { Toaster } from "@/components/ui/sonner";
|
|
5
4
|
{{#if (eq api "orpc")}}
|
|
@@ -20,7 +19,6 @@ import {
|
|
|
20
19
|
HeadContent,
|
|
21
20
|
Outlet,
|
|
22
21
|
createRootRouteWithContext,
|
|
23
|
-
useRouterState,
|
|
24
22
|
} from "@tanstack/react-router";
|
|
25
23
|
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
|
|
26
24
|
import "../index.css";
|
|
@@ -61,10 +59,6 @@ export const Route = createRootRouteWithContext<RouterAppContext>()({
|
|
|
61
59
|
});
|
|
62
60
|
|
|
63
61
|
function RootComponent() {
|
|
64
|
-
const isFetching = useRouterState({
|
|
65
|
-
select: (s) => s.isLoading,
|
|
66
|
-
});
|
|
67
|
-
|
|
68
62
|
{{#if (eq api "orpc")}}
|
|
69
63
|
const [client] = useState<AppRouterClient>(() => createORPCClient(link));
|
|
70
64
|
const [orpcUtils] = useState(() => createTanstackQueryUtils(client));
|
|
@@ -82,7 +76,7 @@ function RootComponent() {
|
|
|
82
76
|
>
|
|
83
77
|
<div className="grid grid-rows-[auto_1fr] h-svh">
|
|
84
78
|
<Header />
|
|
85
|
-
|
|
79
|
+
<Outlet />
|
|
86
80
|
</div>
|
|
87
81
|
<Toaster richColors />
|
|
88
82
|
</ThemeProvider>
|
|
@@ -95,7 +89,7 @@ function RootComponent() {
|
|
|
95
89
|
>
|
|
96
90
|
<div className="grid grid-rows-[auto_1fr] h-svh">
|
|
97
91
|
<Header />
|
|
98
|
-
|
|
92
|
+
<Outlet />
|
|
99
93
|
</div>
|
|
100
94
|
<Toaster richColors />
|
|
101
95
|
</ThemeProvider>
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
Outlet,
|
|
8
8
|
Scripts,
|
|
9
9
|
createRootRouteWithContext,
|
|
10
|
-
useRouterState,
|
|
11
10
|
{{#if (and (eq backend "convex") (or (eq auth "clerk") (eq auth "better-auth")))}}
|
|
12
11
|
useRouteContext,
|
|
13
12
|
{{/if}}
|
|
@@ -24,7 +23,6 @@ import type { ConvexReactClient } from "convex/react";
|
|
|
24
23
|
import type { QueryClient } from "@tanstack/react-query";
|
|
25
24
|
{{/if}}
|
|
26
25
|
{{/if}}
|
|
27
|
-
import Loader from "@/components/loader";
|
|
28
26
|
|
|
29
27
|
{{#if (and (eq backend "convex") (eq auth "clerk"))}}
|
|
30
28
|
import { ClerkProvider, useAuth } from "@clerk/tanstack-react-start";
|
|
@@ -125,7 +123,6 @@ export const Route = createRootRouteWithContext<RouterAppContext>()({
|
|
|
125
123
|
});
|
|
126
124
|
|
|
127
125
|
function RootDocument() {
|
|
128
|
-
const isFetching = useRouterState({ select: (s) => s.isLoading });
|
|
129
126
|
{{#if (and (eq backend "convex") (eq auth "clerk"))}}
|
|
130
127
|
const context = useRouteContext({ from: Route.id });
|
|
131
128
|
return (
|
|
@@ -138,7 +135,7 @@ function RootDocument() {
|
|
|
138
135
|
<body>
|
|
139
136
|
<div className="grid h-svh grid-rows-[auto_1fr]">
|
|
140
137
|
<Header />
|
|
141
|
-
|
|
138
|
+
<Outlet />
|
|
142
139
|
</div>
|
|
143
140
|
<Toaster richColors />
|
|
144
141
|
<TanStackRouterDevtools position="bottom-left" />
|
|
@@ -159,7 +156,7 @@ function RootDocument() {
|
|
|
159
156
|
<body>
|
|
160
157
|
<div className="grid h-svh grid-rows-[auto_1fr]">
|
|
161
158
|
<Header />
|
|
162
|
-
|
|
159
|
+
<Outlet />
|
|
163
160
|
</div>
|
|
164
161
|
<Toaster richColors />
|
|
165
162
|
<TanStackRouterDevtools position="bottom-left" />
|
|
@@ -177,7 +174,7 @@ function RootDocument() {
|
|
|
177
174
|
<body>
|
|
178
175
|
<div className="grid h-svh grid-rows-[auto_1fr]">
|
|
179
176
|
<Header />
|
|
180
|
-
|
|
177
|
+
<Outlet />
|
|
181
178
|
</div>
|
|
182
179
|
<Toaster richColors />
|
|
183
180
|
<TanStackRouterDevtools position="bottom-left" />
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { authClient } from "@/lib/auth-client";
|
|
2
|
-
import { useState } from "react";
|
|
3
|
-
import {
|
|
4
|
-
ActivityIndicator,
|
|
5
|
-
Text,
|
|
6
|
-
TextInput,
|
|
7
|
-
TouchableOpacity,
|
|
8
|
-
View,
|
|
9
|
-
} from "react-native";
|
|
10
|
-
|
|
11
|
-
export function SignIn() {
|
|
12
|
-
const [email, setEmail] = useState("");
|
|
13
|
-
const [password, setPassword] = useState("");
|
|
14
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
15
|
-
const [error, setError] = useState<string | null>(null);
|
|
16
|
-
|
|
17
|
-
const handleLogin = async () => {
|
|
18
|
-
setIsLoading(true);
|
|
19
|
-
setError(null);
|
|
20
|
-
|
|
21
|
-
await authClient.signIn.email(
|
|
22
|
-
{
|
|
23
|
-
email,
|
|
24
|
-
password,
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
onError: (error) => {
|
|
28
|
-
setError(error.error?.message || "Failed to sign in");
|
|
29
|
-
setIsLoading(false);
|
|
30
|
-
},
|
|
31
|
-
onSuccess: () => {
|
|
32
|
-
setEmail("");
|
|
33
|
-
setPassword("");
|
|
34
|
-
},
|
|
35
|
-
onFinished: () => {
|
|
36
|
-
setIsLoading(false);
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<View className="mt-6 p-4 bg-card rounded-lg border border-border">
|
|
44
|
-
<Text className="text-lg font-semibold text-foreground mb-4">
|
|
45
|
-
Sign In
|
|
46
|
-
</Text>
|
|
47
|
-
|
|
48
|
-
{error && (
|
|
49
|
-
<View className="mb-4 p-3 bg-destructive/10 rounded-md">
|
|
50
|
-
<Text className="text-destructive text-sm">{error}</Text>
|
|
51
|
-
</View>
|
|
52
|
-
)}
|
|
53
|
-
|
|
54
|
-
<TextInput
|
|
55
|
-
className="mb-3 p-4 rounded-md bg-input text-foreground border border-input"
|
|
56
|
-
placeholder="Email"
|
|
57
|
-
value={email}
|
|
58
|
-
onChangeText={setEmail}
|
|
59
|
-
placeholderTextColor="#9CA3AF"
|
|
60
|
-
keyboardType="email-address"
|
|
61
|
-
autoCapitalize="none"
|
|
62
|
-
/>
|
|
63
|
-
|
|
64
|
-
<TextInput
|
|
65
|
-
className="mb-4 p-4 rounded-md bg-input text-foreground border border-input"
|
|
66
|
-
placeholder="Password"
|
|
67
|
-
value={password}
|
|
68
|
-
onChangeText={setPassword}
|
|
69
|
-
placeholderTextColor="#9CA3AF"
|
|
70
|
-
secureTextEntry
|
|
71
|
-
/>
|
|
72
|
-
|
|
73
|
-
<TouchableOpacity
|
|
74
|
-
onPress={handleLogin}
|
|
75
|
-
disabled={isLoading}
|
|
76
|
-
className="bg-primary p-4 rounded-md flex-row justify-center items-center"
|
|
77
|
-
>
|
|
78
|
-
{isLoading ? (
|
|
79
|
-
<ActivityIndicator size="small" color="#fff" />
|
|
80
|
-
) : (
|
|
81
|
-
<Text className="text-primary-foreground font-medium">Sign In</Text>
|
|
82
|
-
)}
|
|
83
|
-
</TouchableOpacity>
|
|
84
|
-
</View>
|
|
85
|
-
);
|
|
86
|
-
}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { authClient } from "@/lib/auth-client";
|
|
2
|
-
import { useState } from "react";
|
|
3
|
-
import {
|
|
4
|
-
ActivityIndicator,
|
|
5
|
-
Text,
|
|
6
|
-
TextInput,
|
|
7
|
-
TouchableOpacity,
|
|
8
|
-
View,
|
|
9
|
-
} from "react-native";
|
|
10
|
-
|
|
11
|
-
export function SignUp() {
|
|
12
|
-
const [name, setName] = useState("");
|
|
13
|
-
const [email, setEmail] = useState("");
|
|
14
|
-
const [password, setPassword] = useState("");
|
|
15
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
16
|
-
const [error, setError] = useState<string | null>(null);
|
|
17
|
-
|
|
18
|
-
const handleSignUp = async () => {
|
|
19
|
-
setIsLoading(true);
|
|
20
|
-
setError(null);
|
|
21
|
-
|
|
22
|
-
await authClient.signUp.email(
|
|
23
|
-
{
|
|
24
|
-
name,
|
|
25
|
-
email,
|
|
26
|
-
password,
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
onError: (error) => {
|
|
30
|
-
setError(error.error?.message || "Failed to sign up");
|
|
31
|
-
setIsLoading(false);
|
|
32
|
-
},
|
|
33
|
-
onSuccess: () => {
|
|
34
|
-
setName("");
|
|
35
|
-
setEmail("");
|
|
36
|
-
setPassword("");
|
|
37
|
-
},
|
|
38
|
-
onFinished: () => {
|
|
39
|
-
setIsLoading(false);
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<View className="mt-6 p-4 bg-card rounded-lg border border-border">
|
|
47
|
-
<Text className="text-lg font-semibold text-foreground mb-4">
|
|
48
|
-
Create Account
|
|
49
|
-
</Text>
|
|
50
|
-
|
|
51
|
-
{error && (
|
|
52
|
-
<View className="mb-4 p-3 bg-destructive/10 rounded-md">
|
|
53
|
-
<Text className="text-destructive text-sm">{error}</Text>
|
|
54
|
-
</View>
|
|
55
|
-
)}
|
|
56
|
-
|
|
57
|
-
<TextInput
|
|
58
|
-
className="mb-3 p-4 rounded-md bg-input text-foreground border border-input"
|
|
59
|
-
placeholder="Name"
|
|
60
|
-
value={name}
|
|
61
|
-
onChangeText={setName}
|
|
62
|
-
placeholderTextColor="#9CA3AF"
|
|
63
|
-
/>
|
|
64
|
-
|
|
65
|
-
<TextInput
|
|
66
|
-
className="mb-3 p-4 rounded-md bg-input text-foreground border border-input"
|
|
67
|
-
placeholder="Email"
|
|
68
|
-
value={email}
|
|
69
|
-
onChangeText={setEmail}
|
|
70
|
-
placeholderTextColor="#9CA3AF"
|
|
71
|
-
keyboardType="email-address"
|
|
72
|
-
autoCapitalize="none"
|
|
73
|
-
/>
|
|
74
|
-
|
|
75
|
-
<TextInput
|
|
76
|
-
className="mb-4 p-4 rounded-md bg-input text-foreground border border-input"
|
|
77
|
-
placeholder="Password"
|
|
78
|
-
value={password}
|
|
79
|
-
onChangeText={setPassword}
|
|
80
|
-
placeholderTextColor="#9CA3AF"
|
|
81
|
-
secureTextEntry
|
|
82
|
-
/>
|
|
83
|
-
|
|
84
|
-
<TouchableOpacity
|
|
85
|
-
onPress={handleSignUp}
|
|
86
|
-
disabled={isLoading}
|
|
87
|
-
className="bg-primary p-4 rounded-md flex-row justify-center items-center"
|
|
88
|
-
>
|
|
89
|
-
{isLoading ? (
|
|
90
|
-
<ActivityIndicator size="small" color="#fff" />
|
|
91
|
-
) : (
|
|
92
|
-
<Text className="text-primary-foreground font-medium">Sign Up</Text>
|
|
93
|
-
)}
|
|
94
|
-
</TouchableOpacity>
|
|
95
|
-
</View>
|
|
96
|
-
);
|
|
97
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { authClient } from "@/lib/auth-client";
|
|
2
|
-
import { useQuery } from "@tanstack/react-query";
|
|
3
|
-
import { ScrollView, Text, TouchableOpacity, View } from "react-native";
|
|
4
|
-
|
|
5
|
-
import { Container } from "@/components/container";
|
|
6
|
-
import { SignIn } from "@/components/sign-in";
|
|
7
|
-
import { SignUp } from "@/components/sign-up";
|
|
8
|
-
{{#if (eq api "orpc")}}
|
|
9
|
-
import { queryClient, orpc } from "@/utils/orpc";
|
|
10
|
-
{{/if}}
|
|
11
|
-
{{#if (eq api "trpc")}}
|
|
12
|
-
import { queryClient, trpc } from "@/utils/trpc";
|
|
13
|
-
{{/if}}
|
|
14
|
-
|
|
15
|
-
export default function Home() {
|
|
16
|
-
{{#if (eq api "orpc")}}
|
|
17
|
-
const healthCheck = useQuery(orpc.healthCheck.queryOptions());
|
|
18
|
-
const privateData = useQuery(orpc.privateData.queryOptions());
|
|
19
|
-
{{/if}}
|
|
20
|
-
{{#if (eq api "trpc")}}
|
|
21
|
-
const healthCheck = useQuery(trpc.healthCheck.queryOptions());
|
|
22
|
-
const privateData = useQuery(trpc.privateData.queryOptions());
|
|
23
|
-
{{/if}}
|
|
24
|
-
const { data: session } = authClient.useSession();
|
|
25
|
-
|
|
26
|
-
return (
|
|
27
|
-
<Container>
|
|
28
|
-
<ScrollView className="flex-1">
|
|
29
|
-
<View className="px-4">
|
|
30
|
-
<Text className="font-mono text-foreground text-3xl font-bold mb-4">
|
|
31
|
-
BETTER T STACK
|
|
32
|
-
</Text>
|
|
33
|
-
{session?.user ? (
|
|
34
|
-
<View className="mb-6 p-4 bg-card rounded-lg border border-border">
|
|
35
|
-
<View className="flex-row justify-between items-center mb-2">
|
|
36
|
-
<Text className="text-foreground text-base">
|
|
37
|
-
Welcome,{" "}
|
|
38
|
-
<Text className="font-medium">{session.user.name}</Text>
|
|
39
|
-
</Text>
|
|
40
|
-
</View>
|
|
41
|
-
<Text className="text-muted-foreground text-sm mb-4">
|
|
42
|
-
{session.user.email}
|
|
43
|
-
</Text>
|
|
44
|
-
|
|
45
|
-
<TouchableOpacity
|
|
46
|
-
className="bg-destructive py-2 px-4 rounded-md self-start"
|
|
47
|
-
onPress={() => {
|
|
48
|
-
authClient.signOut();
|
|
49
|
-
queryClient.invalidateQueries();
|
|
50
|
-
}}
|
|
51
|
-
>
|
|
52
|
-
<Text className="text-white font-medium">Sign Out</Text>
|
|
53
|
-
</TouchableOpacity>
|
|
54
|
-
</View>
|
|
55
|
-
) : null}
|
|
56
|
-
<View className="mb-6 rounded-lg border border-border p-4">
|
|
57
|
-
<Text className="mb-3 font-medium text-foreground">API Status</Text>
|
|
58
|
-
<View className="flex-row items-center gap-2">
|
|
59
|
-
<View
|
|
60
|
-
className={`h-3 w-3 rounded-full ${
|
|
61
|
-
healthCheck.data ? "bg-green-500" : "bg-red-500"
|
|
62
|
-
}`}
|
|
63
|
-
/>
|
|
64
|
-
<Text className="text-muted-foreground">
|
|
65
|
-
{healthCheck.isLoading
|
|
66
|
-
? "Checking..."
|
|
67
|
-
: healthCheck.data
|
|
68
|
-
? "Connected to API"
|
|
69
|
-
: "API Disconnected"}
|
|
70
|
-
</Text>
|
|
71
|
-
</View>
|
|
72
|
-
</View>
|
|
73
|
-
<View className="mb-6 rounded-lg border border-border p-4">
|
|
74
|
-
<Text className="mb-3 font-medium text-foreground">
|
|
75
|
-
Private Data
|
|
76
|
-
</Text>
|
|
77
|
-
{privateData && (
|
|
78
|
-
<View>
|
|
79
|
-
<Text className="text-muted-foreground">
|
|
80
|
-
{privateData.data?.message}
|
|
81
|
-
</Text>
|
|
82
|
-
</View>
|
|
83
|
-
)}
|
|
84
|
-
</View>
|
|
85
|
-
{!session?.user && (
|
|
86
|
-
<>
|
|
87
|
-
<SignIn />
|
|
88
|
-
<SignUp />
|
|
89
|
-
</>
|
|
90
|
-
)}
|
|
91
|
-
</View>
|
|
92
|
-
</ScrollView>
|
|
93
|
-
</Container>
|
|
94
|
-
);
|
|
95
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { authClient } from "@/lib/auth-client";
|
|
2
|
-
{{#if (eq api "trpc")}}
|
|
3
|
-
import { queryClient } from "@/utils/trpc";
|
|
4
|
-
{{/if}}
|
|
5
|
-
{{#if (eq api "orpc")}}
|
|
6
|
-
import { queryClient } from "@/utils/orpc";
|
|
7
|
-
{{/if}}
|
|
8
|
-
import { useState } from "react";
|
|
9
|
-
import {
|
|
10
|
-
ActivityIndicator,
|
|
11
|
-
Text,
|
|
12
|
-
TextInput,
|
|
13
|
-
TouchableOpacity,
|
|
14
|
-
View,
|
|
15
|
-
} from "react-native";
|
|
16
|
-
|
|
17
|
-
export function SignIn() {
|
|
18
|
-
const [email, setEmail] = useState("");
|
|
19
|
-
const [password, setPassword] = useState("");
|
|
20
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
21
|
-
const [error, setError] = useState<string | null>(null);
|
|
22
|
-
|
|
23
|
-
const handleLogin = async () => {
|
|
24
|
-
setIsLoading(true);
|
|
25
|
-
setError(null);
|
|
26
|
-
|
|
27
|
-
await authClient.signIn.email(
|
|
28
|
-
{
|
|
29
|
-
email,
|
|
30
|
-
password,
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
onError: (error) => {
|
|
34
|
-
setError(error.error?.message || "Failed to sign in");
|
|
35
|
-
setIsLoading(false);
|
|
36
|
-
},
|
|
37
|
-
onSuccess: () => {
|
|
38
|
-
setEmail("");
|
|
39
|
-
setPassword("");
|
|
40
|
-
queryClient.refetchQueries();
|
|
41
|
-
},
|
|
42
|
-
onFinished: () => {
|
|
43
|
-
setIsLoading(false);
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<View className="mt-6 p-4 bg-card rounded-lg border border-border">
|
|
51
|
-
<Text className="text-lg font-semibold text-foreground mb-4">
|
|
52
|
-
Sign In
|
|
53
|
-
</Text>
|
|
54
|
-
|
|
55
|
-
{error && (
|
|
56
|
-
<View className="mb-4 p-3 bg-destructive/10 rounded-md">
|
|
57
|
-
<Text className="text-destructive text-sm">{error}</Text>
|
|
58
|
-
</View>
|
|
59
|
-
)}
|
|
60
|
-
|
|
61
|
-
<TextInput
|
|
62
|
-
className="mb-3 p-4 rounded-md bg-input text-foreground border border-input"
|
|
63
|
-
placeholder="Email"
|
|
64
|
-
value={email}
|
|
65
|
-
onChangeText={setEmail}
|
|
66
|
-
placeholderTextColor="#9CA3AF"
|
|
67
|
-
keyboardType="email-address"
|
|
68
|
-
autoCapitalize="none"
|
|
69
|
-
/>
|
|
70
|
-
|
|
71
|
-
<TextInput
|
|
72
|
-
className="mb-4 p-4 rounded-md bg-input text-foreground border border-input"
|
|
73
|
-
placeholder="Password"
|
|
74
|
-
value={password}
|
|
75
|
-
onChangeText={setPassword}
|
|
76
|
-
placeholderTextColor="#9CA3AF"
|
|
77
|
-
secureTextEntry
|
|
78
|
-
/>
|
|
79
|
-
|
|
80
|
-
<TouchableOpacity
|
|
81
|
-
onPress={handleLogin}
|
|
82
|
-
disabled={isLoading}
|
|
83
|
-
className="bg-primary p-4 rounded-md flex-row justify-center items-center"
|
|
84
|
-
>
|
|
85
|
-
{isLoading ? (
|
|
86
|
-
<ActivityIndicator size="small" color="#fff" />
|
|
87
|
-
) : (
|
|
88
|
-
<Text className="text-primary-foreground font-medium">Sign In</Text>
|
|
89
|
-
)}
|
|
90
|
-
</TouchableOpacity>
|
|
91
|
-
</View>
|
|
92
|
-
);
|
|
93
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { authClient } from "@/lib/auth-client";
|
|
2
|
-
{{#if (eq api "trpc")}}
|
|
3
|
-
import { queryClient } from "@/utils/trpc";
|
|
4
|
-
{{/if}}
|
|
5
|
-
{{#if (eq api "orpc")}}
|
|
6
|
-
import { queryClient } from "@/utils/orpc";
|
|
7
|
-
{{/if}}
|
|
8
|
-
import { useState } from "react";
|
|
9
|
-
import {
|
|
10
|
-
ActivityIndicator,
|
|
11
|
-
Text,
|
|
12
|
-
TextInput,
|
|
13
|
-
TouchableOpacity,
|
|
14
|
-
View,
|
|
15
|
-
} from "react-native";
|
|
16
|
-
|
|
17
|
-
export function SignUp() {
|
|
18
|
-
const [name, setName] = useState("");
|
|
19
|
-
const [email, setEmail] = useState("");
|
|
20
|
-
const [password, setPassword] = useState("");
|
|
21
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
22
|
-
const [error, setError] = useState<string | null>(null);
|
|
23
|
-
|
|
24
|
-
const handleSignUp = async () => {
|
|
25
|
-
setIsLoading(true);
|
|
26
|
-
setError(null);
|
|
27
|
-
|
|
28
|
-
await authClient.signUp.email(
|
|
29
|
-
{
|
|
30
|
-
name,
|
|
31
|
-
email,
|
|
32
|
-
password,
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
onError: (error) => {
|
|
36
|
-
setError(error.error?.message || "Failed to sign up");
|
|
37
|
-
setIsLoading(false);
|
|
38
|
-
},
|
|
39
|
-
onSuccess: () => {
|
|
40
|
-
setName("");
|
|
41
|
-
setEmail("");
|
|
42
|
-
setPassword("");
|
|
43
|
-
queryClient.refetchQueries();
|
|
44
|
-
},
|
|
45
|
-
onFinished: () => {
|
|
46
|
-
setIsLoading(false);
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
return (
|
|
53
|
-
<View className="mt-6 p-4 bg-card rounded-lg border border-border">
|
|
54
|
-
<Text className="text-lg font-semibold text-foreground mb-4">
|
|
55
|
-
Create Account
|
|
56
|
-
</Text>
|
|
57
|
-
|
|
58
|
-
{error && (
|
|
59
|
-
<View className="mb-4 p-3 bg-destructive/10 rounded-md">
|
|
60
|
-
<Text className="text-destructive text-sm">{error}</Text>
|
|
61
|
-
</View>
|
|
62
|
-
)}
|
|
63
|
-
|
|
64
|
-
<TextInput
|
|
65
|
-
className="mb-3 p-4 rounded-md bg-input text-foreground border border-input"
|
|
66
|
-
placeholder="Name"
|
|
67
|
-
value={name}
|
|
68
|
-
onChangeText={setName}
|
|
69
|
-
placeholderTextColor="#9CA3AF"
|
|
70
|
-
/>
|
|
71
|
-
|
|
72
|
-
<TextInput
|
|
73
|
-
className="mb-3 p-4 rounded-md bg-input text-foreground border border-input"
|
|
74
|
-
placeholder="Email"
|
|
75
|
-
value={email}
|
|
76
|
-
onChangeText={setEmail}
|
|
77
|
-
placeholderTextColor="#9CA3AF"
|
|
78
|
-
keyboardType="email-address"
|
|
79
|
-
autoCapitalize="none"
|
|
80
|
-
/>
|
|
81
|
-
|
|
82
|
-
<TextInput
|
|
83
|
-
className="mb-4 p-4 rounded-md bg-input text-foreground border border-input"
|
|
84
|
-
placeholder="Password"
|
|
85
|
-
value={password}
|
|
86
|
-
onChangeText={setPassword}
|
|
87
|
-
placeholderTextColor="#9CA3AF"
|
|
88
|
-
secureTextEntry
|
|
89
|
-
/>
|
|
90
|
-
|
|
91
|
-
<TouchableOpacity
|
|
92
|
-
onPress={handleSignUp}
|
|
93
|
-
disabled={isLoading}
|
|
94
|
-
className="bg-primary p-4 rounded-md flex-row justify-center items-center"
|
|
95
|
-
>
|
|
96
|
-
{isLoading ? (
|
|
97
|
-
<ActivityIndicator size="small" color="#fff" />
|
|
98
|
-
) : (
|
|
99
|
-
<Text className="text-primary-foreground font-medium">Sign Up</Text>
|
|
100
|
-
)}
|
|
101
|
-
</TouchableOpacity>
|
|
102
|
-
</View>
|
|
103
|
-
);
|
|
104
|
-
}
|