1- import {
2- useLoaderData ,
3- useActionData ,
4- useNavigation ,
5- Form ,
6- redirect ,
7- type ActionFunctionArgs ,
8- } from "react-router" ;
1+ import { useLoaderData , useNavigation , Form , type ActionFunctionArgs } from "react-router" ;
92import { z } from "zod" ;
103import { InputWithLabel } from "~/components/input-with-label" ;
114import { Button } from "~/components/ui/button" ;
@@ -27,64 +20,60 @@ import {
2720} from "~/components/ui/alert-dialog" ;
2821import { useState } from "react" ;
2922import { auth } from "~/lib/auth" ;
30- import { ensureCanWithIdentity } from "~/lib/permissions.server" ;
31- import { getUserInformation } from "~/lib/identity.server" ;
23+
3224import { createProtectedLoader } from "~/lib/secureRoute" ;
3325
34- const orgNameSchema = z . object ( {
35- name : z . string ( ) . min ( 1 , "Name is required" ) ,
36- } ) ;
26+ // const orgNameSchema = z.object({
27+ // name: z.string().min(1, "Name is required"),
28+ // });
3729
3830// TODO: Move to secureRoute, split up into multiple actions
3931export async function action ( { request } : ActionFunctionArgs ) {
40- const identity = await getUserInformation ( request ) ;
41-
42- const formData = await request . formData ( ) ;
43- const intent = formData . get ( "intent" ) ;
44- const name = formData . get ( "name" ) as string | undefined ;
45- const organizationId = formData . get ( "organizationId" ) as string ;
46-
47- if ( intent === "edit" ) {
48- ensureCanWithIdentity ( identity , "update" , "Organization" ) ;
49-
50- try {
51- const validated = orgNameSchema . parse ( { name } ) ;
52- // TODO: Replace with actual updateOrganization API if available
53- if ( typeof auth . api . updateOrganization !== "function" ) {
54- return { error : "Organization update API not implemented" } ;
55- }
56- await auth . api . updateOrganization ( {
57- headers : request . headers ,
58- body : {
59- organizationId,
60- data : {
61- name : validated . name ,
62- } ,
63- } ,
64- } ) ;
65- return { success : true } ;
66- } catch ( error ) {
67- if ( error instanceof z . ZodError ) {
68- return { errors : error . flatten ( ) . fieldErrors } ;
69- }
70- return { error : "Failed to update organization" } ;
71- }
72- }
73-
74- if ( intent === "delete" ) {
75- ensureCanWithIdentity ( identity , "delete" , "Organization" ) ;
76-
77- if ( typeof auth . api . deleteOrganization !== "function" ) {
78- return { error : "Organization delete API not implemented" } ;
79- }
80- await auth . api . deleteOrganization ( {
81- headers : request . headers ,
82- body : {
83- organizationId,
84- } ,
85- } ) ;
86- return redirect ( "/app/organization/select" ) ;
87- }
32+ // const identity = await getUserInformation(request);
33+
34+ // const formData = await request.formData();
35+ // const intent = formData.get("intent");
36+ // // const name = formData.get("name") as string | undefined;
37+ // const organizationId = formData.get("organizationId") as string;
38+
39+ // if (intent === "edit") {
40+ // ensureCanWithIdentity(identity, "update", "Organization");
41+
42+ // try {
43+ // const validated = orgNameSchema.parse({ name });
44+
45+ // await auth.api.updateOrganization({
46+ // headers: request.headers,
47+ // body: {
48+ // organizationId,
49+ // data: {
50+ // name: validated.name,
51+ // },
52+ // },
53+ // });
54+ // return { success: true };
55+ // } catch (error) {
56+ // if (error instanceof z.ZodError) {
57+ // return { errors: error.flatten().fieldErrors };
58+ // }
59+ // return { error: "Failed to update organization" };
60+ // }
61+ // }
62+
63+ // if (intent === "delete") {
64+ // ensureCanWithIdentity(identity, "delete", "Organization");
65+
66+ // if (typeof auth.api.deleteOrganization !== "function") {
67+ // return { error: "Organization delete API not implemented" };
68+ // }
69+ // await auth.api.deleteOrganization({
70+ // headers: request.headers,
71+ // body: {
72+ // organizationId,
73+ // },
74+ // });
75+ // return redirect("/app/organization/select");
76+ // }
8877
8978 return null ;
9079}
@@ -107,7 +96,6 @@ export const loader = createProtectedLoader({
10796
10897export default function OrganizationGeneral ( ) {
10998 const { activeOrg } = useLoaderData < { activeOrg : { id : string ; name : string ; slug : string } } > ( ) ;
110- const actionData = useActionData < typeof action > ( ) ;
11199 const navigation = useNavigation ( ) ;
112100 const isSubmitting = navigation . state === "submitting" ;
113101 const [ showDeleteDialog , setShowDeleteDialog ] = useState ( false ) ;
@@ -119,14 +107,15 @@ export default function OrganizationGeneral() {
119107 < CardTitle > Organization Details</ CardTitle >
120108 < CardDescription > Manage your organization settings.</ CardDescription >
121109 </ CardHeader >
122- < Form method = "post" autoComplete = "off" >
110+ < Form method = "post" action = "/app/organization/edit" autoComplete = "off" >
111+ { /* TODO: add error feedback from action */ }
123112 < CardContent className = "space-y-4 py-4" >
124113 < InputWithLabel
125114 label = "Name"
126115 id = "name"
127116 name = "name"
128117 defaultValue = { activeOrg . name }
129- error = { actionData ?. errors ?. name ?. [ 0 ] }
118+ // error={actionData?.errors?.name?.[0]}
130119 autoFocus
131120 />
132121 < input type = "hidden" name = "organizationId" value = { activeOrg . id } />
@@ -136,10 +125,12 @@ export default function OrganizationGeneral() {
136125 < Button type = "submit" disabled = { isSubmitting } className = "w-full" >
137126 { isSubmitting ? "Saving..." : "Save Changes" }
138127 </ Button >
139- { actionData ?. error && (
128+ { /* TODO: add error feedback from action */ }
129+
130+ { /* {actionData?.error && (
140131 <div className="text-destructive text-sm text-center">{actionData.error}</div>
141- ) }
142- { actionData ?. success && < div className = "text-success text-sm text-center" > Saved!</ div > }
132+ )} */ }
133+ { /* { actionData?.success && <div className="text-success text-sm text-center">Saved!</div>} */ }
143134 </ CardFooter >
144135 </ Form >
145136 </ Card >
@@ -172,7 +163,7 @@ export default function OrganizationGeneral() {
172163 undone.
173164 </ AlertDialogDescription >
174165 </ AlertDialogHeader >
175- < Form method = "post" >
166+ < Form method = "post" action = "/app/organization/delete" >
176167 < input type = "hidden" name = "organizationId" value = { activeOrg . id } />
177168 < input type = "hidden" name = "intent" value = "delete" />
178169 < AlertDialogFooter >
0 commit comments