From 3d7293100744302825061c30b19622fdac5a1f06 Mon Sep 17 00:00:00 2001 From: =bhagwanSingh <=bhagwan.r@hicglobalsolutions.com> Date: Tue, 8 Jul 2025 12:14:52 +0530 Subject: [PATCH] Attributes Update --- .../process/processStepOne/ProcessStepOne.tsx | 14 +- .../processStepTwo/DocumentContainer.tsx | 20 +- .../process/processStepTwo/FieldList.tsx | 11 +- .../process/processStepTwo/ProcessStepTwo.tsx | 25 +- .../process/processStepTwo/RightSideBar.tsx | 653 ------------------ .../rightSideBar/CommonAttrDropDown.tsx | 42 ++ .../rightSideBar/CurrTimeStampAttr.tsx | 37 + .../processStepTwo/rightSideBar/LabelAttr.tsx | 21 + .../rightSideBar/MaskTypePassAttr.tsx | 100 +++ .../rightSideBar/MaxMinLenAttr.tsx | 29 + .../rightSideBar/RecipientsAttrCon.tsx | 88 +++ .../rightSideBar/RequiredAttr.tsx | 23 + .../rightSideBar/RightSideBar.tsx | 367 ++++++++++ .../rightSideBar/SelectTagAttr.tsx | 95 +++ .../rightSideBar/TemporalDateAttr.tsx | 108 +++ src/config/api.tsx | 3 +- src/store/slices/documentSlice.ts | 1 - src/store/slices/selectedRecipientsSlice.tsx | 5 +- .../{dateTimeUtils.ts => dateTimeFormats.ts} | 0 src/utlity/types.tsx | 38 + 20 files changed, 982 insertions(+), 698 deletions(-) delete mode 100644 src/components/process/processStepTwo/RightSideBar.tsx create mode 100644 src/components/process/processStepTwo/rightSideBar/CommonAttrDropDown.tsx create mode 100644 src/components/process/processStepTwo/rightSideBar/CurrTimeStampAttr.tsx create mode 100644 src/components/process/processStepTwo/rightSideBar/LabelAttr.tsx create mode 100644 src/components/process/processStepTwo/rightSideBar/MaskTypePassAttr.tsx create mode 100644 src/components/process/processStepTwo/rightSideBar/MaxMinLenAttr.tsx create mode 100644 src/components/process/processStepTwo/rightSideBar/RecipientsAttrCon.tsx create mode 100644 src/components/process/processStepTwo/rightSideBar/RequiredAttr.tsx create mode 100644 src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx create mode 100644 src/components/process/processStepTwo/rightSideBar/SelectTagAttr.tsx create mode 100644 src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx rename src/utlity/{dateTimeUtils.ts => dateTimeFormats.ts} (100%) diff --git a/src/components/process/processStepOne/ProcessStepOne.tsx b/src/components/process/processStepOne/ProcessStepOne.tsx index a3f82e3..aa15ed3 100644 --- a/src/components/process/processStepOne/ProcessStepOne.tsx +++ b/src/components/process/processStepOne/ProcessStepOne.tsx @@ -45,7 +45,7 @@ const ProcessStepOne = () => { // const signingOrder = useSelector((state: RootState) => state.selectedRecipients.signingOrder) // const user = useSelector((state: RootState) => state.user) - + const [emailDtls, setEmailDtls] = useState({ subject: "Documents for Signature", message: "" }); useEffect(() => { @@ -112,12 +112,20 @@ const ProcessStepOne = () => { name: `${recipient.firstName} ${recipient.lastName}` })); - dispatch(addRecipientAsync({recipientsData, accountId, transactionId})); + dispatch(addRecipientAsync({ recipientsData, accountId, transactionId })); + + dispatch(showLoader("Processing Message...")); + + await api.put(`/api/accounts/${accountId}/transactions/${transactionId}`, { subject: emailDtls.subject, message: emailDtls.message, status: "CREATED" }).then((res) => { + console.log(res); + }) + + dispatch(hideLoader()); if (isSendNow) { dispatch(updateTransactionStatus(TRANSACTION_STATUS_ENUMS.TRANSACTION_SEND_SUCCESS)); setTimeout(() => { - navigate("/"); + // navigate("/"); }, 1000); } else { setTimeout(() => { diff --git a/src/components/process/processStepTwo/DocumentContainer.tsx b/src/components/process/processStepTwo/DocumentContainer.tsx index 0e27e12..03db2a8 100644 --- a/src/components/process/processStepTwo/DocumentContainer.tsx +++ b/src/components/process/processStepTwo/DocumentContainer.tsx @@ -4,13 +4,12 @@ import { RootState } from '../../../store/store' import api from '../../../config/api'; -import RightSideBar from './RightSideBar'; +import RightSideBar from './rightSideBar/RightSideBar'; import { DroppedItem } from '../../../utlity/types'; import { useNavigate, useParams } from 'react-router-dom'; -import { TRANSACTION_STATUS_ENUMS, updateTransactionStatus } from '../../../store/slices/transactionSlice'; -import { hideLoader, showLoader } from '../../../store/slices/loaderSlice'; + import { IoMdClose } from 'react-icons/io'; -import fields from '../../../helper/fieldsListData'; + import { fetchRecipients } from '../../../store/slices/selectedRecipientsSlice'; import { fetchDocuments } from '../../../store/slices/documentSlice'; import { FaQuestionCircle } from 'react-icons/fa'; @@ -186,7 +185,6 @@ const DocumentContainer: React.FC = ({ isSend }) => { // const remove = [] // console.log(updatedTags, "updatedTags"); - for (const dropPageIds of Object.keys(updatedTags)) { for (const dropTag of updatedTags[dropPageIds]) { let mask = null @@ -202,6 +200,8 @@ const DocumentContainer: React.FC = ({ isSend }) => { } // } + console.log(dropTag, "line 204") + const isDeleted = "isDeleted" in dropTag ? dropTag.isDeleted : false const updatedTagData = { @@ -229,7 +229,7 @@ const DocumentContainer: React.FC = ({ isSend }) => { "textSize": 14.0 }, // "required": (dropTag.type.toUpperCase() !== "SIGNATURE" && dropTag.type.toUpperCase() !== "INITIALS") ? dropTag.required : true, - "required": false, + "required": "required" in dropTag ? dropTag.required : true, "update": "update" in dropTag ? dropTag.update : false, "readOnly": false, } @@ -272,9 +272,13 @@ const DocumentContainer: React.FC = ({ isSend }) => { // for(const recipient of selectedRecipients) { // const recrecipient // } - tagsData = groupByRecipientId(tagsData); sendTagsToRecipients(tagsData, accountId, transactionId); + + // (async () => { + // const res = await api.put(`/api/accounts/${accountId}/transactions/${transactionId}`, {status: "SENT"}) + // console.log(res, "Check123") + // })() }, [isSend]) // Save Tags - END @@ -305,6 +309,7 @@ const DocumentContainer: React.FC = ({ isSend }) => { // const IconComponent = typeToIconMap[field.type] || ; let prepData = { + properties: data.properties, icon: typeToIconMap[field.label.toUpperCase()] || , type: dragElemData.label, subType: (dragElemData.label in droppedTagsDefaultField) ? droppedTagsDefaultField[dragElemData.label] : '', @@ -514,7 +519,6 @@ const DocumentContainer: React.FC = ({ isSend }) => { })() } - // const handleAddRadio = (e: React.MouseEvent, key: string, index: number) => { // // const dataToSet: DroppedItemsObj = { // // ...droppedItems, diff --git a/src/components/process/processStepTwo/FieldList.tsx b/src/components/process/processStepTwo/FieldList.tsx index a7bedd7..35862cd 100644 --- a/src/components/process/processStepTwo/FieldList.tsx +++ b/src/components/process/processStepTwo/FieldList.tsx @@ -4,9 +4,9 @@ import api from '../../../config/api'; import { useParams } from 'react-router-dom'; import typeToIconMap from '../../../helper/iconMap'; import { FaQuestionCircle } from 'react-icons/fa'; +import { TagsProperties } from '../../../utlity/types'; -const handlePointerDown = (event: React.DragEvent, label: string, recipientId: number, recipientIndx: number) => { - +const handlePointerDown = (event: React.DragEvent, label: string, recipientId: number, recipientIndx: number, tagsProperties: TagsProperties) => { const dragElemRect = event.currentTarget.getBoundingClientRect(); let width = dragElemRect.width let height = dragElemRect.height @@ -27,7 +27,8 @@ const handlePointerDown = (event: React.DragEvent, label: string recipientId: recipientId, recipientIndx: recipientIndx, width, - height + height, + properties: tagsProperties } window.dragElemData = JSON.stringify(obj); @@ -41,7 +42,7 @@ interface FieldListProps { const FieldList: React.FC = ({ color, recipientId, recipientIndx }) => { - const [tagsData, setTagsData] = useState([]); + const [tagsData, setTagsData] = useState([]); const { accountId } = useParams<{ accountId: string }>(); if (!accountId) { @@ -91,7 +92,7 @@ const FieldList: React.FC = ({ color, recipientId, recipientIndx
handlePointerDown(e, field.type.toLowerCase(), recipientId, recipientIndx)} + onPointerDown={(e) => handlePointerDown(e, field.type.toLowerCase(), recipientId, recipientIndx, field)} className="p-1 flex justify-start items-center gap-2 rounded-sm cursor-grab hover:bg-slate-200 transition-all duration-300">
{ return (
- - {/* Top Header One */} - - {/*
- -
-
-

Setup your Document

-
-
-
-

Prepare

-
-
-
-

Hooray !

-
-
-
-
*/} - {/* Top Header One */} -
diff --git a/src/components/process/processStepTwo/RightSideBar.tsx b/src/components/process/processStepTwo/RightSideBar.tsx deleted file mode 100644 index 5e2ce22..0000000 --- a/src/components/process/processStepTwo/RightSideBar.tsx +++ /dev/null @@ -1,653 +0,0 @@ -import { MdKeyboardArrowDown } from "react-icons/md"; -import { DroppedItemsObj } from "./DocumentContainer"; -import React, { ReactHTMLElement, useEffect, useState } from "react"; - - -import { RiAsterisk } from "react-icons/ri"; -import { GoDotFill } from "react-icons/go"; -import { IoClose } from "react-icons/io5"; -import { LuAsterisk } from "react-icons/lu"; -import { dateFormats, dateTimeFormats, monthFormats, timeFormats, weekFormats, yearFormats } from "../../../utlity/dateTimeUtils"; -import { DroppedItem } from "../../../utlity/types"; -import { IoMdClose } from "react-icons/io"; -import dayjs from "dayjs"; - -interface DroppedItemProps { - selectedTag: DroppedItem - setDroppedItems: React.Dispatch> - selTagKey: string, - selTagIndx: number -} - -enum TEXT { - PARAGRAPH = "paragraph", - SINGLE_LINE = "single_line", - PASSWORD = "password", -} -// enum SIGNATURE { -// TYPED = "typed", -// DRAW = "draw", -// UPLOAD = "upload", -// } -// enum INITIALS { -// TYPED = "typed", -// DRAW = "draw", -// UPLOAD = "upload", -// } -export enum TEMPORAL { - DATE = "date", - TIME = "time", - DATE_TIME = "date_time", - // YEAR = "year", - // MONTH = "month", - // WEEK = "week", -} - -enum NUMBER { - INTEGER = "integer", - DECIMAL = "decimal", - CURRENCY = "currency" -} -// enum IMAGE { -// STAMP = "stamp", -// LOGO = "logo" -// } - -enum SELECT { - SINGLE_SELECT = "single select", - MULTI_SELECT = "multi select" -} - - -enum MASKTYPE { - ALL = "all", - LAST_FOUR = "last_four", - CREDIT_CARD = "credit_Card", - NATIONAL_INSURANCE = "national_insurance", - SOCIAL_SECURITY = "social_security", - SOCIAL_INSURANCE = "social_insurance" -} - -enum MASKCHARACTER { - ASTERISK = "ASTERISK", - DOT = "DOT", - X = "CROSS", -} - -const enumMap = { - text: TEXT, - temporal: TEMPORAL, - number: NUMBER, - image: String, - select: SELECT -} - -enum DROPDOWNTOGGLE { - TYPE, - MASK_TYPE, - MASK_CHARACTER, - DDMMYY_FORMAT -} - -const dateTimeFormatMap = { - "date": dateFormats, - "time": timeFormats, - "date_time": dateTimeFormats, - "year": yearFormats, - "month": monthFormats, - "week": weekFormats -} - -const RightSideBar: React.FC = ({ selectedTag, setDroppedItems, selTagKey, selTagIndx }) => { - console.log(selectedTag, "selectedTag Line 102") - const selectedType = selectedTag.type in enumMap && enumMap[selectedTag.type as keyof typeof enumMap]; - const [dropDownToggle, setDropDownToggle] = useState(null); - - // const [showFormatEg, setShowFormatEg] = useState(false); - const [is24Hrs, setIs24Hrs] = useState(true); - const [isCurrentTimeStamp, setIsCurrentTimeStamp] = useState(true); - - // const [selectedOptions, setSelectedOptions] = useState([]) - - const [decimalPlace, setDecimalPlace] = useState(2) - const [selectedOption, setSelectedOption] = useState() - - const handlePropertyChange = (changeTo: string, changeWith: string | boolean | number) => { - console.log("Handle Property Change Called", "changeTo", changeTo, "changeWith", changeWith) - if (changeTo === '' || changeWith === '') return - - if (changeTo === "subType" && (changeWith === TEMPORAL.DATE || changeWith === TEMPORAL.DATE_TIME || changeWith === TEMPORAL.TIME)) { - // let change: string = changeWith; - // if (change === "DATE TIME") { - // change = "DATE_TIME" - // } - setDroppedItems((prev) => ( - { - ...prev, - [selTagKey]: Array.isArray(prev[selTagKey]) // Ensure it's an array - ? prev[selTagKey].map((item, i) => - i === selTagIndx ? { ...item, [changeTo]: changeWith || "", format: "", update: "id" in item ? true : false } : item - ) - : [], - }// Provide a fallback in case it's undefined or not an array - )); - } else if (changeTo === "subType" && typeof changeWith === "string" && changeWith.toLowerCase() === "password") { - console.log("Line 161") - setDroppedItems((prev) => ( - { - ...prev, - [selTagKey]: Array.isArray(prev[selTagKey]) - ? prev[selTagKey].map((item, i) => - i === selTagIndx ? { ...item, [changeTo]: changeWith, maskType: "All", maskCharacter: "ASTERISK", update: "id" in item ? true : false } : item - ) - : [], - } - )); - } - else if (changeTo === "subType" && (changeWith === NUMBER.CURRENCY || changeWith === NUMBER.INTEGER || changeWith === NUMBER.DECIMAL)) { - let decPlace = changeWith !== NUMBER.DECIMAL ? 0 : decimalPlace; - const isCurrency = changeWith === NUMBER.CURRENCY; - // const currencyType = null - - setDroppedItems((prev) => ( - { - ...prev, - [selTagKey]: Array.isArray(prev[selTagKey]) // Ensure it's an array - ? prev[selTagKey].map((item, i) => - i === selTagIndx ? { ...item, [changeTo]: changeWith, decimalPlace: decPlace, isCurrency, update: "id" in item ? true : false } : item - ) - : [], - }// Provide a fallback in case it's undefined or not an array - )); - - } else if (changeTo === "format" && selectedTag.subType === TEMPORAL.DATE_TIME) { - let val = timeFormats[0].format; - if (!is24Hrs) { - val = timeFormats[1].format - } - setDroppedItems((prev) => ( - { - ...prev, - [selTagKey]: Array.isArray(prev[selTagKey]) // Ensure it's an array - ? prev[selTagKey].map((item, i) => - i === selTagIndx ? { ...item, [changeTo]: changeWith + " " + val, update: "id" in item ? true : false } : item - ) - : [], - }// Provide a fallback in case it's undefined or not an array - )); - - } else { - setDroppedItems((prev) => ( - { - ...prev, - [selTagKey]: Array.isArray(prev[selTagKey]) // Ensure it's an array - ? prev[selTagKey].map((item, i) => - i === selTagIndx ? { ...item, [changeTo]: changeWith, update: "id" in item ? true : false } : item - ) - : [], - }// Provide a fallback in case it's undefined or not an array - )); - } - setDropDownToggle(null) - } - - // const handleSelectTagOptions = () => { - // if (!selectedOptions.length) return - // setDroppedItems((prev) => ( - // { - // ...prev, - // [selTagKey]: Array.isArray(prev[selTagKey]) - // ? prev[selTagKey].map((item, i) => { - // if (i === selTagIndx) { - // return { ...item, options: [...selectedOptions] }; - // } - // return item; - // }) - // : [], - // } - // )); - // } - - // useEffect(() => { - // handleSelectTagOptions(); - // }, [selectedOptions]) - - - useEffect(() => { - if (selectedTag.subType === TEMPORAL.DATE || selectedTag.subType === TEMPORAL.DATE_TIME || selectedTag.subType === TEMPORAL.TIME) { - - if (selectedTag.subType === TEMPORAL.DATE) { - handlePropertyChange("format", dateFormats[0].format) - } - else if (selectedTag.subType === TEMPORAL.DATE_TIME) { - handlePropertyChange("format", dateTimeFormats[0].format) - } - else if (selectedTag.subType === TEMPORAL.TIME) { - handlePropertyChange("format", timeFormats[0].format) - } - } - // else if(selectedTag.subType === TEXT.PASSWORD) { - // handlePropertyChange("format", timeFormats[0].format) - // } - }, [selectedTag.subType]) - - useEffect(() => { - if (selectedTag.format === timeFormats[1].format && is24Hrs) { - setIs24Hrs(false); - } else if (selectedTag.format === timeFormats[0].format && !is24Hrs) { - setIs24Hrs(true); - } - }, [selectedTag.format]) - - useEffect(() => { - if (selectedTag.label === "temporal") { - handlePropertyChange("subType", TEMPORAL.DATE); - handlePropertyChange("format", "DD/MM/YY"); - } - }, []) - - - const handleIs24HrsClick = (checked: boolean) => { - if (selectedTag.subType === TEMPORAL.TIME) { - if (!checked) { - handlePropertyChange("format", timeFormats[1].format) - } else { - handlePropertyChange("format", timeFormats[0].format) - } - } - setIs24Hrs(checked) - } - - - const handleIsCurrentTimeStamp = (checked: boolean) => { - if (selectedTag.type.toLowerCase() === "temporal") { - setIsCurrentTimeStamp(checked) - handlePropertyChange("currentTimeStamp", checked); - } - } - - const handleAddSelectOption = () => { - if (selectedOption && selectedOption.length) { - setDroppedItems((prev) => ( - { - ...prev, - [selTagKey]: Array.isArray(prev[selTagKey]) - ? prev[selTagKey].map((item, i) => { - if (i === selTagIndx) { - return { ...item, options: item.options ? [...item.options, selectedOption] : [selectedOption], update: "id" in item ? true : false }; - } - return item; - }) - : [], - } - )); - } - } - - - const handleSelectOptionDel = (indx: number) => { - // setSelectedOptions(prev => - // prev.filter((_, i) => i !== indx) - // ) - - setDroppedItems((prev) => ( - { - ...prev, - [selTagKey]: Array.isArray(prev[selTagKey]) - ? prev[selTagKey].map((item, i) => { - if (i === selTagIndx) { - return { ...item, options: item.options ? item.options.filter((_, i) => i !== indx) : [] }; - } - return item; - }) - : [], - } - )); - } - - - const handleDecimalPlace = (e: React.ChangeEvent) => { - const val = Number(e.target.value) - setDecimalPlace(val) - handlePropertyChange("decimalPlace", val) - } - - useEffect(() => { - if ("styles" in selectedTag) { - const fontSize = selectedTag?.styles?.textSize; - const tagHeight = selectedTag?.dimensions?.height - 18; - - - console.log(fontSize, tagHeight, "Line 323", selectedTag?.styles) - - if (selectedTag.subType !== "password" && selectedTag.subType !== "paragraph" && tagHeight > (fontSize + fontSize)) { - console.log("Change subType Called from if") - handlePropertyChange("subType", "paragraph") - } else if (selectedTag.subType !== "password" && selectedTag.subType !== "single_line" && tagHeight <= (fontSize + fontSize)) { - console.log("Change subType Called from elseif") - handlePropertyChange("subType", "single_line") - } - } - }, [selectedTag]) - - console.log("RightSideBar - selectedTag", selectedTag) - - return ( - <> - {/* Right Side Bar Start */} -
-

Properties

-
- -
- - {/* label */} -
- - handlePropertyChange('label', e.target.value)} - type="text" - className="outline-none border-1 rounded px-2 py-1 border-slate-200" /> -
- - {/* Required */} - {(selectedTag.type !== "signature" && selectedTag.type !== "initials") &&
- - handlePropertyChange('required', e.target.checked)} - type="checkbox" - className="outline-none border-1 rounded px-2 py-1 border-slate-200" - /> -
} - - {/* Use Current TimeStamp */} - {selectedTag.type.toLowerCase() === "temporal" &&
- - handleIsCurrentTimeStamp(e.target.checked)} - id="use_current_timestamp" - type="checkbox" - /> -
} - - {/* Type | SubType */} - {selectedType && Object.keys(selectedType).length > 0 && -
- -
setDropDownToggle(dropDownToggle === DROPDOWNTOGGLE.TYPE ? null : DROPDOWNTOGGLE.TYPE)} - className="flex justify-between items-center border-1 rounded px-2 py-1 border-slate-200"> -

