create-better-t-stack 3.2.23-canary.2b547ed5 → 3.2.23-canary.b8d62867
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/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{src-ehteLbIu.js → src-VoUvj8ZF.js} +2 -2
- package/package.json +1 -1
- package/templates/addons/biome/biome.json.hbs +5 -0
- package/templates/examples/todo/native/bare/app/(drawer)/todos.tsx.hbs +313 -222
- package/templates/frontend/native/bare/components/header-button.tsx.hbs +3 -3
- /package/templates/auth/clerk/convex/native/base/app/(auth)/{sign-out.tsx.hbs → sign-up.tsx.hbs} +0 -0
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as router, i as init, n as createBtsCli, o as sponsors, r as docs, t as builder } from "./src-
|
|
2
|
+
import { a as router, i as init, n as createBtsCli, o as sponsors, r as docs, t as builder } from "./src-VoUvj8ZF.js";
|
|
3
3
|
|
|
4
4
|
export { builder, createBtsCli, docs, init, router, sponsors };
|
|
@@ -146,7 +146,7 @@ const dependencyVersionMap = {
|
|
|
146
146
|
"nitro-cloudflare-dev": "^0.2.2",
|
|
147
147
|
"@sveltejs/adapter-cloudflare": "^7.2.1",
|
|
148
148
|
"@cloudflare/workers-types": "^4.20250822.0",
|
|
149
|
-
alchemy: "^0.
|
|
149
|
+
alchemy: "^0.77.0",
|
|
150
150
|
dotenv: "^17.2.2",
|
|
151
151
|
tsdown: "^0.15.5",
|
|
152
152
|
zod: "^4.1.11",
|
|
@@ -976,7 +976,7 @@ async function getFrontendChoice(frontendOptions, backend, auth) {
|
|
|
976
976
|
},
|
|
977
977
|
{
|
|
978
978
|
value: "native-uniwind",
|
|
979
|
-
label: "
|
|
979
|
+
label: "Uniwind",
|
|
980
980
|
hint: "Use Tailwind CSS for React Native"
|
|
981
981
|
},
|
|
982
982
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "3.2.23-canary.
|
|
3
|
+
"version": "3.2.23-canary.b8d62867",
|
|
4
4
|
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,10 +22,10 @@ import { useColorScheme } from "@/lib/use-color-scheme";
|
|
|
22
22
|
import { NAV_THEME } from "@/lib/constants";
|
|
23
23
|
{{#unless (eq backend "convex")}}
|
|
24
24
|
{{#if (eq api "orpc")}}
|
|
25
|
-
|
|
25
|
+
import { orpc } from "@/utils/orpc";
|
|
26
26
|
{{/if}}
|
|
27
27
|
{{#if (eq api "trpc")}}
|
|
28
|
-
|
|
28
|
+
import { trpc } from "@/utils/trpc";
|
|
29
29
|
{{/if}}
|
|
30
30
|
{{/unless}}
|
|
31
31
|
|
|
@@ -33,109 +33,122 @@ export default function TodosScreen() {
|
|
|
33
33
|
const { colorScheme } = useColorScheme();
|
|
34
34
|
const theme = colorScheme === "dark" ? NAV_THEME.dark : NAV_THEME.light;
|
|
35
35
|
const [newTodoText, setNewTodoText] = useState("");
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
{{#if (eq backend "convex")}}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
const todos = useQuery(api.todos.getAll);
|
|
39
|
+
const createTodoMutation = useMutation(api.todos.create);
|
|
40
|
+
const toggleTodoMutation = useMutation(api.todos.toggle);
|
|
41
|
+
const deleteTodoMutation = useMutation(api.todos.deleteTodo);
|
|
42
|
+
|
|
43
|
+
async function handleAddTodo() {
|
|
44
|
+
const text = newTodoText.trim();
|
|
45
|
+
if (!text) return;
|
|
46
|
+
await createTodoMutation({ text });
|
|
47
|
+
setNewTodoText("");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function handleToggleTodo(id: Id<"todos">, currentCompleted: boolean) {
|
|
51
|
+
toggleTodoMutation({ id, completed: !currentCompleted });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function handleDeleteTodo(id: Id<"todos">) {
|
|
55
|
+
Alert.alert("Delete Todo", "Are you sure you want to delete this todo?", [
|
|
56
|
+
{ text: "Cancel", style: "cancel" },
|
|
57
|
+
{
|
|
58
|
+
text: "Delete",
|
|
59
|
+
style: "destructive",
|
|
60
|
+
onPress: () => deleteTodoMutation({ id }),
|
|
61
|
+
},
|
|
62
|
+
]);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const isLoading = !todos;
|
|
66
|
+
const completedCount = todos?.filter((t) => t.completed).length || 0;
|
|
67
|
+
const totalCount = todos?.length || 0;
|
|
42
68
|
{{else}}
|
|
43
69
|
{{#if (eq api "orpc")}}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
70
|
+
const todos = useQuery(orpc.todo.getAll.queryOptions());
|
|
71
|
+
const createMutation = useMutation(
|
|
72
|
+
orpc.todo.create.mutationOptions({
|
|
73
|
+
onSuccess: () => {
|
|
74
|
+
todos.refetch();
|
|
75
|
+
setNewTodoText("");
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
);
|
|
79
|
+
const toggleMutation = useMutation(
|
|
80
|
+
orpc.todo.toggle.mutationOptions({
|
|
81
|
+
onSuccess: () => {
|
|
82
|
+
todos.refetch();
|
|
83
|
+
},
|
|
84
|
+
})
|
|
85
|
+
);
|
|
86
|
+
const deleteMutation = useMutation(
|
|
87
|
+
orpc.todo.delete.mutationOptions({
|
|
88
|
+
onSuccess: () => {
|
|
89
|
+
todos.refetch();
|
|
90
|
+
},
|
|
91
|
+
})
|
|
92
|
+
);
|
|
61
93
|
{{/if}}
|
|
62
94
|
{{#if (eq api "trpc")}}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
95
|
+
const todos = useQuery(trpc.todo.getAll.queryOptions());
|
|
96
|
+
const createMutation = useMutation(
|
|
97
|
+
trpc.todo.create.mutationOptions({
|
|
98
|
+
onSuccess: () => {
|
|
99
|
+
todos.refetch();
|
|
100
|
+
setNewTodoText("");
|
|
101
|
+
},
|
|
102
|
+
})
|
|
103
|
+
);
|
|
104
|
+
const toggleMutation = useMutation(
|
|
105
|
+
trpc.todo.toggle.mutationOptions({
|
|
106
|
+
onSuccess: () => {
|
|
107
|
+
todos.refetch();
|
|
108
|
+
},
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
const deleteMutation = useMutation(
|
|
112
|
+
trpc.todo.delete.mutationOptions({
|
|
113
|
+
onSuccess: () => {
|
|
114
|
+
todos.refetch();
|
|
115
|
+
},
|
|
116
|
+
})
|
|
117
|
+
);
|
|
80
118
|
{{/if}}
|
|
81
|
-
{{/if}}
|
|
82
|
-
|
|
83
|
-
{{#if (eq backend "convex")}}
|
|
84
|
-
async function handleAddTodo() {
|
|
85
|
-
const text = newTodoText.trim();
|
|
86
|
-
if (!text) return;
|
|
87
|
-
await createTodoMutation({ text });
|
|
88
|
-
setNewTodoText("");
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function handleToggleTodo(id: Id<"todos">, currentCompleted: boolean) {
|
|
92
|
-
toggleTodoMutation({ id, completed: !currentCompleted });
|
|
93
|
-
}
|
|
94
119
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
{
|
|
99
|
-
text: "Delete",
|
|
100
|
-
style: "destructive",
|
|
101
|
-
onPress: () => deleteTodoMutation({ id }),
|
|
102
|
-
},
|
|
103
|
-
]);
|
|
120
|
+
function handleAddTodo() {
|
|
121
|
+
if (newTodoText.trim()) {
|
|
122
|
+
createMutation.mutate({ text: newTodoText });
|
|
104
123
|
}
|
|
124
|
+
}
|
|
105
125
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
{{else}}
|
|
110
|
-
function handleAddTodo() {
|
|
111
|
-
if (newTodoText.trim()) {
|
|
112
|
-
createMutation.mutate({ text: newTodoText });
|
|
113
|
-
}
|
|
114
|
-
}
|
|
126
|
+
function handleToggleTodo(id: number, completed: boolean) {
|
|
127
|
+
toggleMutation.mutate({ id, completed: !completed });
|
|
128
|
+
}
|
|
115
129
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
onPress: () => deleteMutation.mutate({ id }),
|
|
127
|
-
},
|
|
128
|
-
]);
|
|
129
|
-
}
|
|
130
|
+
function handleDeleteTodo(id: number) {
|
|
131
|
+
Alert.alert("Delete Todo", "Are you sure you want to delete this todo?", [
|
|
132
|
+
{ text: "Cancel", style: "cancel" },
|
|
133
|
+
{
|
|
134
|
+
text: "Delete",
|
|
135
|
+
style: "destructive",
|
|
136
|
+
onPress: () => deleteMutation.mutate({ id }),
|
|
137
|
+
},
|
|
138
|
+
]);
|
|
139
|
+
}
|
|
130
140
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
141
|
+
const isLoading = todos?.isLoading;
|
|
142
|
+
const completedCount = todos?.data?.filter((t) => t.completed).length || 0;
|
|
143
|
+
const totalCount = todos?.data?.length || 0;
|
|
134
144
|
{{/if}}
|
|
135
145
|
|
|
136
146
|
return (
|
|
137
147
|
<Container>
|
|
138
|
-
<ScrollView
|
|
148
|
+
<ScrollView
|
|
149
|
+
style={styles.scrollView}
|
|
150
|
+
contentContainerStyle={styles.contentContainer}
|
|
151
|
+
>
|
|
139
152
|
<View style={styles.header}>
|
|
140
153
|
<View style={styles.headerRow}>
|
|
141
154
|
<Text style={[styles.title, { color: theme.text }]}>
|
|
@@ -150,8 +163,12 @@ export default function TodosScreen() {
|
|
|
150
163
|
)}
|
|
151
164
|
</View>
|
|
152
165
|
</View>
|
|
153
|
-
|
|
154
|
-
|
|
166
|
+
<View
|
|
167
|
+
style={[
|
|
168
|
+
styles.inputCard,
|
|
169
|
+
{ backgroundColor: theme.card, borderColor: theme.border },
|
|
170
|
+
]}
|
|
171
|
+
>
|
|
155
172
|
<View style={styles.inputRow}>
|
|
156
173
|
<View style={styles.inputContainer}>
|
|
157
174
|
<TextInput
|
|
@@ -160,164 +177,239 @@ export default function TodosScreen() {
|
|
|
160
177
|
placeholder="Add a new task..."
|
|
161
178
|
placeholderTextColor={theme.text}
|
|
162
179
|
{{#unless (eq backend "convex")}}
|
|
163
|
-
|
|
180
|
+
editable={!createMutation.isPending}
|
|
164
181
|
{{/unless}}
|
|
165
182
|
onSubmitEditing={handleAddTodo}
|
|
166
183
|
returnKeyType="done"
|
|
167
|
-
style={[
|
|
184
|
+
style={[
|
|
185
|
+
styles.input,
|
|
186
|
+
{
|
|
187
|
+
color: theme.text,
|
|
188
|
+
borderColor: theme.border,
|
|
189
|
+
backgroundColor: theme.background,
|
|
190
|
+
},
|
|
191
|
+
]}
|
|
168
192
|
/>
|
|
169
193
|
</View>
|
|
170
194
|
<TouchableOpacity
|
|
171
195
|
onPress={handleAddTodo}
|
|
172
196
|
{{#if (eq backend "convex")}}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
197
|
+
disabled={!newTodoText.trim()}
|
|
198
|
+
style={[
|
|
199
|
+
styles.addButton,
|
|
200
|
+
{
|
|
201
|
+
backgroundColor: !newTodoText.trim()
|
|
202
|
+
? theme.border
|
|
203
|
+
: theme.primary,
|
|
204
|
+
opacity: !newTodoText.trim() ? 0.5 : 1,
|
|
205
|
+
},
|
|
206
|
+
]}
|
|
207
|
+
>
|
|
208
|
+
<Ionicons
|
|
209
|
+
name="add"
|
|
210
|
+
size={24}
|
|
211
|
+
color={newTodoText.trim() ? "#ffffff" : theme.text}
|
|
212
|
+
/>
|
|
187
213
|
{{else}}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
214
|
+
disabled={createMutation.isPending || !newTodoText.trim()}
|
|
215
|
+
style={[
|
|
216
|
+
styles.addButton,
|
|
217
|
+
{
|
|
218
|
+
backgroundColor:
|
|
219
|
+
createMutation.isPending || !newTodoText.trim()
|
|
220
|
+
? theme.border
|
|
221
|
+
: theme.primary,
|
|
222
|
+
opacity:
|
|
223
|
+
createMutation.isPending || !newTodoText.trim() ? 0.5 : 1,
|
|
224
|
+
},
|
|
225
|
+
]}
|
|
226
|
+
>
|
|
227
|
+
{createMutation.isPending ? (
|
|
228
|
+
<ActivityIndicator size="small" color="#ffffff" />
|
|
229
|
+
) : (
|
|
230
|
+
<Ionicons name="add" size={24} color="#ffffff" />
|
|
231
|
+
)}
|
|
206
232
|
{{/if}}
|
|
207
233
|
</TouchableOpacity>
|
|
208
234
|
</View>
|
|
209
235
|
</View>
|
|
210
236
|
|
|
211
237
|
{{#if (eq backend "convex")}}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
238
|
+
{isLoading && (
|
|
239
|
+
<View style={styles.centerContainer}>
|
|
240
|
+
<ActivityIndicator size="large" color={theme.primary} />
|
|
241
|
+
<Text
|
|
242
|
+
style={[styles.loadingText, { color: theme.text, opacity: 0.7 }]}
|
|
243
|
+
>
|
|
244
|
+
Loading todos...
|
|
245
|
+
</Text>
|
|
246
|
+
</View>
|
|
247
|
+
)}
|
|
220
248
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
249
|
+
{todos && todos.length === 0 && !isLoading && (
|
|
250
|
+
<View
|
|
251
|
+
style={[
|
|
252
|
+
styles.emptyCard,
|
|
253
|
+
{ backgroundColor: theme.card, borderColor: theme.border },
|
|
254
|
+
]}
|
|
255
|
+
>
|
|
256
|
+
<Ionicons
|
|
257
|
+
name="checkbox-outline"
|
|
258
|
+
size={64}
|
|
259
|
+
color={theme.text}
|
|
260
|
+
style=\{{ opacity: 0.5, marginBottom: 16 }}
|
|
261
|
+
/>
|
|
262
|
+
<Text style={[styles.emptyTitle, { color: theme.text }]}>
|
|
263
|
+
No todos yet
|
|
264
|
+
</Text>
|
|
265
|
+
<Text
|
|
266
|
+
style={[styles.emptyText, { color: theme.text, opacity: 0.7 }]}
|
|
267
|
+
>
|
|
268
|
+
Add your first task to get started!
|
|
269
|
+
</Text>
|
|
270
|
+
</View>
|
|
271
|
+
)}
|
|
232
272
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
273
|
+
{todos && todos.length > 0 && (
|
|
274
|
+
<View style={styles.todosList}>
|
|
275
|
+
{todos.map((todo) => (
|
|
276
|
+
<View
|
|
277
|
+
key={todo._id}
|
|
278
|
+
style={[
|
|
279
|
+
styles.todoCard,
|
|
280
|
+
{ backgroundColor: theme.card, borderColor: theme.border },
|
|
281
|
+
]}
|
|
282
|
+
>
|
|
283
|
+
<View style={styles.todoRow}>
|
|
284
|
+
<TouchableOpacity
|
|
285
|
+
onPress={() => handleToggleTodo(todo._id, todo.completed)}
|
|
286
|
+
style={[styles.checkbox, { borderColor: theme.border }]}
|
|
287
|
+
>
|
|
288
|
+
{todo.completed && (
|
|
289
|
+
<Ionicons
|
|
290
|
+
name="checkmark"
|
|
291
|
+
size={16}
|
|
292
|
+
color={theme.primary}
|
|
293
|
+
/>
|
|
294
|
+
)}
|
|
295
|
+
</TouchableOpacity>
|
|
296
|
+
<View style={styles.todoTextContainer}>
|
|
297
|
+
<Text
|
|
298
|
+
style={[
|
|
248
299
|
styles.todoText,
|
|
249
300
|
{ color: theme.text },
|
|
250
|
-
todo.completed && {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
<TouchableOpacity
|
|
256
|
-
onPress={() => handleDeleteTodo(todo._id)}
|
|
257
|
-
style=\{{ styles.deleteButton }}
|
|
301
|
+
todo.completed && {
|
|
302
|
+
textDecorationLine: "line-through",
|
|
303
|
+
opacity: 0.5,
|
|
304
|
+
},
|
|
305
|
+
]}
|
|
258
306
|
>
|
|
259
|
-
|
|
260
|
-
</
|
|
307
|
+
{todo.text}
|
|
308
|
+
</Text>
|
|
261
309
|
</View>
|
|
310
|
+
<TouchableOpacity
|
|
311
|
+
onPress={() => handleDeleteTodo(todo._id)}
|
|
312
|
+
style={styles.deleteButton}
|
|
313
|
+
>
|
|
314
|
+
<Ionicons
|
|
315
|
+
name="trash-outline"
|
|
316
|
+
size={24}
|
|
317
|
+
color={theme.notification}
|
|
318
|
+
/>
|
|
319
|
+
</TouchableOpacity>
|
|
262
320
|
</View>
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
321
|
+
</View>
|
|
322
|
+
))}
|
|
323
|
+
</View>
|
|
324
|
+
)}
|
|
266
325
|
{{else}}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
326
|
+
{isLoading && (
|
|
327
|
+
<View style={styles.centerContainer}>
|
|
328
|
+
<ActivityIndicator size="large" color={theme.primary} />
|
|
329
|
+
<Text
|
|
330
|
+
style={[styles.loadingText, { color: theme.text, opacity: 0.7 }]}
|
|
331
|
+
>
|
|
332
|
+
Loading todos...
|
|
333
|
+
</Text>
|
|
334
|
+
</View>
|
|
335
|
+
)}
|
|
275
336
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
337
|
+
{todos?.data && todos.data.length === 0 && !isLoading && (
|
|
338
|
+
<View
|
|
339
|
+
style={[
|
|
340
|
+
styles.emptyCard,
|
|
341
|
+
{ backgroundColor: theme.card, borderColor: theme.border },
|
|
342
|
+
]}
|
|
343
|
+
>
|
|
344
|
+
<Ionicons
|
|
345
|
+
name="checkbox-outline"
|
|
346
|
+
size={64}
|
|
347
|
+
color={theme.text}
|
|
348
|
+
style=\{{ opacity: 0.5, marginBottom: 16 }}
|
|
349
|
+
/>
|
|
350
|
+
<Text style={[styles.emptyTitle, { color: theme.text }]}>
|
|
351
|
+
No todos yet
|
|
352
|
+
</Text>
|
|
353
|
+
<Text
|
|
354
|
+
style={[styles.emptyText, { color: theme.text, opacity: 0.7 }]}
|
|
355
|
+
>
|
|
356
|
+
Add your first task to get started!
|
|
357
|
+
</Text>
|
|
358
|
+
</View>
|
|
359
|
+
)}
|
|
287
360
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
361
|
+
{todos?.data && todos.data.length > 0 && (
|
|
362
|
+
<View style={styles.todosList}>
|
|
363
|
+
{todos.data.map((todo) => (
|
|
364
|
+
<View
|
|
365
|
+
key={todo.id}
|
|
366
|
+
style={[
|
|
367
|
+
styles.todoCard,
|
|
368
|
+
{ backgroundColor: theme.card, borderColor: theme.border },
|
|
369
|
+
]}
|
|
370
|
+
>
|
|
371
|
+
<View style={styles.todoRow}>
|
|
372
|
+
<TouchableOpacity
|
|
373
|
+
onPress={() => handleToggleTodo(todo.id, todo.completed)}
|
|
374
|
+
style={[styles.checkbox, { borderColor: theme.border }]}
|
|
375
|
+
>
|
|
376
|
+
{todo.completed && (
|
|
377
|
+
<Ionicons
|
|
378
|
+
name="checkmark"
|
|
379
|
+
size={16}
|
|
380
|
+
color={theme.primary}
|
|
381
|
+
/>
|
|
382
|
+
)}
|
|
383
|
+
</TouchableOpacity>
|
|
384
|
+
<View style={styles.todoTextContainer}>
|
|
385
|
+
<Text
|
|
386
|
+
style={[
|
|
303
387
|
styles.todoText,
|
|
304
388
|
{ color: theme.text },
|
|
305
|
-
todo.completed && {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
<TouchableOpacity
|
|
311
|
-
onPress={() => handleDeleteTodo(todo.id)}
|
|
312
|
-
style={styles.deleteButton}
|
|
389
|
+
todo.completed && {
|
|
390
|
+
textDecorationLine: "line-through",
|
|
391
|
+
opacity: 0.5,
|
|
392
|
+
},
|
|
393
|
+
]}
|
|
313
394
|
>
|
|
314
|
-
|
|
315
|
-
</
|
|
395
|
+
{todo.text}
|
|
396
|
+
</Text>
|
|
316
397
|
</View>
|
|
398
|
+
<TouchableOpacity
|
|
399
|
+
onPress={() => handleDeleteTodo(todo.id)}
|
|
400
|
+
style={styles.deleteButton}
|
|
401
|
+
>
|
|
402
|
+
<Ionicons
|
|
403
|
+
name="trash-outline"
|
|
404
|
+
size={24}
|
|
405
|
+
color={theme.notification}
|
|
406
|
+
/>
|
|
407
|
+
</TouchableOpacity>
|
|
317
408
|
</View>
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
409
|
+
</View>
|
|
410
|
+
))}
|
|
411
|
+
</View>
|
|
412
|
+
)}
|
|
321
413
|
{{/if}}
|
|
322
414
|
</ScrollView>
|
|
323
415
|
</Container>
|
|
@@ -426,5 +518,4 @@ const styles = StyleSheet.create({
|
|
|
426
518
|
deleteButton: {
|
|
427
519
|
padding: 8,
|
|
428
520
|
},
|
|
429
|
-
});
|
|
430
|
-
|
|
521
|
+
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import FontAwesome from "@expo/vector-icons/FontAwesome";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
|
-
import { Pressable, StyleSheet } from "react-native";
|
|
3
|
+
import { Pressable, StyleSheet, View } from "react-native";
|
|
4
4
|
import { useColorScheme } from "@/lib/use-color-scheme";
|
|
5
5
|
import { NAV_THEME } from "@/lib/constants";
|
|
6
6
|
|
|
7
7
|
export const HeaderButton = forwardRef<
|
|
8
|
-
|
|
8
|
+
View,
|
|
9
9
|
{ onPress?: () => void }
|
|
10
10
|
>(({ onPress }, ref) => {
|
|
11
11
|
const { colorScheme } = useColorScheme();
|
|
@@ -19,7 +19,7 @@ export const HeaderButton = forwardRef<
|
|
|
19
19
|
styles.button,
|
|
20
20
|
{
|
|
21
21
|
backgroundColor: pressed
|
|
22
|
-
? theme.
|
|
22
|
+
? theme.background
|
|
23
23
|
: theme.card,
|
|
24
24
|
},
|
|
25
25
|
]}
|
/package/templates/auth/clerk/convex/native/base/app/(auth)/{sign-out.tsx.hbs → sign-up.tsx.hbs}
RENAMED
|
File without changes
|