Add error handling to upsert role
This commit is contained in:
parent
2e04483343
commit
bae8a2aa3e
|
|
@ -1,9 +1,11 @@
|
|||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import DashboardError from "@/features/dashboard/errors/DashboardError";
|
||||
import getRoleById from "@/features/dashboard/roles/actions/getRoleById";
|
||||
import upsertRole from "@/features/dashboard/roles/actions/upsertRole";
|
||||
import roleFormDataSchema, {
|
||||
RoleFormData,
|
||||
} from "@/features/dashboard/roles/formSchemas/RoleFormData";
|
||||
import withErrorHandling from "@/features/dashboard/utils/withServerAction";
|
||||
import { showNotification } from "@/utils/notifications";
|
||||
import {
|
||||
Flex,
|
||||
|
|
@ -17,6 +19,7 @@ import {
|
|||
Checkbox,
|
||||
Skeleton,
|
||||
Fieldset,
|
||||
Alert,
|
||||
} from "@mantine/core";
|
||||
import { useForm, zodResolver } from "@mantine/form";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
|
@ -41,6 +44,7 @@ export default function FormModal(props: ModalProps) {
|
|||
const router = useRouter();
|
||||
const [isSubmitting, setSubmitting] = useState(false);
|
||||
const [isFetching, setFetching] = useState(false);
|
||||
const [errorMessage, setErrorMessage] = useState("");
|
||||
|
||||
const form = useForm<RoleFormData>({
|
||||
initialValues: {
|
||||
|
|
@ -93,21 +97,29 @@ export default function FormModal(props: ModalProps) {
|
|||
};
|
||||
|
||||
const handleSubmit = (values: RoleFormData) => {
|
||||
upsertRole(values)
|
||||
setSubmitting(true);
|
||||
withErrorHandling(() => upsertRole(values))
|
||||
.then((response) => {
|
||||
if (response.success) {
|
||||
showNotification(response.message, "success");
|
||||
return closeModal();
|
||||
} else {
|
||||
form.setErrors(response.errors ?? {});
|
||||
if (!response.errors) {
|
||||
showNotification(response.message, "error");
|
||||
}
|
||||
}
|
||||
showNotification(response.message!, "success");
|
||||
closeModal();
|
||||
})
|
||||
.catch((e) => {
|
||||
//TODO: Handle Error
|
||||
console.log(e);
|
||||
if (e instanceof DashboardError) {
|
||||
if (e.errorCode === "INVALID_FORM_DATA") {
|
||||
form.setErrors(e.formErrors ?? {});
|
||||
} else {
|
||||
setErrorMessage(`ERROR: ${e.message} (${e.errorCode})`);
|
||||
}
|
||||
} else if (e instanceof Error) {
|
||||
setErrorMessage(`ERROR: ${e.message}`);
|
||||
} else {
|
||||
setErrorMessage(
|
||||
`Unkown error is occured. Please contact administrator`
|
||||
);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
setSubmitting(false);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -121,6 +133,7 @@ export default function FormModal(props: ModalProps) {
|
|||
>
|
||||
<form onSubmit={form.onSubmit(handleSubmit)}>
|
||||
<Stack mt="sm" gap="lg" px="lg">
|
||||
{errorMessage && <Alert color="red">{errorMessage}</Alert>}
|
||||
{/* ID */}
|
||||
{form.values.id ? (
|
||||
<TextInput
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ export const DashboardErrorCodes = [
|
|||
"UNAUTHORIZED",
|
||||
"NOT_FOUND",
|
||||
"UNKNOWN_ERROR",
|
||||
"INVALID_FORM_DATA"
|
||||
"INVALID_FORM_DATA",
|
||||
] as const;
|
||||
|
||||
interface ErrorOptions {
|
||||
|
|
@ -14,7 +14,7 @@ interface ErrorOptions {
|
|||
}
|
||||
|
||||
export default class DashboardError extends Error {
|
||||
public readonly errorCode: string;
|
||||
public readonly errorCode: typeof DashboardErrorCodes[number] | string & {};
|
||||
public readonly formErrors?: {[k: string]: string}
|
||||
// public readonly data: object;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,39 +2,40 @@
|
|||
|
||||
import checkPermission from "@/features/auth/tools/checkPermission";
|
||||
import roleFormDataSchema, { RoleFormData } from "../formSchemas/RoleFormData";
|
||||
import { unauthorized } from "@/BaseError";
|
||||
import mapObjectToFirstValue from "@/utils/mapObjectToFirstValue";
|
||||
import prisma from "@/db";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import ServerResponse from "@/types/Action";
|
||||
import DashboardError, { handleCatch, unauthorized } from "../../errors/DashboardError";
|
||||
|
||||
/**
|
||||
* Upserts a role based on the provided RoleFormData.
|
||||
* If the role already exists (determined by `id`), it updates the role; otherwise, it creates a new role.
|
||||
* Authorization checks are performed based on whether it's a create or update operation.
|
||||
*
|
||||
* @param {RoleFormData} data - The data for creating or updating the role.
|
||||
* @returns {Promise<object>} An object containing the success status, message, and any errors.
|
||||
* @param data - The data for creating or updating the role.
|
||||
* @returns An object containing the success status, message, and any errors.
|
||||
*/
|
||||
export default async function upsertRole(data: RoleFormData) {
|
||||
export default async function upsertRole(
|
||||
data: RoleFormData
|
||||
): Promise<ServerResponse> {
|
||||
try {
|
||||
const isInsert = !data.id;
|
||||
|
||||
// Authorization check
|
||||
const permissionType = isInsert ? "role.create" : "role.update";
|
||||
if (!await checkPermission(permissionType)) {
|
||||
if (!(await checkPermission(permissionType))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
// Validate form data
|
||||
const validatedFields = roleFormDataSchema.safeParse(data);
|
||||
if (!validatedFields.success) {
|
||||
return {
|
||||
success: false,
|
||||
message: "Invalid Form Data",
|
||||
errors: mapObjectToFirstValue(validatedFields.error.flatten().fieldErrors),
|
||||
};
|
||||
throw new DashboardError({
|
||||
errorCode: "INVALID_FORM_DATA",
|
||||
formErrors: mapObjectToFirstValue(validatedFields.error.flatten().fieldErrors)
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
const roleData = {
|
||||
code: validatedFields.data.code,
|
||||
description: validatedFields.data.description,
|
||||
|
|
@ -44,6 +45,18 @@ export default async function upsertRole(data: RoleFormData) {
|
|||
|
||||
// Database operation
|
||||
if (isInsert) {
|
||||
if (await prisma.role.findFirst({
|
||||
where: {
|
||||
code: roleData.code
|
||||
}
|
||||
})){
|
||||
throw new DashboardError({
|
||||
errorCode: "INVALID_FORM_DATA",
|
||||
formErrors: {
|
||||
code: "The code is already exists"
|
||||
}
|
||||
})
|
||||
}
|
||||
await prisma.role.create({ data: roleData });
|
||||
} else {
|
||||
await prisma.role.update({
|
||||
|
|
@ -58,13 +71,11 @@ export default async function upsertRole(data: RoleFormData) {
|
|||
// Return success message
|
||||
return {
|
||||
success: true,
|
||||
message: `Role ${validatedFields.data.name} has been successfully ${isInsert ? "created" : "updated"}.`,
|
||||
message: `Role ${validatedFields.data.name} has been successfully ${
|
||||
isInsert ? "created" : "updated"
|
||||
}.`,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error updating role data', error);
|
||||
return {
|
||||
success: false,
|
||||
message: "Error updating role data.",
|
||||
};
|
||||
return handleCatch(error)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ export interface RoleFormData {
|
|||
|
||||
const roleFormDataSchema = z.object({
|
||||
id: z.string().nullable(),
|
||||
name: z.string(),
|
||||
code: z.string(),
|
||||
name: z.string().min(1),
|
||||
code: z.string().min(1),
|
||||
description: z.string(),
|
||||
isActive: z.boolean(),
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user