{selectedTag?.subType ? (selectedTag.subType === "date_time" ? "Date Time" : selectedTag.subType) : selectedType[Object.keys(selectedType)[0] as keyof typeof selectedType]}

- -
- - {dropDownToggle === DROPDOWNTOGGLE.TYPE && -
- {Object.keys(selectedType).map((val, indx) => ( -
handlePropertyChange("subType", selectedType[val as keyof typeof selectedType])} - className={`capitalize px-2 py-1 hover:bg-slate-200 cursor-pointer`} - > - {selectedType[val as keyof typeof selectedType] === "date_time" ? "Date Time" : selectedType[val as keyof typeof selectedType]} -
- ))} -
- } -
- } - - - {/* Mask Type */} - { - selectedTag?.subType === TEXT.PASSWORD && -
- -
setDropDownToggle(dropDownToggle === DROPDOWNTOGGLE.MASK_TYPE ? null : DROPDOWNTOGGLE.MASK_TYPE)} - className="flex justify-between items-center border-1 rounded px-2 py-1 border-slate-200"> -

{(selectedTag.maskType && selectedTag.maskType.replace("_", " ")) ? selectedTag.maskType : MASKTYPE.ALL}

- -
- - { - dropDownToggle === DROPDOWNTOGGLE.MASK_TYPE && -
- {(Object.keys(MASKTYPE) as (keyof typeof MASKTYPE)[]).map((val, indx) => - ( -
handlePropertyChange("maskType", MASKTYPE[val])} - className="capitalize px-2 py-1 hover:bg-slate-200 cursor-pointer" - > - {(MASKTYPE[val]).replace("_", " ")} -
- ) - )} -
- } -
- } - - - {/* Mask Character - START */} - { - selectedTag?.subType === TEXT.PASSWORD && -
- -
setDropDownToggle(dropDownToggle === DROPDOWNTOGGLE.MASK_CHARACTER ? null : DROPDOWNTOGGLE.MASK_CHARACTER)} - className="flex justify-between items-center border-1 rounded px-2 py-1 border-slate-200"> -

