From 5530b077692cc8627e877bc264ac310aecaad5b3 Mon Sep 17 00:00:00 2001 From: sianida26 Date: Fri, 16 Feb 2024 02:09:07 +0700 Subject: [PATCH] Added UI for request --- .vscode/launch.json | 15 ++ bun.lockb | Bin 201003 -> 201445 bytes prisma/seeds/roleSeed.ts | 6 + .../reseller-office-365/request/page.tsx | 28 +++ src/modules/resellerOffice365/config.ts | 5 + .../resellerOffice365/modals/RequestModal.tsx | 194 ++++++++++++++++++ .../tables/RequestTable/RequestTable.tsx | 76 +++++++ .../tables/RequestTable/columns.tsx | 86 ++++++++ .../resellerOffice365/types/RequestLink.d.ts | 6 + 9 files changed, 416 insertions(+) create mode 100644 .vscode/launch.json create mode 100644 src/app/dashboard/reseller-office-365/request/page.tsx create mode 100644 src/modules/resellerOffice365/config.ts create mode 100644 src/modules/resellerOffice365/modals/RequestModal.tsx create mode 100644 src/modules/resellerOffice365/tables/RequestTable/RequestTable.tsx create mode 100644 src/modules/resellerOffice365/tables/RequestTable/columns.tsx create mode 100644 src/modules/resellerOffice365/types/RequestLink.d.ts diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2ba986f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:8080", + "webRoot": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index 5122c5db0d8dadd45239159d7ca96727e2c9110d..6a58ffd6d340df22db524ab9817ef794069a0ac9 100755 GIT binary patch delta 1653 zcmY+E3rv$&6oBu&E%Indy^WYVB9YST!0i zYeSy&zma_;uUld*j)}L9yeY*Y{|4Ek4!svE+X%`0-J2jKOs!$-y?f3glmIi>+8U8W zR@khgXOnTRJ=)eQ_r(xB1Sch6N5EqH9@|B^?0?w)WoLIznKn!DquJ6gJU*GS*l618 zP^B#=m3>uzwB1SGG%vYS=DF>cpIoJdt?v)ko+)gn-P`Ylz4dp}O{KMJa=&SxxD+

