create-croissant 0.1.38 → 0.1.40
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/package.json +9 -9
- package/template/README.md +4 -4
- package/template/apps/desktop/electron-builder.yml +6 -6
- package/template/apps/desktop/electron.vite.config.ts +8 -8
- package/template/apps/desktop/package.json +5 -5
- package/template/apps/desktop/src/main/index.ts +32 -32
- package/template/apps/desktop/src/preload/index.d.ts +3 -3
- package/template/apps/desktop/src/preload/index.ts +8 -8
- package/template/apps/desktop/src/renderer/src/App.tsx +5 -5
- package/template/apps/desktop/src/renderer/src/assets/base.css +4 -4
- package/template/apps/desktop/src/renderer/src/assets/main.css +3 -3
- package/template/apps/desktop/src/renderer/src/components/Versions.tsx +4 -4
- package/template/apps/desktop/src/renderer/src/main.tsx +7 -7
- package/template/apps/desktop/tsconfig.json +1 -4
- package/template/apps/desktop/tsconfig.node.json +7 -1
- package/template/apps/desktop/tsconfig.web.json +3 -9
- package/template/apps/mobile/app/(tabs)/_layout.tsx +11 -10
- package/template/apps/mobile/app/(tabs)/explore.tsx +29 -27
- package/template/apps/mobile/app/(tabs)/index.tsx +25 -24
- package/template/apps/mobile/app/_layout.tsx +8 -8
- package/template/apps/mobile/app/modal.tsx +6 -6
- package/template/apps/mobile/components/external-link.tsx +5 -5
- package/template/apps/mobile/components/haptic-tab.tsx +4 -4
- package/template/apps/mobile/components/hello-wave.tsx +5 -4
- package/template/apps/mobile/components/parallax-scroll-view.tsx +15 -13
- package/template/apps/mobile/components/themed-text.tsx +14 -14
- package/template/apps/mobile/components/themed-view.tsx +3 -3
- package/template/apps/mobile/components/ui/collapsible.tsx +14 -13
- package/template/apps/mobile/components/ui/icon-symbol.ios.tsx +4 -4
- package/template/apps/mobile/components/ui/icon-symbol.tsx +9 -9
- package/template/apps/mobile/constants/theme.ts +19 -19
- package/template/apps/mobile/hooks/use-color-scheme.ts +1 -1
- package/template/apps/mobile/hooks/use-color-scheme.web.ts +3 -3
- package/template/apps/mobile/hooks/use-theme-color.ts +4 -4
- package/template/apps/mobile/package.json +3 -3
- package/template/apps/mobile/scripts/reset-project.js +2 -2
- package/template/apps/mobile/tsconfig.json +2 -9
- package/template/apps/platform/drizzle.config.ts +5 -5
- package/template/apps/platform/package.json +4 -4
- package/template/apps/platform/src/components/app-sidebar.tsx +60 -69
- package/template/apps/platform/src/components/login-form.tsx +32 -39
- package/template/apps/platform/src/components/search-form.tsx +5 -13
- package/template/apps/platform/src/components/signup-form.tsx +39 -49
- package/template/apps/platform/src/components/version-switcher.tsx +11 -21
- package/template/apps/platform/src/lib/auth-utils.ts +12 -14
- package/template/apps/platform/src/lib/orpc.ts +17 -17
- package/template/apps/platform/src/router.tsx +5 -5
- package/template/apps/platform/src/routes/__root.tsx +13 -15
- package/template/apps/platform/src/routes/_auth/account.tsx +61 -50
- package/template/apps/platform/src/routes/_auth/dashboard.tsx +17 -17
- package/template/apps/platform/src/routes/_auth/examples/client-orpc-auth.tsx +13 -13
- package/template/apps/platform/src/routes/_auth/examples/ssr-orpc-auth.tsx +16 -16
- package/template/apps/platform/src/routes/_auth.tsx +5 -5
- package/template/apps/platform/src/routes/_public/examples/client-orpc.tsx +108 -88
- package/template/apps/platform/src/routes/_public/examples/isr.tsx +14 -14
- package/template/apps/platform/src/routes/_public/examples/ssr-orpc.tsx +92 -75
- package/template/apps/platform/src/routes/_public/index.tsx +22 -19
- package/template/apps/platform/src/routes/_public/login.tsx +4 -4
- package/template/apps/platform/src/routes/_public/signup.tsx +6 -5
- package/template/apps/platform/src/routes/_public.tsx +5 -5
- package/template/apps/platform/src/routes/api/auth/$.ts +13 -13
- package/template/apps/platform/src/routes/api/rpc.$.ts +13 -13
- package/template/apps/platform/vite.config.ts +8 -8
- package/template/docker-compose.yml +1 -1
- package/template/package.json +24 -26
- package/template/packages/auth/package.json +9 -9
- package/template/packages/auth/src/lib/auth.ts +1 -1
- package/template/packages/db/package.json +7 -7
- package/template/packages/db/src/index.ts +4 -4
- package/template/packages/db/src/schema.ts +2 -2
- package/template/packages/orpc/package.json +6 -6
- package/template/packages/orpc/src/lib/planets.ts +39 -43
- package/template/packages/orpc/src/lib/router.ts +15 -15
- package/template/packages/ui/package.json +10 -10
- package/template/packages/ui/src/components/accordion.tsx +20 -22
- package/template/packages/ui/src/components/alert-dialog.tsx +31 -56
- package/template/packages/ui/src/components/alert.tsx +15 -23
- package/template/packages/ui/src/components/aspect-ratio.tsx +3 -3
- package/template/packages/ui/src/components/avatar.tsx +19 -35
- package/template/packages/ui/src/components/badge.tsx +13 -17
- package/template/packages/ui/src/components/breadcrumb.tsx +22 -44
- package/template/packages/ui/src/components/button-group.tsx +16 -25
- package/template/packages/ui/src/components/button.tsx +8 -9
- package/template/packages/ui/src/components/calendar.tsx +43 -82
- package/template/packages/ui/src/components/card.tsx +15 -26
- package/template/packages/ui/src/components/carousel.tsx +70 -78
- package/template/packages/ui/src/components/chart.tsx +84 -117
- package/template/packages/ui/src/components/checkbox.tsx +8 -9
- package/template/packages/ui/src/components/collapsible.tsx +5 -9
- package/template/packages/ui/src/components/combobox.tsx +44 -68
- package/template/packages/ui/src/components/command.tsx +32 -47
- package/template/packages/ui/src/components/context-menu.tsx +45 -71
- package/template/packages/ui/src/components/dialog.tsx +29 -51
- package/template/packages/ui/src/components/direction.tsx +1 -4
- package/template/packages/ui/src/components/drawer.tsx +24 -38
- package/template/packages/ui/src/components/dropdown-menu.tsx +45 -55
- package/template/packages/ui/src/components/empty.tsx +16 -27
- package/template/packages/ui/src/components/field.tsx +49 -63
- package/template/packages/ui/src/components/hover-card.tsx +9 -14
- package/template/packages/ui/src/components/input-group.tsx +40 -52
- package/template/packages/ui/src/components/input-otp.tsx +17 -18
- package/template/packages/ui/src/components/input.tsx +6 -6
- package/template/packages/ui/src/components/item.tsx +31 -44
- package/template/packages/ui/src/components/kbd.tsx +5 -5
- package/template/packages/ui/src/components/label.tsx +6 -6
- package/template/packages/ui/src/components/menubar.tsx +51 -64
- package/template/packages/ui/src/components/mode-toggle.tsx +9 -15
- package/template/packages/ui/src/components/native-select.tsx +18 -24
- package/template/packages/ui/src/components/navigation-menu.tsx +28 -35
- package/template/packages/ui/src/components/pagination.tsx +19 -31
- package/template/packages/ui/src/components/popover.tsx +13 -26
- package/template/packages/ui/src/components/progress.tsx +13 -30
- package/template/packages/ui/src/components/radio-group.tsx +7 -7
- package/template/packages/ui/src/components/resizable.tsx +12 -20
- package/template/packages/ui/src/components/scroll-area.tsx +8 -12
- package/template/packages/ui/src/components/select.tsx +31 -42
- package/template/packages/ui/src/components/separator.tsx +6 -10
- package/template/packages/ui/src/components/sheet.tsx +25 -38
- package/template/packages/ui/src/components/sidebar.tsx +137 -170
- package/template/packages/ui/src/components/skeleton.tsx +3 -3
- package/template/packages/ui/src/components/slider.tsx +5 -5
- package/template/packages/ui/src/components/sonner.tsx +20 -24
- package/template/packages/ui/src/components/spinner.tsx +10 -5
- package/template/packages/ui/src/components/switch.tsx +6 -6
- package/template/packages/ui/src/components/table.tsx +18 -45
- package/template/packages/ui/src/components/tabs.tsx +14 -22
- package/template/packages/ui/src/components/textarea.tsx +5 -5
- package/template/packages/ui/src/components/theme-provider.tsx +43 -48
- package/template/packages/ui/src/components/toggle-group.tsx +18 -20
- package/template/packages/ui/src/components/toggle.tsx +9 -10
- package/template/packages/ui/src/components/tooltip.tsx +10 -22
- package/template/packages/ui/src/hooks/use-mobile.ts +11 -11
- package/template/packages/ui/src/lib/utils.ts +4 -4
- package/template/packages/ui/src/styles/globals.css +106 -106
- package/template/turbo.json +15 -6
- package/template/.prettierignore +0 -10
- package/template/apps/desktop/.prettierignore +0 -6
- package/template/apps/desktop/eslint.config.ts +0 -11
- package/template/apps/desktop/prettier.config.ts +0 -3
- package/template/apps/mobile/eslint.config.js +0 -10
- package/template/apps/platform/eslint.config.ts +0 -11
- package/template/apps/platform/prettier.config.ts +0 -3
- package/template/packages/auth/eslint.config.ts +0 -3
- package/template/packages/auth/prettier.config.ts +0 -3
- package/template/packages/config-eslint/index.ts +0 -24
- package/template/packages/config-eslint/package.json +0 -11
- package/template/packages/config-prettier/index.ts +0 -14
- package/template/packages/config-prettier/package.json +0 -7
- package/template/packages/db/eslint.config.ts +0 -3
- package/template/packages/db/prettier.config.ts +0 -3
- package/template/packages/orpc/eslint.config.ts +0 -3
- package/template/packages/orpc/prettier.config.ts +0 -3
- package/template/packages/ui/eslint.config.ts +0 -3
- package/template/packages/ui/prettier.config.ts +0 -3
- package/template/prettier.config.ts +0 -15
|
@@ -1,26 +1,22 @@
|
|
|
1
|
-
import * as React from "react"
|
|
2
|
-
import { createFileRoute } from "@tanstack/react-router"
|
|
3
|
-
import { Check, Pencil, Plus, Trash2 } from "lucide-react"
|
|
4
|
-
import { toast } from "sonner"
|
|
5
|
-
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
|
6
|
-
import { useForm } from "@tanstack/react-form"
|
|
7
|
-
import { type } from "arktype"
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
3
|
+
import { Check, Pencil, Plus, Trash2 } from "lucide-react";
|
|
4
|
+
import { toast } from "sonner";
|
|
5
|
+
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
6
|
+
import { useForm } from "@tanstack/react-form";
|
|
7
|
+
import { type } from "arktype";
|
|
8
8
|
|
|
9
|
-
import { Button } from "@workspace/ui/components/button"
|
|
10
|
-
import { Input } from "@workspace/ui/components/input"
|
|
11
|
-
import {
|
|
12
|
-
Field,
|
|
13
|
-
FieldError,
|
|
14
|
-
FieldLabel,
|
|
15
|
-
} from "@workspace/ui/components/field"
|
|
9
|
+
import { Button } from "@workspace/ui/components/button";
|
|
10
|
+
import { Input } from "@workspace/ui/components/input";
|
|
11
|
+
import { Field, FieldError, FieldLabel } from "@workspace/ui/components/field";
|
|
16
12
|
|
|
17
|
-
import type { router } from "@workspace/orpc/router"
|
|
18
|
-
import type { InferRouterInputs, InferRouterOutputs } from "@orpc/server"
|
|
19
|
-
import { orpc } from "@/lib/orpc"
|
|
13
|
+
import type { router } from "@workspace/orpc/router";
|
|
14
|
+
import type { InferRouterInputs, InferRouterOutputs } from "@orpc/server";
|
|
15
|
+
import { orpc } from "@/lib/orpc";
|
|
20
16
|
|
|
21
|
-
type Inputs = InferRouterInputs<typeof router
|
|
22
|
-
type Outputs = InferRouterOutputs<typeof router
|
|
23
|
-
type Planet = Outputs["planets"]["getPlanets"][number]
|
|
17
|
+
type Inputs = InferRouterInputs<typeof router>;
|
|
18
|
+
type Outputs = InferRouterOutputs<typeof router>;
|
|
19
|
+
type Planet = Outputs["planets"]["getPlanets"][number];
|
|
24
20
|
|
|
25
21
|
const planetSchema = type({
|
|
26
22
|
name: "string>0",
|
|
@@ -29,13 +25,13 @@ const planetSchema = type({
|
|
|
29
25
|
diameter: "string",
|
|
30
26
|
}).narrow((data, ctx) => {
|
|
31
27
|
if (isNaN(parseFloat(data.distance))) {
|
|
32
|
-
ctx.error({ message: "Must be a number", path: ["distance"] })
|
|
28
|
+
ctx.error({ message: "Must be a number", path: ["distance"] });
|
|
33
29
|
}
|
|
34
30
|
if (isNaN(parseFloat(data.diameter))) {
|
|
35
|
-
ctx.error({ message: "Must be a number", path: ["diameter"] })
|
|
31
|
+
ctx.error({ message: "Must be a number", path: ["diameter"] });
|
|
36
32
|
}
|
|
37
|
-
return true
|
|
38
|
-
})
|
|
33
|
+
return true;
|
|
34
|
+
});
|
|
39
35
|
|
|
40
36
|
export const Route = createFileRoute("/_public/examples/client-orpc")({
|
|
41
37
|
head: () => ({
|
|
@@ -50,28 +46,28 @@ export const Route = createFileRoute("/_public/examples/client-orpc")({
|
|
|
50
46
|
],
|
|
51
47
|
}),
|
|
52
48
|
component: ClientORPC,
|
|
53
|
-
})
|
|
49
|
+
});
|
|
54
50
|
|
|
55
51
|
function ClientORPC() {
|
|
56
|
-
const queryClient = useQueryClient()
|
|
57
|
-
const [editingId, setEditingId] = React.useState<number | null>(null)
|
|
58
|
-
|
|
52
|
+
const queryClient = useQueryClient();
|
|
53
|
+
const [editingId, setEditingId] = React.useState<number | null>(null);
|
|
54
|
+
|
|
59
55
|
const { data: planets = [], isLoading } = useQuery({
|
|
60
56
|
queryKey: ["planets"],
|
|
61
57
|
queryFn: () => orpc.planets.getPlanets(),
|
|
62
|
-
})
|
|
58
|
+
});
|
|
63
59
|
|
|
64
60
|
const form = useForm({
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
61
|
+
defaultValues: {
|
|
62
|
+
name: "",
|
|
63
|
+
description: "",
|
|
64
|
+
distance: "0",
|
|
65
|
+
diameter: "0",
|
|
66
|
+
},
|
|
67
|
+
validators: {
|
|
68
|
+
onChange: planetSchema,
|
|
69
|
+
},
|
|
70
|
+
onSubmit: async ({ value }) => {
|
|
75
71
|
if (editingId) {
|
|
76
72
|
await updateMutation.mutateAsync({
|
|
77
73
|
id: editingId,
|
|
@@ -80,7 +76,7 @@ function ClientORPC() {
|
|
|
80
76
|
distanceFromSun: parseFloat(value.distance),
|
|
81
77
|
diameter: parseFloat(value.diameter),
|
|
82
78
|
hasRings: false,
|
|
83
|
-
})
|
|
79
|
+
});
|
|
84
80
|
} else {
|
|
85
81
|
await createMutation.mutateAsync({
|
|
86
82
|
name: value.name,
|
|
@@ -88,69 +84,71 @@ function ClientORPC() {
|
|
|
88
84
|
distanceFromSun: parseFloat(value.distance),
|
|
89
85
|
diameter: parseFloat(value.diameter),
|
|
90
86
|
hasRings: false,
|
|
91
|
-
})
|
|
87
|
+
});
|
|
92
88
|
}
|
|
93
89
|
},
|
|
94
|
-
})
|
|
90
|
+
});
|
|
95
91
|
|
|
96
92
|
const resetForm = () => {
|
|
97
|
-
form.reset()
|
|
98
|
-
setEditingId(null)
|
|
99
|
-
}
|
|
93
|
+
form.reset();
|
|
94
|
+
setEditingId(null);
|
|
95
|
+
};
|
|
100
96
|
|
|
101
97
|
const createMutation = useMutation({
|
|
102
98
|
mutationFn: (input: Inputs["planets"]["createPlanet"]) => orpc.planets.createPlanet(input),
|
|
103
99
|
onSuccess: () => {
|
|
104
|
-
queryClient.invalidateQueries({ queryKey: ["planets"] })
|
|
105
|
-
resetForm()
|
|
106
|
-
toast.success("Planet added successfully")
|
|
100
|
+
queryClient.invalidateQueries({ queryKey: ["planets"] });
|
|
101
|
+
resetForm();
|
|
102
|
+
toast.success("Planet added successfully");
|
|
107
103
|
},
|
|
108
104
|
onError: (err) => {
|
|
109
|
-
toast.error(err.message || "Failed to add planet")
|
|
105
|
+
toast.error(err.message || "Failed to add planet");
|
|
110
106
|
},
|
|
111
|
-
})
|
|
107
|
+
});
|
|
112
108
|
|
|
113
109
|
const updateMutation = useMutation({
|
|
114
110
|
mutationFn: (input: Inputs["planets"]["updatePlanet"]) => orpc.planets.updatePlanet(input),
|
|
115
111
|
onSuccess: () => {
|
|
116
|
-
queryClient.invalidateQueries({ queryKey: ["planets"] })
|
|
117
|
-
resetForm()
|
|
118
|
-
toast.success("Planet updated successfully")
|
|
112
|
+
queryClient.invalidateQueries({ queryKey: ["planets"] });
|
|
113
|
+
resetForm();
|
|
114
|
+
toast.success("Planet updated successfully");
|
|
119
115
|
},
|
|
120
116
|
onError: (err) => {
|
|
121
|
-
toast.error(err.message || "Failed to update planet")
|
|
117
|
+
toast.error(err.message || "Failed to update planet");
|
|
122
118
|
},
|
|
123
|
-
})
|
|
119
|
+
});
|
|
124
120
|
|
|
125
121
|
const deleteMutation = useMutation({
|
|
126
122
|
mutationFn: (input: Inputs["planets"]["deletePlanet"]) => orpc.planets.deletePlanet(input),
|
|
127
123
|
onSuccess: () => {
|
|
128
|
-
queryClient.invalidateQueries({ queryKey: ["planets"] })
|
|
129
|
-
toast.success("Planet deleted successfully")
|
|
124
|
+
queryClient.invalidateQueries({ queryKey: ["planets"] });
|
|
125
|
+
toast.success("Planet deleted successfully");
|
|
130
126
|
},
|
|
131
127
|
onError: (err) => {
|
|
132
|
-
toast.error(err.message || "Failed to delete planet")
|
|
128
|
+
toast.error(err.message || "Failed to delete planet");
|
|
133
129
|
},
|
|
134
|
-
})
|
|
130
|
+
});
|
|
135
131
|
|
|
136
132
|
const handleDelete = async (id: number) => {
|
|
137
|
-
if (!confirm("Are you sure you want to delete this planet?")) return
|
|
138
|
-
await deleteMutation.mutateAsync({ id })
|
|
139
|
-
}
|
|
133
|
+
if (!confirm("Are you sure you want to delete this planet?")) return;
|
|
134
|
+
await deleteMutation.mutateAsync({ id });
|
|
135
|
+
};
|
|
140
136
|
|
|
141
137
|
const startEdit = (planet: Planet) => {
|
|
142
|
-
setEditingId(planet.id)
|
|
143
|
-
form.setFieldValue("name", planet.name)
|
|
144
|
-
form.setFieldValue("description", planet.description || "")
|
|
145
|
-
form.setFieldValue("distance", planet.distanceFromSun.toString())
|
|
146
|
-
form.setFieldValue("diameter", planet.diameter.toString())
|
|
147
|
-
}
|
|
138
|
+
setEditingId(planet.id);
|
|
139
|
+
form.setFieldValue("name", planet.name);
|
|
140
|
+
form.setFieldValue("description", planet.description || "");
|
|
141
|
+
form.setFieldValue("distance", planet.distanceFromSun.toString());
|
|
142
|
+
form.setFieldValue("diameter", planet.diameter.toString());
|
|
143
|
+
};
|
|
148
144
|
|
|
149
145
|
return (
|
|
150
146
|
<div className="flex flex-col gap-8">
|
|
151
147
|
<div>
|
|
152
148
|
<h1 className="text-2xl font-bold mb-2">Client + oRPC CRUD</h1>
|
|
153
|
-
<p className="text-muted-foreground">
|
|
149
|
+
<p className="text-muted-foreground">
|
|
150
|
+
Manage planets directly from the client using TanStack Query, TanStack Form and oRPC.
|
|
151
|
+
</p>
|
|
154
152
|
</div>
|
|
155
153
|
|
|
156
154
|
<div className="rounded-lg border p-6 bg-muted/30">
|
|
@@ -160,16 +158,18 @@ function ClientORPC() {
|
|
|
160
158
|
</h2>
|
|
161
159
|
<form
|
|
162
160
|
onSubmit={(e) => {
|
|
163
|
-
e.preventDefault()
|
|
164
|
-
e.stopPropagation()
|
|
165
|
-
form.handleSubmit()
|
|
161
|
+
e.preventDefault();
|
|
162
|
+
e.stopPropagation();
|
|
163
|
+
form.handleSubmit();
|
|
166
164
|
}}
|
|
167
165
|
>
|
|
168
166
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
169
167
|
<form.Field
|
|
170
168
|
name="name"
|
|
171
169
|
children={(field) => (
|
|
172
|
-
<Field
|
|
170
|
+
<Field
|
|
171
|
+
data-invalid={field.state.meta.isTouched && field.state.meta.errors.length > 0}
|
|
172
|
+
>
|
|
173
173
|
<FieldLabel htmlFor={field.name}>Name</FieldLabel>
|
|
174
174
|
<Input
|
|
175
175
|
id={field.name}
|
|
@@ -186,7 +186,9 @@ function ClientORPC() {
|
|
|
186
186
|
<form.Field
|
|
187
187
|
name="description"
|
|
188
188
|
children={(field) => (
|
|
189
|
-
<Field
|
|
189
|
+
<Field
|
|
190
|
+
data-invalid={field.state.meta.isTouched && field.state.meta.errors.length > 0}
|
|
191
|
+
>
|
|
190
192
|
<FieldLabel htmlFor={field.name}>Description</FieldLabel>
|
|
191
193
|
<Input
|
|
192
194
|
id={field.name}
|
|
@@ -203,7 +205,9 @@ function ClientORPC() {
|
|
|
203
205
|
<form.Field
|
|
204
206
|
name="distance"
|
|
205
207
|
children={(field) => (
|
|
206
|
-
<Field
|
|
208
|
+
<Field
|
|
209
|
+
data-invalid={field.state.meta.isTouched && field.state.meta.errors.length > 0}
|
|
210
|
+
>
|
|
207
211
|
<FieldLabel htmlFor={field.name}>Distance (M km)</FieldLabel>
|
|
208
212
|
<Input
|
|
209
213
|
id={field.name}
|
|
@@ -220,7 +224,9 @@ function ClientORPC() {
|
|
|
220
224
|
<form.Field
|
|
221
225
|
name="diameter"
|
|
222
226
|
children={(field) => (
|
|
223
|
-
<Field
|
|
227
|
+
<Field
|
|
228
|
+
data-invalid={field.state.meta.isTouched && field.state.meta.errors.length > 0}
|
|
229
|
+
>
|
|
224
230
|
<FieldLabel htmlFor={field.name}>Diameter (km)</FieldLabel>
|
|
225
231
|
<Input
|
|
226
232
|
id={field.name}
|
|
@@ -242,24 +248,31 @@ function ClientORPC() {
|
|
|
242
248
|
<>
|
|
243
249
|
{editingId ? (
|
|
244
250
|
<>
|
|
245
|
-
<Button
|
|
251
|
+
<Button
|
|
246
252
|
type="submit"
|
|
247
253
|
className="flex items-center gap-2"
|
|
248
254
|
disabled={!canSubmit || isSubmitting || updateMutation.isPending}
|
|
249
255
|
>
|
|
250
|
-
<Check className="h-4 w-4" />
|
|
256
|
+
<Check className="h-4 w-4" />{" "}
|
|
257
|
+
{isSubmitting || updateMutation.isPending ? "Saving..." : "Save Changes"}
|
|
251
258
|
</Button>
|
|
252
|
-
<Button
|
|
259
|
+
<Button
|
|
260
|
+
variant="outline"
|
|
261
|
+
type="button"
|
|
262
|
+
onClick={resetForm}
|
|
263
|
+
disabled={isSubmitting || updateMutation.isPending}
|
|
264
|
+
>
|
|
253
265
|
Cancel
|
|
254
266
|
</Button>
|
|
255
267
|
</>
|
|
256
268
|
) : (
|
|
257
|
-
<Button
|
|
269
|
+
<Button
|
|
258
270
|
type="submit"
|
|
259
271
|
className="flex items-center gap-2"
|
|
260
272
|
disabled={!canSubmit || isSubmitting || createMutation.isPending}
|
|
261
273
|
>
|
|
262
|
-
<Plus className="h-4 w-4" />
|
|
274
|
+
<Plus className="h-4 w-4" />{" "}
|
|
275
|
+
{isSubmitting || createMutation.isPending ? "Adding..." : "Add Planet"}
|
|
263
276
|
</Button>
|
|
264
277
|
)}
|
|
265
278
|
</>
|
|
@@ -278,13 +291,20 @@ function ClientORPC() {
|
|
|
278
291
|
) : (
|
|
279
292
|
<div className="grid grid-cols-1 gap-3">
|
|
280
293
|
{planets.map((planet) => (
|
|
281
|
-
<div
|
|
294
|
+
<div
|
|
295
|
+
key={planet.id}
|
|
296
|
+
className="flex items-center justify-between rounded-lg border p-4 bg-background shadow-sm hover:shadow-md transition-shadow"
|
|
297
|
+
>
|
|
282
298
|
<div className="flex-1">
|
|
283
299
|
<div className="flex items-center gap-2">
|
|
284
300
|
<span className="font-bold text-lg">{planet.name}</span>
|
|
285
|
-
<span className="text-xs bg-muted px-2 py-0.5 rounded-full text-muted-foreground">
|
|
301
|
+
<span className="text-xs bg-muted px-2 py-0.5 rounded-full text-muted-foreground">
|
|
302
|
+
ID: {planet.id}
|
|
303
|
+
</span>
|
|
286
304
|
</div>
|
|
287
|
-
<p className="text-sm text-muted-foreground">
|
|
305
|
+
<p className="text-sm text-muted-foreground">
|
|
306
|
+
{planet.description || "No description provided."}
|
|
307
|
+
</p>
|
|
288
308
|
<div className="mt-2 flex gap-4 text-xs text-muted-foreground font-mono">
|
|
289
309
|
<span>Distance: {planet.distanceFromSun} M km</span>
|
|
290
310
|
<span>Diameter: {planet.diameter} km</span>
|
|
@@ -294,9 +314,9 @@ function ClientORPC() {
|
|
|
294
314
|
<Button variant="outline" size="icon" onClick={() => startEdit(planet)}>
|
|
295
315
|
<Pencil className="h-4 w-4" />
|
|
296
316
|
</Button>
|
|
297
|
-
<Button
|
|
298
|
-
variant="destructive"
|
|
299
|
-
size="icon"
|
|
317
|
+
<Button
|
|
318
|
+
variant="destructive"
|
|
319
|
+
size="icon"
|
|
300
320
|
onClick={() => handleDelete(planet.id)}
|
|
301
321
|
disabled={deleteMutation.isPending}
|
|
302
322
|
>
|
|
@@ -309,5 +329,5 @@ function ClientORPC() {
|
|
|
309
329
|
)}
|
|
310
330
|
</div>
|
|
311
331
|
</div>
|
|
312
|
-
)
|
|
332
|
+
);
|
|
313
333
|
}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { createFileRoute } from "@tanstack/react-router"
|
|
2
|
-
import { createServerFn } from "@tanstack/react-start"
|
|
3
|
-
import { orpc } from "@/lib/orpc"
|
|
1
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
2
|
+
import { createServerFn } from "@tanstack/react-start";
|
|
3
|
+
import { orpc } from "@/lib/orpc";
|
|
4
4
|
|
|
5
5
|
const getISRData = createServerFn({ method: "GET" }).handler(async () => {
|
|
6
6
|
// In a real ISR scenario, this would be cached on the server
|
|
7
7
|
// For this example, we'll fetch planets via oRPC
|
|
8
|
-
const planets = await orpc.planets.getPlanets()
|
|
8
|
+
const planets = await orpc.planets.getPlanets();
|
|
9
9
|
|
|
10
10
|
return {
|
|
11
11
|
generatedAt: new Date().toISOString(),
|
|
12
12
|
planets,
|
|
13
13
|
message:
|
|
14
14
|
"This page is an example of ISR. In a production build with proper configuration, this data would be cached and updated in the background.",
|
|
15
|
-
}
|
|
16
|
-
})
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
17
|
|
|
18
18
|
export const Route = createFileRoute("/_public/examples/isr")({
|
|
19
19
|
head: () => ({
|
|
@@ -23,8 +23,7 @@ export const Route = createFileRoute("/_public/examples/isr")({
|
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
name: "description",
|
|
26
|
-
content:
|
|
27
|
-
"Experience high-performance page loads with ISR in Croissant Stack.",
|
|
26
|
+
content: "Experience high-performance page loads with ISR in Croissant Stack.",
|
|
28
27
|
},
|
|
29
28
|
],
|
|
30
29
|
}),
|
|
@@ -34,16 +33,16 @@ export const Route = createFileRoute("/_public/examples/isr")({
|
|
|
34
33
|
"Cache-Control": "public, max-age=10, s-maxage=10, stale-while-revalidate=60",
|
|
35
34
|
}),
|
|
36
35
|
component: ISRExample,
|
|
37
|
-
})
|
|
36
|
+
});
|
|
38
37
|
|
|
39
38
|
function ISRExample() {
|
|
40
|
-
const { generatedAt, message, planets } = Route.useLoaderData()
|
|
39
|
+
const { generatedAt, message, planets } = Route.useLoaderData();
|
|
41
40
|
|
|
42
41
|
return (
|
|
43
42
|
<div className="flex flex-col gap-4">
|
|
44
43
|
<h1 className="text-2xl font-bold">ISR Example + oRPC</h1>
|
|
45
44
|
<p>{message}</p>
|
|
46
|
-
|
|
45
|
+
|
|
47
46
|
<div className="rounded-lg border p-4">
|
|
48
47
|
<h2 className="font-semibold">Generated At (Server-side):</h2>
|
|
49
48
|
<p className="font-mono">{generatedAt}</p>
|
|
@@ -63,10 +62,11 @@ function ISRExample() {
|
|
|
63
62
|
</ul>
|
|
64
63
|
)}
|
|
65
64
|
</div>
|
|
66
|
-
|
|
65
|
+
|
|
67
66
|
<p className="text-sm text-muted-foreground">
|
|
68
|
-
Refresh the page to see if the time updates. In a true ISR setup, it would only update after
|
|
67
|
+
Refresh the page to see if the time updates. In a true ISR setup, it would only update after
|
|
68
|
+
a certain interval.
|
|
69
69
|
</p>
|
|
70
70
|
</div>
|
|
71
|
-
)
|
|
71
|
+
);
|
|
72
72
|
}
|