- {selectedTag?.maskCharacter - ? - selectedTag.maskCharacter === MASKCHARACTER.ASTERISK && || - selectedTag.maskCharacter === MASKCHARACTER.DOT && || - selectedTag.maskCharacter === MASKCHARACTER.X && - : - - } -

- - - -
- - { - dropDownToggle === DROPDOWNTOGGLE.MASK_CHARACTER && -
- {(Object.keys(MASKCHARACTER) as (keyof typeof MASKCHARACTER)[]).map((val, indx) => - ( -
handlePropertyChange("maskCharacter", MASKCHARACTER[val])} - className="capitalize p-2 hover:bg-slate-200 cursor-pointer" - > - { - MASKCHARACTER[val] === MASKCHARACTER.ASTERISK && - - } - { - MASKCHARACTER[val] === MASKCHARACTER.DOT && - - } - { - MASKCHARACTER[val] === MASKCHARACTER.X && - - } -
- ) - )} -
- } -
- } - {/* Mask Character - END */} - - - - - - - - - {/* TEMPORAL DATE FORMAT - START */} - { - (selectedTag?.subType === TEMPORAL.DATE || - selectedTag?.subType === TEMPORAL.TIME || - selectedTag?.subType === TEMPORAL.DATE_TIME) && - -
- {/*
- -
- setShowFormatEg(e.target.checked)} - id="data_time_format" - type="checkbox" /> - -
-
*/} - -
- - {(selectedTag.subType === TEMPORAL.DATE_TIME || selectedTag.subType === TEMPORAL.TIME) && -
- handleIs24HrsClick(e.target.checked)} - id="data_time_format" - type="checkbox" /> - -
- } -
- -
setDropDownToggle(dropDownToggle === DROPDOWNTOGGLE.DDMMYY_FORMAT ? null : DROPDOWNTOGGLE.DDMMYY_FORMAT)} - className="flex justify-between items-center border-1 rounded px-2 py-1 border-slate-200"> -

