diff --git a/server/socket.ts b/server/socket.ts deleted file mode 100644 index 1269481..0000000 --- a/server/socket.ts +++ /dev/null @@ -1,101 +0,0 @@ -import getUserFromToken from "@/modules/auth/utils/getUserFromToken"; -import { User } from "@prisma/client"; -import prisma from "@/core/db"; -import Bun from "bun"; - -const intents = { - listenMyWaitingLinkRequest: "listenMyWaitingLinkRequest", -} as const; - -const waitingLinkRequestConnections: Map< - string, - Bun.ServerWebSocket<{ - channel: string; - user: User; - intent: string; - }> -> = new Map(); - -export const server = Bun.serve<{ - channel: string; - user: User; - intent: string; -}>({ - async fetch(req, server) { - const url = new URL(req.url); - req.headers.getSetCookie(); - const pathname = url.pathname; - - const cookies = req.headers.get("Cookie"); - - // Extract the Authorization header - const authHeader = req.headers.get("Authorization"); - const token = authHeader?.startsWith("Bearer ") - ? authHeader.substring(7, authHeader.length) - : null; - - const user = token ? await getUserFromToken(token) : null; - - const intent = pathname.substring(1); - - switch (intent) { - case `/${intents.listenMyWaitingLinkRequest}`: { - if (!user) { - return new Response("Unauthorized", { status: 401 }); - } - const channel = `mwrl-${user.id}`; - const success = server.upgrade(req, { - data: { user, channel, intent }, - }); - if (success) return undefined; - break; - } - default: { - return new Response(""); - } - } - }, - websocket: { - async open(ws) { - switch (ws.data.intent) { - case intents.listenMyWaitingLinkRequest: { - ws.subscribe(ws.data.channel); - - //retrieve user's link requests with status of waiting - const result = await prisma.office365LinkRequest.findMany({ - where: { - createdBy: ws.data.user.id, - status: "WAITING", - }, - select: { - id: true, - }, - }); - - server.publish(ws.data.channel, JSON.stringify(result)); - - waitingLinkRequestConnections.set(ws.data.channel, ws); - } - } - }, - - message(ws, message) { - // the server re-broadcasts incoming messages to everyone - // server.publish("the-group-chat", `: ${message}`); - }, - close(ws) { - // const msg = ` has left the chat`; - // server.publish("the-group-chat", msg); - // ws.unsubscribe("the-group-chat"); - switch (ws.data.intent) { - case intents.listenMyWaitingLinkRequest: { - ws.unsubscribe(ws.data.channel); - waitingLinkRequestConnections.delete(ws.data.channel); - } - } - }, - }, - port: 3001, -}); - -console.log(`Listening on ${server.hostname}:${server.port}`); diff --git a/src/app/dashboard/reseller-office-365/list/page.tsx b/src/app/dashboard/reseller-office-365/list/page.tsx deleted file mode 100644 index 9420636..0000000 --- a/src/app/dashboard/reseller-office-365/list/page.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import getUserRoles from "@/modules/auth/utils/getUserRoles"; -import checkMultiplePermissions from "@/modules/dashboard/services/checkMultiplePermissions"; -import checkPermission from "@/modules/dashboard/services/checkPermission"; -import getAllLinkRequests from "@/modules/resellerOffice365/actions/getAllLinkRequests"; -import getLinkRequests from "@/modules/resellerOffice365/actions/getLinkRequests"; -import ListOfRequestTable from "@/modules/resellerOffice365/tables/ListOfRequestTable/ListOfRequestTable"; -import RequestTable from "@/modules/resellerOffice365/tables/RequestTable/RequestTable"; -import { Card, Stack, Title } from "@mantine/core"; -import { notFound } from "next/navigation"; -import React from "react"; - -export default async function RequestLinkPage() { - const permissions = await checkMultiplePermissions({ - create: "office-365-link.create", - readAll: "office-365-link.readAll", - read: "office-365-link.read", - update: "office-365-link.update", - delete: "office-365-link.delete", - }); - - if (!permissions.readAll) notFound(); - - const data = await getAllLinkRequests(); - if (!data.success) { - //todo: handle error - console.error(data.error); - throw new Error("Error while fetch data"); - } - const tableData = data.data; - - return ( - - List Link Office 365 - - - - - ); -} diff --git a/src/app/dashboard/reseller-office-365/request/page.tsx b/src/app/dashboard/reseller-office-365/request/page.tsx deleted file mode 100644 index 3c81347..0000000 --- a/src/app/dashboard/reseller-office-365/request/page.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import getUserRoles from "@/modules/auth/utils/getUserRoles"; -import checkMultiplePermissions from "@/modules/dashboard/services/checkMultiplePermissions"; -import checkPermission from "@/modules/dashboard/services/checkPermission"; -import getLinkRequests from "@/modules/resellerOffice365/actions/getLinkRequests"; -import RequestTable from "@/modules/resellerOffice365/tables/RequestTable/RequestTable"; -import { Card, Stack, Title } from "@mantine/core"; -import { notFound } from "next/navigation"; -import React from "react"; - -export default async function RequestLinkPage() { - const permissions = await checkMultiplePermissions({ - create: "office-365-link.create", - readAll: "office-365-link.readAll", - read: "office-365-link.read", - update: "office-365-link.update", - delete: "office-365-link.delete", - }); - - if (!permissions.readAll) notFound(); - - const data = await getLinkRequests() - if (!data.success){ - //todo: handle error - console.error(data.error) - throw new Error("Error while fetch data") - } - const tableData = data.data - - return ( - - Permohonan Link Office 365 - - - - - ); -} diff --git a/src/modules/resellerOffice365/actions/cancelRequest.ts b/src/modules/resellerOffice365/actions/cancelRequest.ts deleted file mode 100644 index fd75589..0000000 --- a/src/modules/resellerOffice365/actions/cancelRequest.ts +++ /dev/null @@ -1,48 +0,0 @@ -"use server"; - -import db from "@/core/db"; -import checkPermission from "@/modules/dashboard/services/checkPermission"; -import handleCatch from "@/modules/dashboard/utils/handleCatch"; -import notFound from "@/modules/dashboard/utils/notFound"; -import unauthorized from "@/modules/dashboard/utils/unauthorized"; -import ResellerOffice365Error from "../errors/ResellerOffice365Error"; -import getCurrentUser from "@/modules/auth/utils/getCurrentUser"; -import ServerResponseAction from "@/modules/dashboard/types/ServerResponseAction"; -import { revalidatePath } from "next/cache"; -import "server-only" - -export default async function cancelRequest(id: string): Promise { - try { - //TODO: Fix permission - if (!(await checkPermission("authenticated-only"))) return unauthorized(); - - const data = await db.office365LinkRequest.findFirst({ - where: { id }, - }); - - if (!data) return notFound({message: "The Provided ID does not match any"}) - - if (data.status !== "WAITING") throw new ResellerOffice365Error({ - errorCode: "REQUEST_IS_NOT_IN_WAITING_STATE", - message: "This item is not in \"waiting\" state to perform cancellation. This might be due to the request has been accepted" - }); - - if (data.createdBy !== (await getCurrentUser())?.id) return unauthorized(); - - await db.office365LinkRequest.update({ - where: {id}, - data: { - status: "CANCELLED", - cancelledAt: new Date() - } - }) - - revalidatePath(".") - - return { - success: true - } - } catch (e) { - return handleCatch(e); - } -} diff --git a/src/modules/resellerOffice365/actions/createLinkRequest.ts b/src/modules/resellerOffice365/actions/createLinkRequest.ts deleted file mode 100644 index 16fdd6b..0000000 --- a/src/modules/resellerOffice365/actions/createLinkRequest.ts +++ /dev/null @@ -1,65 +0,0 @@ -"use server"; -import checkPermission from "@/modules/dashboard/services/checkPermission"; -import ServerResponseAction from "@/modules/dashboard/types/ServerResponseAction"; -import handleCatch from "@/modules/dashboard/utils/handleCatch"; -import unauthorized from "@/modules/dashboard/utils/unauthorized"; -import "server-only"; -import requestLinkFormSchema from "../formSchemas/requestLinkFormSchema"; -import DashboardError from "@/modules/dashboard/errors/DashboardError"; -import mapObjectToFirstValue from "@/utils/mapObjectToFirstValue"; -import db from "@/core/db"; -import getCurrentUser from "@/modules/auth/utils/getCurrentUser"; -import { revalidatePath } from "next/cache"; - -export default async function createLinkRequest( - formData: RequestLinkForm -): Promise { - try { - if (!(await checkPermission("office-365-request.create"))) - unauthorized(); - - const currentUser = await getCurrentUser(); - if (!currentUser) return unauthorized(); - - const validatedFields = requestLinkFormSchema.safeParse(formData); - if (!validatedFields.success) { - throw new DashboardError({ - errorCode: "INVALID_FORM_DATA", - formErrors: mapObjectToFirstValue( - validatedFields.error.flatten().fieldErrors - ), - }); - } - - //database operations - await db.office365LinkRequest.create({ - data: { - creator: { - connect: { - id: currentUser.id, - }, - }, - status: "WAITING", - links: { - createMany: { - data: validatedFields.data.details.map((detail) => ({ - numberOfUsers: detail.endUserQty, - activePeriod: detail.activePeriod, - email: detail.email, - })), - }, - }, - }, - }); - - revalidatePath(".") - - return { - success: true, - message: - "Your request has been made. Please wait while our admin processing your request", - }; - } catch (e) { - return handleCatch(e); - } -} diff --git a/src/modules/resellerOffice365/actions/getAllLinkRequests.ts b/src/modules/resellerOffice365/actions/getAllLinkRequests.ts deleted file mode 100644 index 5baadca..0000000 --- a/src/modules/resellerOffice365/actions/getAllLinkRequests.ts +++ /dev/null @@ -1,55 +0,0 @@ -import checkPermission from "@/modules/dashboard/services/checkPermission"; -import ServerResponseAction from "@/modules/dashboard/types/ServerResponseAction"; -import handleCatch from "@/modules/dashboard/utils/handleCatch"; -import unauthorized from "@/modules/dashboard/utils/unauthorized"; -import db from "@/core/db"; -import RequestLinkWithIssuerData from "../types/RequestLinkWithIssuerData"; - -export default async function getAllLinkRequests(): Promise< - ServerResponseAction -> { - try { - //TODO: Fix permission check - if (!(await checkPermission("authenticated-only"))) - return unauthorized(); - - const requestLinks = await db.office365LinkRequest.findMany({ - orderBy: [ - { - status: "asc" - }, - { - requestedAt: "desc" - } - ], - select: { - id: true, - creator: { - select: { - id: true, - name: true, - photoProfile: true, - email: true, - }, - }, - status: true, - requestedAt: true, - _count: { - select: { - links: true, - }, - }, - }, - }); - - return { - success: true, - data: requestLinks.map((item) => ({ - ...item, - userCount: item._count.links, - })), - }; - } catch (e) { - return handleCatch(e); - } -} diff --git a/src/modules/resellerOffice365/actions/getLinkRequestDataById.ts b/src/modules/resellerOffice365/actions/getLinkRequestDataById.ts deleted file mode 100644 index 9e266bf..0000000 --- a/src/modules/resellerOffice365/actions/getLinkRequestDataById.ts +++ /dev/null @@ -1,70 +0,0 @@ -"use server" -import checkPermission from "@/modules/dashboard/services/checkPermission"; -import ServerResponseAction from "@/modules/dashboard/types/ServerResponseAction"; -import handleCatch from "@/modules/dashboard/utils/handleCatch"; -import unauthorized from "@/modules/dashboard/utils/unauthorized"; -import RequestLinkWithIssuerData from "../types/RequestLinkWithIssuerData"; -import db from "@/core/db"; -import { string } from "zod"; -import notFound from "@/modules/dashboard/utils/notFound"; - -async function getOffice365LinkRequestData(id: string) { - const data = await db.office365LinkRequest.findFirst({ - where: { id }, - select: { - acceptedAt: true, - cancelledAt: true, - creator: { - select: { - name: true, - id: true, - email: true, - }, - }, - id: true, - links: { - select: { - activePeriod: true, - email: true, - id: true, - link: true, - numberOfUsers: true, - }, - }, - rejectedAt: true, - requestedAt: true, - status: true, - }, - }); - - return data; -} - -export default async function getLinkRequestDataById( - id: string -): Promise< - ServerResponseAction< - NonNullable>> - > -> { - try { - //TODO: Adjust permission - if (!(await checkPermission("authenticated-only"))) - return unauthorized(); - - const data = await getOffice365LinkRequestData(id); - - if (!data) { - return notFound({ - message: "The requested link request item is not found", - }); - } - - return { - success: true, - data, - }; - } catch (e) { - return handleCatch(e); - } -} diff --git a/src/modules/resellerOffice365/actions/getLinkRequests.ts b/src/modules/resellerOffice365/actions/getLinkRequests.ts deleted file mode 100644 index 63bf5a8..0000000 --- a/src/modules/resellerOffice365/actions/getLinkRequests.ts +++ /dev/null @@ -1,57 +0,0 @@ -import ServerResponseAction from "@/modules/dashboard/types/ServerResponseAction"; -import RequestLink from "../types/RequestLink"; -import handleCatch from "@/modules/dashboard/utils/handleCatch"; -import checkPermission from "@/modules/dashboard/services/checkPermission"; -import unauthorized from "@/modules/dashboard/utils/unauthorized"; -import getCurrentUser from "@/modules/auth/utils/getCurrentUser"; -import db from "@/core/db"; - -export default async function getLinkRequests(): Promise< - ServerResponseAction -> { - try { - if (!(await checkPermission("office-365-request.getMine"))) - unauthorized(); - - const user = await getCurrentUser(); - - if (!user) return unauthorized(); - - const requests = await db.office365LinkRequest.findMany({ - orderBy: [ - { - status: "asc" - }, - { - requestedAt: "desc" - } - ], - where: { - creator: { id: user.id }, - }, - select: { - id: true, - requestedAt: true, - status: true, - links: true, - }, - }); - - const result: RequestLink[] = requests.map((request) => ({ - id: request.id, - requestDate: request.requestedAt.toISOString(), - status: request.status, - userCount: request.links.reduce( - (prev, curr) => prev + curr.numberOfUsers, - 0 - ), - })); - - return { - success: true, - data: result, - }; - } catch (e) { - return handleCatch(e); - } -} diff --git a/src/modules/resellerOffice365/actions/inputLinks.ts b/src/modules/resellerOffice365/actions/inputLinks.ts deleted file mode 100644 index d0beadf..0000000 --- a/src/modules/resellerOffice365/actions/inputLinks.ts +++ /dev/null @@ -1,81 +0,0 @@ -"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 { - 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); - } -} diff --git a/src/modules/resellerOffice365/config.ts b/src/modules/resellerOffice365/config.ts deleted file mode 100644 index a3ef800..0000000 --- a/src/modules/resellerOffice365/config.ts +++ /dev/null @@ -1,5 +0,0 @@ -const resellerOffice365Config = { - activePeriods: ["1 Month", "1 Year", "2 Years"], -} as const; - -export default resellerOffice365Config; diff --git a/src/modules/resellerOffice365/errors/ResellerOffice365Error.ts b/src/modules/resellerOffice365/errors/ResellerOffice365Error.ts deleted file mode 100644 index 409f8f8..0000000 --- a/src/modules/resellerOffice365/errors/ResellerOffice365Error.ts +++ /dev/null @@ -1,25 +0,0 @@ -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 -} - -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; - } -} diff --git a/src/modules/resellerOffice365/formSchemas/requestLinkFormSchema.ts b/src/modules/resellerOffice365/formSchemas/requestLinkFormSchema.ts deleted file mode 100644 index 2b58b5d..0000000 --- a/src/modules/resellerOffice365/formSchemas/requestLinkFormSchema.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { z } from "zod"; -import resellerOffice365Config from "../config"; - -const requestLinkFormSchema = z.object({ - numberOfLinks: z.number().min(1), // Assuming you need at least one link - details: z.array( - z.object({ - email: z.string().email(), // Validate string as an email - activePeriod: z.enum(resellerOffice365Config.activePeriods), // Validate against the specific allowed values - endUserQty: z.number().min(1), // Assuming you need at least one end user - }) - ), -}); - -export default requestLinkFormSchema; diff --git a/src/modules/resellerOffice365/modals/RequestModal.tsx b/src/modules/resellerOffice365/modals/RequestModal.tsx deleted file mode 100644 index 581c8ce..0000000 --- a/src/modules/resellerOffice365/modals/RequestModal.tsx +++ /dev/null @@ -1,449 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -import { - Alert, - Button, - Divider, - Fieldset, - Flex, - Group, - Modal, - NumberInput, - ScrollArea, - Select, - Stack, - TextInput, - Loader, - Text, - Skeleton, -} from "@mantine/core"; -import { useForm, zodResolver } from "@mantine/form"; -import React, { useEffect, useState } from "react"; -import { - TbAt, - TbCalendarTime, - TbDeviceFloppy, - TbLink, - TbUser, - TbUsers, -} from "react-icons/tb"; -import resellerOffice365Config from "../config"; -import requestLinkFormSchema from "../formSchemas/requestLinkFormSchema"; -import withServerAction from "@/modules/dashboard/utils/withServerAction"; -import createLinkRequest from "../actions/createLinkRequest"; -import { notifications } from "@mantine/notifications"; -import DashboardError from "@/modules/dashboard/errors/DashboardError"; -import getLinkRequestDataById from "../actions/getLinkRequestDataById"; -import { isPagesAPIRouteMatch } from "next/dist/server/future/route-matches/pages-api-route-match"; -import inputLink from "../actions/inputLinks"; -import { Office365LinkRequestStatus } from "@prisma/client"; -import cancelRequest from "../actions/cancelRequest"; - -export interface ModalProps { - title: string; - opened: boolean; - onClose?: () => void; - type: "create" | "detail" | "waiting" | "input link"; - detailId: string | null; -} - -export default function RequestModal(props: ModalProps) { - const [formState, setFormState] = useState< - | "idle" - | "submitting" - | "waiting" - | "fetching" - | "error" - | "confirming cancel" - | "cancelling" - >("idle"); - - const [errorMessage, setErrorMessage] = useState(""); - const [requestStatus, setRequestStatus] = useState< - Office365LinkRequestStatus | "CREATING" - >("CREATING"); - - const closeModal = (force?: boolean) => { - if (!force){ - if (["submitting, cancelling"].includes(formState)) return; //prevents closing - } - //reset state - setErrorMessage(""); - setRequestStatus("CREATING"); - setFormState("idle"); - form.reset(); - props.onClose ? props.onClose() : ""; - }; - - useEffect(() => { - const fetchDataById = async (id: string) => { - const { data } = await withServerAction(getLinkRequestDataById, id); - if (!props.opened) return; - return data; - }; - - switch (props.type) { - case "detail": - case "input link": { - if (!props.detailId || !props.opened) return; - setFormState("fetching"); - fetchDataById(props.detailId) - .then((data) => { - if (!data) { - closeModal(); - notifications.show({ - message: - "The returned data from server is empty. Please try again", - color: "red", - }); - return; - } - form.setValues({ - numberOfLinks: data.links.length, - id: data.id, - details: data.links.map((item) => ({ - activePeriod: item.activePeriod, - email: item.email, - endUserQty: item.numberOfUsers, - id: item.id, - link: item.link ?? "", - })), - }); - setRequestStatus(data.status); - if ( - data.status === "WAITING" && - props.type === "detail" - ) { - setFormState("waiting"); - } else { - setFormState("idle"); - } - }) - .catch((e) => { - if (e instanceof Error) { - setErrorMessage(e.message); - } else { - setErrorMessage("Unkown error occured"); - } - setFormState("idle"); - }); - break; - } - } - }, [props]); - - const form = useForm({ - initialValues: { - id: undefined, - numberOfLinks: 1, - details: [ - { - email: "", - activePeriod: "2 Years", - endUserQty: 1, - link: "", - }, - ], - }, - validate: zodResolver(requestLinkFormSchema), - onValuesChange: (values, prev) => { - // Check if numberOfLinks has changed - if (values.numberOfLinks !== prev.numberOfLinks) { - const currentDetails = values.details; - const targetLength = values.numberOfLinks; - - // Add new detail objects if numberOfLinks has increased - while (currentDetails.length < targetLength) { - currentDetails.push({ - email: "", - activePeriod: "2 Years", - endUserQty: 1, - link: "", - }); - } - - // Remove extra detail objects if numberOfLinks has decreased - if (currentDetails.length > targetLength) { - currentDetails.length = targetLength; // Adjusts the array length - } - - // Update the form values with the adjusted details array - form.setValues({ - ...values, - details: currentDetails, - }); - } - }, - }); - - const handleSubmit = (values: RequestLinkForm) => { - const submitableState: (typeof formState)[] = ["idle"]; - - if (!submitableState.includes(formState)) return; //prevent submit when not in subitable state - - switch (props.type) { - case "create": { - setFormState("submitting"); - withServerAction(createLinkRequest, values) - .then((response) => { - notifications.show({ - message: response.message, - color: "green", - }); - setFormState("waiting"); - }) - .catch((e) => { - if (e instanceof DashboardError) { - if (e.errorCode === "INVALID_FORM_DATA") { - if (e.formErrors) { - form.setErrors(e.formErrors); - } else { - setErrorMessage(e.message); - } - } 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` - ); - } - - setFormState("idle"); - }); - break; - } - case "input 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 handleCancel = () => { - if (!props.detailId) return setErrorMessage("Cannot request cancellation. Cause: the ID is empty. Please contact your administrator") - setFormState("cancelling") - withServerAction(cancelRequest, props.detailId) - .then(() => { - notifications.show({ - message: "The request has been cancelled", - color: "green" - }) - setFormState("idle") - closeModal(true) - }) - .catch(e => { - if (e instanceof Error){ - setErrorMessage(e.message) - } - setFormState("idle") - }) - } - - const renderActionButtons = () => ( - - - {showCancelButton && ( - - )} - {showSubmitButton && ( - - )} - - ); - - const renderCancelConfirmation = () => ( - - Are you sure to cancel this link request? - - - - - - ); - - const disableChange = formState !== "idle"; - const readonly = ["input link", "detail"].includes(props.type); - const showSkeleton = formState === "fetching"; - const showActivationLink = ["input link", "detail"].includes(props.type); - const enableInputActivationLink = props.type === "input link"; - const showSubmitButton = ["create", "input link"].includes(props.type); - const showCancelButton = - ["detail"].includes(props.type) && formState === "waiting"; - const showCancelRequestConfirmation = [ - "confirming cancel", - "cancelling", - ].includes(formState); - const showWaitingAlert = (["waiting", "confirming cancel"] as typeof formState[]).includes(formState) - - return ( - -
- - {showWaitingAlert && ( - - Your request is being processed by administrator - - )} - - {errorMessage && {errorMessage}} - - - } - disabled={disableChange} - readOnly={readonly} - {...form.getInputProps("numberOfLinks")} - /> - - - - - - {form.values.details.map((item, i) => ( -
- - - } - label="Email" - readOnly={readonly} - disabled={disableChange} - {...form.getInputProps( - `details.${i}.email` - )} - /> - - - -