Added update lnk

This commit is contained in:
sianida26 2024-02-18 05:01:45 +07:00
parent 0a848d9458
commit 27fdced0c9
4 changed files with 163 additions and 11 deletions

View File

@ -0,0 +1,81 @@
"use server";
import db from "@/core/db";
import checkPermission from "@/modules/dashboard/services/checkPermission";
import ServerResponseAction from "@/modules/dashboard/types/ServerResponseAction";
import handleCatch from "@/modules/dashboard/utils/handleCatch";
import notFound from "@/modules/dashboard/utils/notFound";
import unauthorized from "@/modules/dashboard/utils/unauthorized";
import "server-only";
import ResellerOffice365Error from "../errors/ResellerOffice365Error";
import { revalidatePath } from "next/cache";
interface Args {
id: string;
data: {
linkId: string;
link: string;
}[];
}
export default async function inputLink(
args: Args
): Promise<ServerResponseAction> {
try {
//TODO: Implement permission
if (!(await checkPermission("authenticated-only")))
return unauthorized();
const data = await db.office365LinkRequest.findFirst({
where: {
id: args.id,
},
include: {
links: true,
},
});
if (!data)
return notFound({
message:
"The requested link is not found. It might seems has been deleted. Please contact administrator",
});
if (data.status !== "WAITING")
throw new ResellerOffice365Error({
errorCode: "REQUEST_IS_NOT_IN_WAITING_STATE",
message: `This request has been ${
data.acceptedAt
? "completed"
: data.rejectedAt
? "rejected"
: "cancelled"
} thus cannot be updated. Please contact administrator`,
});
await db.office365LinkRequest.update({
where: {
id: args.id,
},
data: {
acceptedAt: new Date(),
status: "ACCEPTED",
links: {
updateMany: args.data.map((linkItem) => ({
where: { id: linkItem.linkId },
data: {
link: linkItem.link,
},
})),
},
},
});
revalidatePath(".")
return {
success: true,
};
} catch (e) {
return handleCatch(e);
}
}

View File

@ -0,0 +1,25 @@
import DashboardError from "@/modules/dashboard/errors/DashboardError";
export const ResellerOffice365ErrorCodes = [
"REQUEST_IS_NOT_IN_WAITING_STATE"
] as const;
interface ResellerOffice365ErrorOptions {
message?: string;
errorCode: (typeof ResellerOffice365ErrorCodes)[number] | (string & {});
formErrors?: Record<string, string>
}
export default class ResellerOffice365Error extends DashboardError {
public readonly errorCode: ResellerOffice365ErrorOptions['errorCode'];
public readonly formErrors?: ResellerOffice365ErrorOptions['formErrors']
constructor(options: ResellerOffice365ErrorOptions) {
super({
errorCode: options.errorCode,
message: options.message,
});
this.errorCode = options.errorCode;
}
}

View File