- {selectedTag.format ? selectedTag.format : dateTimeFormatMap['date'][0].format} - {/* {(selectedTag.subType !== TEMPORAL.DATE && selectedTag.subType !== TEMPORAL.TIME) ? (is24Hrs ? " " + timeFormats[0].format : " " + timeFormats[1].format) : ""} */} -

- -
- - { - dropDownToggle === DROPDOWNTOGGLE.DDMMYY_FORMAT && -
- {dateTimeFormatMap[selectedTag.subType].map((valObj, indx) => { - // let val = showFormatEg ? valObj["example"] : valObj["format"] - let val = valObj["format"] - if (selectedTag.subType === TEMPORAL.DATE_TIME) { - if (is24Hrs) { - val = val + " " + timeFormats[0].format; - } else { - val = val + " " + timeFormats[1].format; - } - } - return ( -
handlePropertyChange("format", valObj["format"])} - className="px-2 py-1 hover:bg-slate-200 cursor-pointer" - > - {val} -
- ) - } - )} -
- } - - {selectedTag.format &&
- {/*

- Example -

*/} -

{dayjs().format(selectedTag.format)}

-
} -
- } - {/* TEMPORAL DATE FORMAT - END */} - - - - {/* NUMBER - DECIMAL PLACES */} - { - selectedTag?.subType === NUMBER.DECIMAL && -
- - handleDecimalPlace(e)} - value={decimalPlace} - className="bg-slate-100 w-full outline-none p-2 rounded" /> -
- } - - - {(selectedTag?.subType === "single select" || selectedTag?.subType === "multi select") && - <> -
- - setSelectedOption(e.target.value)} - value={selectedOption} - onKeyUp={(e) => { - if (e.code === "Enter") { - // if (selectedOption) { - // setSelectedOptions((prev) => [...prev, selectedOption]); - // setSelectedOption(""); - // } - handleAddSelectOption() - } - }} - className="bg-slate-100 w-full outline-none p-2 rounded" /> - -
- { - selectedTag.options && selectedTag.options.map((val, indx) => ( -
-

{val}

- - // setSelectedOptions(prev => - // prev.filter((_, i) => i !== indx) - // ) - handleSelectOptionDel(indx) - } - className="cursor-pointer text-slate-500 hover:text-slate-600" /> -
- )) - } -
-
- - } - - -
-
- {/* Right Side Bar End */} - - ) -} - -export default RightSideBar \ No newline at end of file diff --git a/src/components/process/processStepTwo/rightSideBar/CommonAttrDropDown.tsx b/src/components/process/processStepTwo/rightSideBar/CommonAttrDropDown.tsx new file mode 100644 index 0000000..5ac385e --- /dev/null +++ b/src/components/process/processStepTwo/rightSideBar/CommonAttrDropDown.tsx @@ -0,0 +1,42 @@ + +import { MdKeyboardArrowDown } from 'react-icons/md'; +import { DROPDOWNTOGGLE } from './RightSideBar'; + +interface CommonAttrDropDownInt { + selectedType: any; + subType: string | undefined; + dropDownToggle: DROPDOWNTOGGLE | null; + setDropDownToggle: React.Dispatch>; + handlePropertyChange: (changeTo: string, changeWith: string | boolean | number) => void; +} + +const CommonAttrDropDown: React.FC = ({selectedType, subType, dropDownToggle, setDropDownToggle, handlePropertyChange}) => { + + return ( +
+ +
setDropDownToggle(dropDownToggle === DROPDOWNTOGGLE.TYPE ? null : DROPDOWNTOGGLE.TYPE)} + className="flex justify-between items-center border-1 rounded px-2 py-1 border-slate-200"> +

{subType ? (subType === "date_time" ? "Date Time" : subType) : selectedType[Object.keys(selectedType)[0] as keyof typeof selectedType]}

+ +
+ + {dropDownToggle === DROPDOWNTOGGLE.TYPE && +
+ {Object.keys(selectedType).map((val, indx) => ( +
handlePropertyChange("subType", selectedType[val as keyof typeof selectedType])} + className={`capitalize px-2 py-1 hover:bg-slate-200 cursor-pointer`} + > + {selectedType[val as keyof typeof selectedType] === "date_time" ? "Date Time" : selectedType[val as keyof typeof selectedType]} +
+ ))} +
+ } +
+ ) +} + +export default CommonAttrDropDown \ No newline at end of file diff --git a/src/components/process/processStepTwo/rightSideBar/CurrTimeStampAttr.tsx b/src/components/process/processStepTwo/rightSideBar/CurrTimeStampAttr.tsx new file mode 100644 index 0000000..15b3314 --- /dev/null +++ b/src/components/process/processStepTwo/rightSideBar/CurrTimeStampAttr.tsx @@ -0,0 +1,37 @@ +import React, { useState } from 'react' + +interface CurrTimeStampAttrInt { + type: string; + handlePropertyChange: (changeTo: string, changeWith: string | boolean | number) => void; +} + +const CurrTimeStampAttr: React.FC = ({ type, handlePropertyChange}) => { + + const [isCurrentTimeStamp, setIsCurrentTimeStamp] = useState(true); + + const handleIsCurrentTimeStamp = (checked: boolean) => { + if (type.toLowerCase() === "temporal") { + setIsCurrentTimeStamp(checked) + handlePropertyChange("currentTimeStamp", checked); + } + } + + return ( +
+ + handleIsCurrentTimeStamp(e.target.checked)} + id="use_current_timestamp" + type="checkbox" + /> +
+ ) +} + +export default CurrTimeStampAttr \ No newline at end of file diff --git a/src/components/process/processStepTwo/rightSideBar/LabelAttr.tsx b/src/components/process/processStepTwo/rightSideBar/LabelAttr.tsx new file mode 100644 index 0000000..f40d219 --- /dev/null +++ b/src/components/process/processStepTwo/rightSideBar/LabelAttr.tsx @@ -0,0 +1,21 @@ +import React from 'react' + +interface LabelAttrInt { + label: string; + handlePropertyChange: (changeTo: string, changeWith: string | boolean | number) => void; +} + +const LabelAttr: React.FC = ({ label, handlePropertyChange }) => { + return ( +
+ + handlePropertyChange('label', e.target.value)} + type="text" + className="outline-none border-1 rounded px-2 py-1 border-slate-200" /> +
+ ) +} + +export default LabelAttr \ No newline at end of file diff --git a/src/components/process/processStepTwo/rightSideBar/MaskTypePassAttr.tsx b/src/components/process/processStepTwo/rightSideBar/MaskTypePassAttr.tsx new file mode 100644 index 0000000..69d9e6e --- /dev/null +++ b/src/components/process/processStepTwo/rightSideBar/MaskTypePassAttr.tsx @@ -0,0 +1,100 @@ +import { MdKeyboardArrowDown } from "react-icons/md"; +import { DROPDOWNTOGGLE, MASKCHARACTER, MASKTYPE } from "./RightSideBar"; +import { LuAsterisk } from "react-icons/lu"; +import { GoDotFill } from "react-icons/go"; +import { IoClose } from "react-icons/io5"; + +interface MaskTypePassAttrInt { + maskType: string; + maskCharacter: string; + dropDownToggle: DROPDOWNTOGGLE | null; + setDropDownToggle: React.Dispatch>; + handlePropertyChange: (changeTo: string, changeWith: string | boolean | number) => void; +} + +const MaskTypePassAttr: React.FC = ({ maskType, maskCharacter, dropDownToggle, setDropDownToggle, handlePropertyChange }) => { + return ( + <> + {/* Mask Type */} +
+ +
setDropDownToggle(dropDownToggle === DROPDOWNTOGGLE.MASK_TYPE ? null : DROPDOWNTOGGLE.MASK_TYPE)} + className="flex justify-between items-center border-1 rounded px-2 py-1 border-slate-200"> +

{(maskType && maskType.replace("_", " ")) ? maskType : MASKTYPE.ALL}

+ +
+ + { + dropDownToggle === DROPDOWNTOGGLE.MASK_TYPE && +
+ {(Object.keys(MASKTYPE) as (keyof typeof MASKTYPE)[]).map((val, indx) => + ( +
handlePropertyChange("maskType", MASKTYPE[val])} + className="capitalize px-2 py-1 hover:bg-slate-200 cursor-pointer" + > + {(MASKTYPE[val]).replace("_", " ")} +
+ ) + )} +
+ } +
+ + {/* Mask Character */} +
+ +
setDropDownToggle(dropDownToggle === DROPDOWNTOGGLE.MASK_CHARACTER ? null : DROPDOWNTOGGLE.MASK_CHARACTER)} + className="flex justify-between items-center border-1 rounded px-2 py-1 border-slate-200"> +