fhsYNV37xB^NXSD|oZt`la6J>8*A7qjytWKJ9S;i~7pVoEkCYI;BW)gOoYl2X1 za>Q3LiWLEM%|-RG&cjg!rL%854BXfutPH>gg~3|wGAGRI>K1x3e$G7~{oSpC7Ikvl z<2Fm@)zRE8U0Yvyu)hVV1mBN}ut(aw<5ZHa(riB+X3${KqnQRNwMAl;p|8_sQ>LyP zix@Sj&Rj3icU>PTimH+gJ~uyhJh!L+e#1!Lg{DZ??xxER=5xbCJ_y!-U)Xph%eB{- zI%^uZ6Cg}RV&jVjpag z^Q7{wpSPwr@#_sy=)<*|_Qv#IXF?z4$tkrNv5M|7;vIOBUNYirJSAWg7S>qD)c(TN zYCN=$))!-)k7L|j%a#e+ForkN{xQ4-2h&yK*sm;vm)HRzEXo5koU?w;mcclhvqzkH z!g$c#z36w&ynsF7aRZz|>!NAS204SaMg^>y5Gq4M974|{qZ^`OU@W&3)Xdo^XEI=7 z&i>?Umjm?vn*V1Ata#hC(FAZKGstPCMvfW!PvSfSuS?Bh#k4#+dk{J_7*LE_(;TY6kK!ks;VcN49hAu|XTjjt zEfIuVoUyBfpT&~QamM~8F+ATqFm}BwL9Z=ELH#jI0!Lw>TJYHd0+y{&gT`{kO3vam zpgJ}Q;sKTwWEH5M$9aKe)8U}&!O?*A0n65|28{=w#Y@~wf*h=FAc_TQcH#%iSW^v% zgsl^JEy2UWp(%V$tb7Mz-UiKwKt1S?h$`oBA{i0UZFATxF)X-~3`hw*=)@7rSW+hz zhURdEJdC|Gy9qH^R()nwGB^Op&7-tJLL%8~2+b1mMU+^tjYG6qPXdMVcp~!=C28Y? z>SQ9qSTCI3LQ-_0nUDZlv)sFA^X<{BPp%PsEJ3SJ)W##JjXpd~^mr$g9U<#{6c+a; z)x|XJ2uTsDkC1Zg(^c%I=}IBkLORk#up{m1B02QaW)e=XbP)y3EG8cG-5bPPD7ryT i%0=-I;<`^>TRKh759DGpEh!;>RCj}f3of}xhyMW$1(aR@ delta 1869 zcmeH{{ZCU@7{|{!7Yeq;mLY|9ATJwlB4sU<5oPQ;-5gWQGG-vdWk5DooP`MJmpZh$| zZO^&)d2mtPc0pZdjF}v>G;TJ$CJGrf)zXxw>2&?bse8xYQx$BSaT;B{l?_?}F?)I< zGlZO-`?2i2#`gt?l?YWj8xdLqtIlrHp3~SzLN1Hak=#V7D@V;%`(n<3O1cr6C@t<& zV}sOZiIrXn^|mM5j>LOfpbkrY5wDWbMrl)1Dh{!K(KM>@B+&bzJ@-o6bE)qc$f`)( z86Vyr{!Zx7_a<|XoR>EA?a`mEf7Q6X{ZMSMYDnt62PCEhgz(;ezz;PaNUaX{GU^Wt=F1l*OuYH&X(_L zTMh)!c5Ack!`X}?{dCaJQ^~$k1_v@eYgkF4vQ|JU-a5xQnjQuKN_-8Q&DJ;tqe2TMi&J++Y zaCVO~FNpKmcMEo(GjGsV&L)7dAp)ZU?d9wtXD~*PhnrQPzj(0=4($GV@MI9IKmjW& z4gpUD%?jAjFjmL@I#|au>TqGFVgfp*Ao=7x-azoA+_Qksc_{KA!Hj6(5>BE&EMco^ z?3uf&Qbp)h7miS{E*?mJYZ)KY7}(BvKndF|wsxrCVPN8ZI-@3$a-a|Cj22ABWO>L! zB9uasF+pB@od_74slw5H14 IzQRWQFUmz{2><{9 diff --git a/prisma/seeds/roleSeed.ts b/prisma/seeds/roleSeed.ts index 878523a..54638d0 100644 --- a/prisma/seeds/roleSeed.ts +++ b/prisma/seeds/roleSeed.ts @@ -11,6 +11,12 @@ export default async function roleSeed(prisma: PrismaClient) { description: "Has full access to the system and can manage all features and settings", isActive: true, name: "Super Admin" + }, + { + code: "reseller-office-365", + description: "Has ability to make request Office 365 links", + isActive: true, + name: "Reseller Office 365" } ]; diff --git a/src/app/dashboard/reseller-office-365/request/page.tsx b/src/app/dashboard/reseller-office-365/request/page.tsx new file mode 100644 index 0000000..2db2afb --- /dev/null +++ b/src/app/dashboard/reseller-office-365/request/page.tsx @@ -0,0 +1,28 @@ +import getUserRoles from "@/modules/auth/utils/getUserRoles"; +import checkMultiplePermissions from "@/modules/dashboard/services/checkMultiplePermissions"; +import checkPermission from "@/modules/dashboard/services/checkPermission"; +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(); + + return ( + + Permohonan Link Office 365 + + + + + ); +} diff --git a/src/modules/resellerOffice365/config.ts b/src/modules/resellerOffice365/config.ts new file mode 100644 index 0000000..a3ef800 --- /dev/null +++ b/src/modules/resellerOffice365/config.ts @@ -0,0 +1,5 @@ +const resellerOffice365Config = { + activePeriods: ["1 Month", "1 Year", "2 Years"], +} as const; + +export default resellerOffice365Config; diff --git a/src/modules/resellerOffice365/modals/RequestModal.tsx b/src/modules/resellerOffice365/modals/RequestModal.tsx new file mode 100644 index 0000000..6f83dce --- /dev/null +++ b/src/modules/resellerOffice365/modals/RequestModal.tsx @@ -0,0 +1,194 @@ +import { + Button, + Divider, + Fieldset, + Flex, + Group, + Modal, + NumberInput, + ScrollArea, + Select, + Stack, + TextInput, +} from "@mantine/core"; +import { useForm } from "@mantine/form"; +import React, { useState } from "react"; +import { + TbAt, + TbCalendarTime, + TbDeviceFloppy, + TbLink, + TbUser, + TbUsers, +} from "react-icons/tb"; +import resellerOffice365Config from "../config"; + +export interface ModalProps { + title: string; + opened: boolean; + readonly: boolean; + onClose?: () => void; +} + +interface FormType { + numberOfLinks: number; + details: { + email: string; + activePeriod: (typeof resellerOffice365Config.activePeriods)[number]; + endUserQty: number; + }[]; +} + +export default function RequestModal(props: ModalProps) { + const [isSubmitting, setSubmitting] = useState(false); + const [formState, setFormState] = useState< + "idle" | "submitting" | "waiting" + >("idle"); + + const closeModal = () => { + props.onClose ? props.onClose() : ""; + }; + + const form = useForm({ + initialValues: { + numberOfLinks: 1, + details: [ + { + email: "", + activePeriod: "2 Years", + endUserQty: 1, + }, + ], + }, + 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, + }); + } + + // 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 disableChange = formState !== "idle"; + + const handleSubmit = (values: FormType) => { + const submitableState = ["idle"]; + + if (!submitableState.includes(formState)) return; //prevent submit + + setFormState("submitting"); + }; + + return ( + +

+ + } + disabled={disableChange} + {...form.getInputProps("numberOfLinks")} + /> + + + + + {form.values.details.map((item, i) => ( +
+ } + label="Email" + disabled={disableChange} + {...form.getInputProps( + `details.${i}.email` + )} + /> + +