@ -34,6 +34,7 @@ import { notifications } from "@mantine/notifications";
import DashboardError from "@/modules/dashboard/errors/DashboardError"; import DashboardError from "@/modules/dashboard/errors/DashboardError";
import getLinkRequestDataById from "../actions/getLinkRequestDataById"; import getLinkRequestDataById from "../actions/getLinkRequestDataById";
import { isPagesAPIRouteMatch } from "next/dist/server/future/route-matches/pages-api-route-match"; import { isPagesAPIRouteMatch } from "next/dist/server/future/route-matches/pages-api-route-match";
import inputLink from "../actions/inputLinks";
export interface ModalProps { export interface ModalProps {
title: string; title: string;
@ -89,6 +90,8 @@ export default function RequestModal(props: ModalProps) {
activePeriod: item.activePeriod, activePeriod: item.activePeriod,
email: item.email, email: item.email,
endUserQty: item.numberOfUsers, endUserQty: item.numberOfUsers,
id: item.id,
link: item.link ?? "",
})), })),
}); });
}) })
@ -116,6 +119,7 @@ export default function RequestModal(props: ModalProps) {
email: "", email: "",
activePeriod: "2 Years", activePeriod: "2 Years",
endUserQty: 1, endUserQty: 1,
link: "",
}, },
], ],
}, },
@ -132,6 +136,7 @@ export default function RequestModal(props: ModalProps) {
email: "", email: "",
activePeriod: "2 Years", activePeriod: "2 Years",
endUserQty: 1, endUserQty: 1,
link: "",
}); });
} }
@ -154,10 +159,9 @@ export default function RequestModal(props: ModalProps) {
if (!submitableState.includes(formState)) return; //prevent submit when not in subitable state if (!submitableState.includes(formState)) return; //prevent submit when not in subitable state
setFormState("submitting");
switch (props.type) { switch (props.type) {
case "create": { case "create": {
setFormState("submitting");
withServerAction(createLinkRequest, values) withServerAction(createLinkRequest, values)
.then((response) => { .then((response) => {
notifications.show({ notifications.show({
@ -192,16 +196,43 @@ export default function RequestModal(props: ModalProps) {
break; break;
} }
case "input link": { case "input link": {
//TODO: Handle add link if (!props.detailId) return;
setFormState("submitting");
withServerAction(inputLink, {
id: props.detailId,
data: form.values.details.map((item) => ({
link: item.link,
linkId: item.id ?? "",
})),
})
.then(() => {
setFormState("idle");
notifications.show({
message: "Data has been updated",
color: "green",
});
closeModal();
})
.catch((e) => {
if (e instanceof Error) {
setErrorMessage(e.message);
} else {
setErrorMessage("An unkown error occured");
}
})
.finally(() => {
setFormState("idle");
});
} }
} }
}; };
const disableChange = formState !== "idle"; const disableChange = formState !== "idle";
const readonly = ["input link", "detail"].includes(props.type) const readonly = ["input link", "detail"].includes(props.type);
const showSkeleton = formState === "fetching"; const showSkeleton = formState === "fetching";
const showActivationLink = ["input link", "detail"].includes(props.type) const showActivationLink = ["input link", "detail"].includes(props.type);
const enableInputActivationLink = props.type === "input link" const enableInputActivationLink = props.type === "input link";
const showSubmitButton = ["create", "input link"].includes(props.type);
return ( return (
<Modal <Modal
@ -294,10 +325,21 @@ export default function RequestModal(props: ModalProps) {
<Skeleton visible={showSkeleton}> <Skeleton visible={showSkeleton}>
<TextInput <TextInput
label="Activation Link" label="Activation Link"
required required={
enableInputActivationLink
}
disabled={disableChange} disabled={disableChange}
readOnly={!enableInputActivationLink} readOnly={
placeholder={enableInputActivationLink ? "Enter link here" : "No link provided"} !enableInputActivationLink
}
{...form.getInputProps(
`details.${i}.link`
)}
placeholder={
enableInputActivationLink
? "Enter link here"
: "No link provided"
}
/> />
</Skeleton> </Skeleton>
)} )}
@ -315,7 +357,7 @@ export default function RequestModal(props: ModalProps) {
> >
Close Close
</Button> </Button>
{formState === "waiting" && ( {showSubmitButton && (
<Button <Button
variant="filled" variant="filled"
leftSection={<TbDeviceFloppy size={20} />} leftSection={<TbDeviceFloppy size={20} />}
@ -325,7 +367,9 @@ export default function RequestModal(props: ModalProps) {
)} )}
loading={["submitting"].includes(formState)} loading={["submitting"].includes(formState)}
> >
Make Request {props.type === "create"
? "Make Request"
: "Save"}
</Button> </Button>
)} )}
</Flex> </Flex>

View File

@ -2,8 +2,10 @@ interface RequestLinkForm {
id: string | undefined; id: string | undefined;
numberOfLinks: number; numberOfLinks: number;
details: { details: {
id?: string;
email: string; email: string;
activePeriod: (typeof resellerOffice365Config.activePeriods)[number]; activePeriod: (typeof resellerOffice365Config.activePeriods)[number];
endUserQty: number; endUserQty: number;
link: string
}[]; }[];
} }