+ {maskCharacter + ? + maskCharacter === MASKCHARACTER.ASTERISK && || + maskCharacter === MASKCHARACTER.DOT && || + maskCharacter === MASKCHARACTER.X && + : + + } +

+ + + +
+ + { + dropDownToggle === DROPDOWNTOGGLE.MASK_CHARACTER && +
+ {(Object.keys(MASKCHARACTER) as (keyof typeof MASKCHARACTER)[]).map((val, indx) => + ( +
handlePropertyChange("maskCharacter", MASKCHARACTER[val])} + className="capitalize p-2 hover:bg-slate-200 cursor-pointer" + > + { + MASKCHARACTER[val] === MASKCHARACTER.ASTERISK && + + } + { + MASKCHARACTER[val] === MASKCHARACTER.DOT && + + } + { + MASKCHARACTER[val] === MASKCHARACTER.X && + + } +
+ ) + )} +
+ } +
+ + + ) +} + +export default MaskTypePassAttr \ No newline at end of file diff --git a/src/components/process/processStepTwo/rightSideBar/MaxMinLenAttr.tsx b/src/components/process/processStepTwo/rightSideBar/MaxMinLenAttr.tsx new file mode 100644 index 0000000..67f4196 --- /dev/null +++ b/src/components/process/processStepTwo/rightSideBar/MaxMinLenAttr.tsx @@ -0,0 +1,29 @@ +import React from 'react' + +interface MaxMinLenAttrIntr { + maxLength: number; + minLength: number; +} + +const MaxMinLenAttr : React.FC = ({ maxLength, minLength }) => { + return ( + <> +
+ + +
+
+ + +
+ + ) +} + +export default MaxMinLenAttr \ No newline at end of file diff --git a/src/components/process/processStepTwo/rightSideBar/RecipientsAttrCon.tsx b/src/components/process/processStepTwo/rightSideBar/RecipientsAttrCon.tsx new file mode 100644 index 0000000..7490575 --- /dev/null +++ b/src/components/process/processStepTwo/rightSideBar/RecipientsAttrCon.tsx @@ -0,0 +1,88 @@ +import React, { useEffect, useState } from 'react' +import { IoCheckmark } from 'react-icons/io5'; +import { MdKeyboardArrowDown } from 'react-icons/md'; +import { useSelector } from 'react-redux'; +import { RootState } from '../../../../store/store'; + + +interface SelectedRecipientsIntr { + id: number; + firstName: string; + lastName: string; + color: string; +} + +interface RecipientsAttrConIntr { + selectedRecipientId: number; + handlePropertyChange: (changeTo: string, changeWith: string | boolean | number) => void; +} + +const RecipientsAttrCon: React.FC = ({ selectedRecipientId, handlePropertyChange }) => { + + const [selectedRecipient, setSelectedRecipient] = useState(null); + + const selectedRecipients = useSelector((state: RootState) => state.selectedRecipients.recipients); + const [dropDownToggle, setDropDownToggle] = useState(false); + + useEffect(() => { + if (selectedRecipients.length) { + const filter = selectedRecipients.filter((obj, indx) => obj.id == selectedRecipientId) + setSelectedRecipient(filter[0]); + } + }, [selectedRecipientId]) + + + if (!selectedRecipient) { + return ( + <> + + + ) + } + + + return ( + <> +
setDropDownToggle(false)}> + {/* Selected Recipient */} +
setDropDownToggle(!dropDownToggle)} + className='flex items-center justify-between gap-2 w-full p-2 text-xs rounded-sm border-1 border-slate-200 cursor-pointer'> +
+

