Is there cleaner implementation for this?
Answered
Rhinelander posted this in #help-forum
RhinelanderOP
Trying to refactor some code. Help me improve it. Give me criticism. This is decently large project - splitting stuff in to multiple files, enterprise patterns, everything can be mentioned. I also use react-query if i could use it anywhere. Thank you!
Answered by Brown bear
export type InvitationStatus = 'pending' | 'accepted' | 'rejected';
export interface BaseInvitationData {
id: string;
email: string;
inviterEmail: string;
organizationName: string;
createdAt: string;
updatedAt: string;
}
export interface PendingInvitationData extends BaseInvitationData {
status: 'pending';
}
export interface AcceptedInvitationData extends BaseInvitationData {
status: 'accepted';
}
export interface RejectedInvitationData extends BaseInvitationData {
status: 'rejected';
}
export type InvitationData =
| PendingInvitationData
| AcceptedInvitationData
| RejectedInvitationData;
7 Replies
RhinelanderOP
Feel free to add feedback via Github or via Discord https://gist.github.com/jan-arnez/0ea1ae36125ff40bef7d0fe5711920da
Brown bear
Move the rendering logic to separate components
export default function InvitationPage() {
const params = useParams<{ id: string }>();
const {
invitation,
isLoading,
error,
acceptInvitation,
rejectInvitation,
isAccepting,
isRejecting,
} = useInvitation(params.id!);
if (isLoading) return <InvitationSkeleton />;
if (error) return <div>{error.message}</div>;
if (!invitation) return null;
return (
<div className="flex min-h-[80vh] items-center justify-center">
<Card className="w-full max-w-md">
<CardHeader>
<CardTitle>Organization Invitation</CardTitle>
<CardDescription>
You've been invited to join an organization
</CardDescription>
</CardHeader>
<CardContent>
<InvitationStatus invitation={invitation} />
</CardContent>
{invitation.status === "pending" && (
<CardFooter>
<InvitationActions
onAccept={acceptInvitation}
onReject={rejectInvitation}
isAccepting={isAccepting}
isRejecting={isRejecting}
/>
</CardFooter>
)}
</Card>
</div>
);
}
you can also create a custom hook with react query for handling the invitations
something like
export function useInvitation(id: string) {
const query = useQuery({
queryKey: ['invitation', id],
queryFn: async () => {
const response = await authClient.organization.getInvitation({
query: { id },
});
return response.data;
},
onError: (error: Error) => {
toast.error("Error", {
description: error.message,
});
},
});
const acceptMutation = useMutation({ /* code */ });
const rejectMutation = useMutation({ /* code */ });
return {
invitation: query.data,
isLoading: query.isLoading,
error: query.error,
acceptInvitation: acceptMutation.mutate,
rejectInvitation: rejectMutation.mutate,
isAccepting: acceptMutation.isPending,
isRejecting: rejectMutation.isPending,
};
}
finally, you're using typescript but you're not using types so probably a good idea to define them
Brown bear
export type InvitationStatus = 'pending' | 'accepted' | 'rejected';
export interface BaseInvitationData {
id: string;
email: string;
inviterEmail: string;
organizationName: string;
createdAt: string;
updatedAt: string;
}
export interface PendingInvitationData extends BaseInvitationData {
status: 'pending';
}
export interface AcceptedInvitationData extends BaseInvitationData {
status: 'accepted';
}
export interface RejectedInvitationData extends BaseInvitationData {
status: 'rejected';
}
export type InvitationData =
| PendingInvitationData
| AcceptedInvitationData
| RejectedInvitationData;
Answer
RhinelanderOP
Wow that was in depth. I appreciate that. Thank you!