+ {/* */} +

{"firstName" in selectedRecipient && selectedRecipient.firstName} {"lastName" in selectedRecipient && selectedRecipient.lastName}

+
+ +
+ +
+ {selectedRecipients.length && selectedRecipients.map((recipient, indx) => { + return (
{ + // handlePropertyChange() + setTimeout(() => { + setDropDownToggle(false); + }, 0) + }} + > +
+

+ {/* */} +

{recipient.firstName} {recipient.lastName}

+
+ {selectedRecipientId === recipient.id && } +
) + })} +
+
+ + ) +} + +export default RecipientsAttrCon \ No newline at end of file diff --git a/src/components/process/processStepTwo/rightSideBar/RequiredAttr.tsx b/src/components/process/processStepTwo/rightSideBar/RequiredAttr.tsx new file mode 100644 index 0000000..ef72316 --- /dev/null +++ b/src/components/process/processStepTwo/rightSideBar/RequiredAttr.tsx @@ -0,0 +1,23 @@ +import React from 'react' + +interface RequiredAttrInt { + required: boolean; + handlePropertyChange: (changeTo: string, changeWith: string | boolean | number) => void; +} + +const RequiredAttr : React.FC = ({required, handlePropertyChange}) => { + return ( +
+ + handlePropertyChange('required', e.target.checked)} + type="checkbox" + className="outline-none border-1 rounded px-2 py-1 border-slate-200" + /> +
+ ) +} + +export default RequiredAttr \ No newline at end of file diff --git a/src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx b/src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx new file mode 100644 index 0000000..6203764 --- /dev/null +++ b/src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx @@ -0,0 +1,367 @@ +import { DroppedItemsObj } from "../DocumentContainer"; +import React, { useEffect, useState } from "react"; + +import { dateFormats, dateTimeFormats, timeFormats } from "../../../../utlity/dateTimeFormats"; +import { DroppedItem } from "../../../../utlity/types"; +import { IoIosArrowDown } from "react-icons/io"; + +import { TagsTypes } from "../../../../utlity/types"; + +import LabelAttr from "./LabelAttr"; +import RequiredAttr from "./RequiredAttr"; +import CurrTimeStampAttr from "./currTimeStampAttr"; +import CommonAttrDropDown from "./CommonAttrDropDown"; +import MaskTypePassAttr from "./MaskTypePassAttr"; +import TemporalDateAttr from "./TemporalDateAttr"; +import SelectTagAttr from "./SelectTagAttr"; +import MaxMinLenAttr from "./MaxMinLenAttr"; +import RecipientsAttrCon from "./RecipientsAttrCon"; + +export interface DroppedItemProps { + selectedTag: DroppedItem + setDroppedItems: React.Dispatch> + selTagKey: string, + selTagIndx: number +} + +export enum TEXT { + PARAGRAPH = "paragraph", + SINGLE_LINE = "single_line", + PASSWORD = "password", +} + +export enum TEMPORAL { + DATE = "date", + TIME = "time", + DATE_TIME = "date_time", +} + +export enum NUMBER { + INTEGER = "integer", + DECIMAL = "decimal", + CURRENCY = "currency" +} + +export enum SELECT { + SINGLE_SELECT = "single select", + MULTI_SELECT = "multi select" +} + +export enum MASKTYPE { + ALL = "all", + LAST_FOUR = "last_four", + CREDIT_CARD = "credit_Card", + NATIONAL_INSURANCE = "national_insurance", + SOCIAL_SECURITY = "social_security", + SOCIAL_INSURANCE = "social_insurance" +} + +export enum MASKCHARACTER { + ASTERISK = "ASTERISK", + DOT = "DOT", + X = "CROSS", +} + +export const enumMap = { + text: TEXT, + temporal: TEMPORAL, + number: NUMBER, + image: String, + select: SELECT +} + +export enum DROPDOWNTOGGLE { + TYPE, + MASK_TYPE, + MASK_CHARACTER, + DDMMYY_FORMAT +} + +const RightSideBar: React.FC = ({ selectedTag, setDroppedItems, selTagKey, selTagIndx }) => { + + const selectedType = selectedTag.type in enumMap && enumMap[selectedTag.type as keyof typeof enumMap]; + + const [dropDownToggle, setDropDownToggle] = useState(null); + const [decimalPlace, setDecimalPlace] = useState(2) + const [styleOpen, setStyleOpen] = useState(false); + + const handlePropertyChange = (changeTo: string, changeWith: string | boolean | number, is24Hrs=null) => { + console.log("Handle Property Change Called", "changeTo", changeTo, "changeWith", changeWith) + if (changeTo === '' || changeWith === '') return + + if (changeTo === "subType" && (changeWith === TEMPORAL.DATE || changeWith === TEMPORAL.DATE_TIME || changeWith === TEMPORAL.TIME)) { + // let change: string = changeWith; + // if (change === "DATE TIME") { + // change = "DATE_TIME" + // } + setDroppedItems((prev) => ( + { + ...prev, + [selTagKey]: Array.isArray(prev[selTagKey]) // Ensure it's an array + ? prev[selTagKey].map((item, i) => + i === selTagIndx ? { ...item, [changeTo]: changeWith || "", format: "", update: true } : item + ) + : [], + }// Provide a fallback in case it's undefined or not an array + )); + } else if (changeTo === "subType" && typeof changeWith === "string" && changeWith.toLowerCase() === "password") { + console.log("Line 161") + setDroppedItems((prev) => ( + { + ...prev, + [selTagKey]: Array.isArray(prev[selTagKey]) + ? prev[selTagKey].map((item, i) => + i === selTagIndx ? { ...item, [changeTo]: changeWith, maskType: "All", maskCharacter: "ASTERISK", update: true } : item + ) + : [], + } + )); + } + else if (changeTo === "subType" && (changeWith === NUMBER.CURRENCY || changeWith === NUMBER.INTEGER || changeWith === NUMBER.DECIMAL)) { + let decPlace = changeWith !== NUMBER.DECIMAL ? 0 : decimalPlace; + const isCurrency = changeWith === NUMBER.CURRENCY; + // const currencyType = null + + setDroppedItems((prev) => ( + { + ...prev, + [selTagKey]: Array.isArray(prev[selTagKey]) // Ensure it's an array + ? prev[selTagKey].map((item, i) => + i === selTagIndx ? { ...item, [changeTo]: changeWith, decimalPlace: decPlace, isCurrency, update: true } : item + ) + : [], + }// Provide a fallback in case it's undefined or not an array + )); + + } else if (changeTo === "format" && selectedTag.subType === TEMPORAL.DATE_TIME) { + let val = timeFormats[0].format; + if (!is24Hrs) { + val = timeFormats[1].format + } + setDroppedItems((prev) => ( + { + ...prev, + [selTagKey]: Array.isArray(prev[selTagKey]) // Ensure it's an array + ? prev[selTagKey].map((item, i) => + i === selTagIndx ? { ...item, [changeTo]: changeWith + " " + val, update: true } : item + ) + : [], + }// Provide a fallback in case it's undefined or not an array + )); + + } else { + setDroppedItems((prev) => ( + { + ...prev, + [selTagKey]: Array.isArray(prev[selTagKey]) // Ensure it's an array + ? prev[selTagKey].map((item, i) => + i === selTagIndx ? { ...item, [changeTo]: changeWith, update: true } : item + ) + : [], + }// Provide a fallback in case it's undefined or not an array + )); + } + setDropDownToggle(null) + } + + useEffect(() => { + if (selectedTag.subType === TEMPORAL.DATE || selectedTag.subType === TEMPORAL.DATE_TIME || selectedTag.subType === TEMPORAL.TIME) { + + if (selectedTag.subType === TEMPORAL.DATE) { + handlePropertyChange("format", dateFormats[0].format) + } + else if (selectedTag.subType === TEMPORAL.DATE_TIME) { + handlePropertyChange("format", dateTimeFormats[0].format) + } + else if (selectedTag.subType === TEMPORAL.TIME) { + handlePropertyChange("format", timeFormats[0].format) + } + } + }, [selectedTag.subType]) + + + useEffect(() => { + if (selectedTag.label === "temporal") { + handlePropertyChange("subType", TEMPORAL.DATE); + handlePropertyChange("format", "DD/MM/YY"); + } + }, []) + + const handleDecimalPlace = (e: React.ChangeEvent) => { + const val = Number(e.target.value) + setDecimalPlace(val) + handlePropertyChange("decimalPlace", val) + } + + useEffect(() => { + if ("styles" in selectedTag) { + const fontSize = selectedTag?.styles?.textSize; + const tagHeight = selectedTag?.dimensions?.height - 18; + + if (selectedTag.subType !== TEXT.PASSWORD && selectedTag.subType !== TEXT.PARAGRAPH && tagHeight > (fontSize + fontSize)) { + handlePropertyChange("subType", TEXT.PARAGRAPH) + } else if (selectedTag.subType !== TEXT.PASSWORD && selectedTag.subType !== TEXT.SINGLE_LINE && tagHeight <= (fontSize + fontSize)) { + console.log("Change subType Called from elseif") + handlePropertyChange("subType", TEXT.SINGLE_LINE) + } + } + }, [selectedTag]) + + return ( + <> + {/* Right Side Bar Start */} +
+

Properties

+
+ +
+ + { + + } + + {selectedTag.label && + } + + {(selectedTag.type !== TagsTypes.SIGNATURE && selectedTag.type !== TagsTypes.INITIALS) && + } + + {selectedTag.type.toLowerCase() === TagsTypes.TEMPORAL && + } + + { + selectedType && Object.keys(selectedType).length > 0 && + + } + + {/* Mask Type */} + { + selectedTag?.subType === TEXT.PASSWORD && + + } + + + {/* TEMPORAL DATE FORMAT - START */} + { + (selectedTag?.subType === TEMPORAL.DATE || + selectedTag?.subType === TEMPORAL.TIME || + selectedTag?.subType === TEMPORAL.DATE_TIME) && + + } + {/* TEMPORAL DATE FORMAT - END */} + + {/* NUMBER - DECIMAL PLACES */} + { + selectedTag?.subType === NUMBER.DECIMAL && +
+ + handleDecimalPlace(e)} + value={decimalPlace} + className="bg-slate-100 w-full outline-none p-2 rounded" /> +
+ } + + { + (selectedTag?.subType === SELECT.SINGLE_SELECT || selectedTag?.subType === SELECT.MULTI_SELECT) && + + + } + + { + selectedTag.type === TagsTypes.TEXT && + + } + + + { +
+
setStyleOpen(!styleOpen)} + > + + +
+ { + styleOpen && <> + {/* Font */} +
+ + +
+ + {/* Text Size */} +
+ + +
+ + {/* Color */} +
+ + +
+ + {/* Toggles for Bold, Italic, Underline */} +
+ + + +
+ + } +
+ } + + + +
+
+ {/* Right Side Bar End */} + + ) +} + +export default RightSideBar \ No newline at end of file diff --git a/src/components/process/processStepTwo/rightSideBar/SelectTagAttr.tsx b/src/components/process/processStepTwo/rightSideBar/SelectTagAttr.tsx new file mode 100644 index 0000000..306ec4a --- /dev/null +++ b/src/components/process/processStepTwo/rightSideBar/SelectTagAttr.tsx @@ -0,0 +1,95 @@ +import { useState } from "react"; +import { DROPDOWNTOGGLE } from "./RightSideBar"; +import { DroppedItemsObj } from "../DocumentContainer"; +import { IoMdClose } from "react-icons/io"; + +interface SelectTagAttrInt { + options: string[] | undefined; + selTagKey: string; + selTagIndx: number; + setDroppedItems: React.Dispatch>; + handlePropertyChange: (changeTo: string, changeWith: string | boolean | number) => void; +} + +const SelectTagAttr: React.FC = ({ options, selTagKey, selTagIndx, setDroppedItems, handlePropertyChange }) => { + const [selectedOption, setSelectedOption] = useState() + + const handleAddSelectOption = () => { + if (selectedOption && selectedOption.length) { + setDroppedItems((prev) => ( + { + ...prev, + [selTagKey]: Array.isArray(prev[selTagKey]) + ? prev[selTagKey].map((item, i) => { + if (i === selTagIndx) { + return { ...item, options: item.options ? [...item.options, selectedOption] : [selectedOption], update: true }; + } + return item; + }) + : [], + } + )); + } + } + + const handleSelectOptionDel = (indx: number) => { + setDroppedItems((prev) => ( + { + ...prev, + [selTagKey]: Array.isArray(prev[selTagKey]) + ? prev[selTagKey].map((item, i) => { + if (i === selTagIndx) { + return { ...item, options: item.options ? item.options.filter((_, i) => i !== indx) : [] }; + } + return item; + }) + : [], + } + )); + } + + return ( + <> +
+ + setSelectedOption(e.target.value)} + value={selectedOption} + onKeyUp={(e) => { + if (e.code === "Enter") { + // if (selectedOption) { + // setSelectedOptions((prev) => [...prev, selectedOption]); + // setSelectedOption(""); + // } + handleAddSelectOption() + } + }} + className="bg-slate-100 w-full outline-none p-2 rounded" /> + +
+ { + options && options.map((val, indx) => ( +
+

{val}

+ + // setSelectedOptions(prev => + // prev.filter((_, i) => i !== indx) + // ) + handleSelectOptionDel(indx) + } + className="cursor-pointer text-slate-500 hover:text-slate-600" /> +
+ )) + } +
+
+ + + ) +} + +export default SelectTagAttr \ No newline at end of file diff --git a/src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx b/src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx new file mode 100644 index 0000000..dfc42bf --- /dev/null +++ b/src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx @@ -0,0 +1,108 @@ +import { useEffect, useState } from "react"; +import { dateFormats, dateTimeFormats, monthFormats, timeFormats, weekFormats, yearFormats } from "../../../../utlity/dateTimeFormats"; +import { DROPDOWNTOGGLE, TEMPORAL } from "./RightSideBar"; +import { MdKeyboardArrowDown } from "react-icons/md"; +import dayjs from "dayjs"; + +const dateTimeFormatMap = { + "date": dateFormats, + "time": timeFormats, + "date_time": dateTimeFormats, + "year": yearFormats, + "month": monthFormats, + "week": weekFormats +} + +interface TemporalDateAttrInt { + subType: string; + format: string | undefined; + dropDownToggle: DROPDOWNTOGGLE | null; + setDropDownToggle: React.Dispatch>; + handlePropertyChange: (changeTo: string, changeWith: string | boolean | number, is24Hrs: boolean) => void; +} + +const TemporalDateAttr: React.FC = ({ subType, format, dropDownToggle, setDropDownToggle, handlePropertyChange }) => { + const [is24Hrs, setIs24Hrs] = useState(true); + + const handleIs24HrsClick = (checked: boolean) => { + if (subType === TEMPORAL.TIME) { + if (!checked) { + handlePropertyChange("format", timeFormats[1].format, is24Hrs) + } else { + handlePropertyChange("format", timeFormats[0].format, is24Hrs) + } + } + setIs24Hrs(checked) + } + + useEffect(() => { + if (format === timeFormats[1].format && is24Hrs) { + setIs24Hrs(false); + } else if (format === timeFormats[0].format && !is24Hrs) { + setIs24Hrs(true); + } + }, [format]) + + return ( +
+
+ + {(subType === TEMPORAL.DATE_TIME || subType === TEMPORAL.TIME) && +
+ handleIs24HrsClick(e.target.checked)} + id="data_time_format" + type="checkbox" /> + +
+ } +
+ +
setDropDownToggle(dropDownToggle === DROPDOWNTOGGLE.DDMMYY_FORMAT ? null : DROPDOWNTOGGLE.DDMMYY_FORMAT)} + className="flex justify-between items-center border-1 rounded px-2 py-1 border-slate-200"> +

+ {format ? format : dateTimeFormatMap['date'][0].format} + {/* {(subType !== TEMPORAL.DATE && subType !== TEMPORAL.TIME) ? (is24Hrs ? " " + timeFormats[0].format : " " + timeFormats[1].format) : ""} */} +

+ +
+ + { + dropDownToggle === DROPDOWNTOGGLE.DDMMYY_FORMAT && +
+ {dateTimeFormatMap[subType].map((valObj, indx) => { + // let val = showFormatEg ? valObj["example"] : valObj["format"] + let val = valObj["format"] + if (subType === TEMPORAL.DATE_TIME) { + if (is24Hrs) { + val = val + " " + timeFormats[0].format; + } else { + val = val + " " + timeFormats[1].format; + } + } + return ( +
handlePropertyChange("format", valObj["format"])} + className="px-2 py-1 hover:bg-slate-200 cursor-pointer" + > + {val} +
+ ) + } + )} +
+ } + + {format &&
+

{dayjs().format(format)}

+
} +
+ ) +} + +export default TemporalDateAttr \ No newline at end of file diff --git a/src/config/api.tsx b/src/config/api.tsx index 81f5bb9..bdfb4f3 100644 --- a/src/config/api.tsx +++ b/src/config/api.tsx @@ -28,7 +28,8 @@ api.interceptors.response.use( async error => { const originalRequest = error.config; // Prevent multiple refresh attempts - if (error.response?.status === 401 || error.response?.status === 500) { + // if (error.response?.status === 401 || error.response?.status === 500) { + if (error.response?.status === 401) { originalRequest._retry = true; try { if (!isRefreshing) { diff --git a/src/store/slices/documentSlice.ts b/src/store/slices/documentSlice.ts index 40fbe0c..b1a67c3 100644 --- a/src/store/slices/documentSlice.ts +++ b/src/store/slices/documentSlice.ts @@ -134,7 +134,6 @@ const documentSlice = createSlice({ }) .addCase(fetchDocuments.fulfilled, (state, action: PayloadAction) => { state.loading = false; - console.log(action.payload, "action.payload") state.documents = action.payload; }) .addCase(fetchDocuments.rejected, (state, action) => { diff --git a/src/store/slices/selectedRecipientsSlice.tsx b/src/store/slices/selectedRecipientsSlice.tsx index 49c2b49..9feaa2c 100644 --- a/src/store/slices/selectedRecipientsSlice.tsx +++ b/src/store/slices/selectedRecipientsSlice.tsx @@ -180,10 +180,9 @@ const selectedRecipientsSlice = createSlice({ extraReducers: (builder) => { builder .addCase(fetchRecipients.pending, (state) => { - console.log("Fetching recipients..."); }) .addCase(fetchRecipients.fulfilled, (state, action: PayloadAction) => { - console.log("Fetched recipients successfully:", action.payload); + // console.log("Fetched recipients successfully:", action.payload); // Assign colors to recipients const assignedRecipients = action.payload.map((recipient, index) => ({ @@ -209,7 +208,7 @@ const selectedRecipientsSlice = createSlice({ .addCase(addRecipientAsync.pending, (state) => { - console.log("Fetching recipients..."); + }) .addCase(addRecipientAsync.fulfilled, (state, action: PayloadAction) => { console.log("Added recipient successfully:", action.payload); diff --git a/src/utlity/dateTimeUtils.ts b/src/utlity/dateTimeFormats.ts similarity index 100% rename from src/utlity/dateTimeUtils.ts rename to src/utlity/dateTimeFormats.ts diff --git a/src/utlity/types.tsx b/src/utlity/types.tsx index eb08579..eb4cc7a 100644 --- a/src/utlity/types.tsx +++ b/src/utlity/types.tsx @@ -79,3 +79,41 @@ export interface AccountData { role: UserRole; status: AccountStatus; } + +export interface TagsProperties { + "editable": boolean; + "required": boolean; + "navigationOrder": number; + "type": string; + "lastName"?: boolean; + "firstName"?: boolean; + "maxLength"?: number; + "minLength"?: number; + "readOnly"?: boolean; + "multiLine"?: boolean; + "regex"?: string[]; + "format"?: string; + "dateFormat"?: string; + "currentTimeStamp"?: boolean; + "decimalPlace"?: number; + "multiSelect"?: boolean; +} + + +export enum TagsTypes { + TEXT= "text", + SIGNATURE= "signature", + INITIALS= "initials", + TEMPORAL= "temporal", + NUMBER= "number", + IMAGE= "image", + STAMP= "stamp", + CHECKBOX= "checkbox", + SELECT= "select", + FILE= "file", + ATTACHMENT= "attachment", + RADIO= "radio", + EMAIL= "email", + NAME= "name", + COMPANY= "company", + }