491 lines
19 KiB
TypeScript
491 lines
19 KiB
TypeScript
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";
|
|
import MovableFieldContainer from "./MovableField";
|
|
import DirectionalControls from "./DirectionalControls";
|
|
|
|
// interface DirectionalControlsProps {
|
|
// onMove: (direction: 'up' | 'down' | 'left' | 'right') => void;
|
|
// disabled?: boolean;
|
|
// stepSize?: number;
|
|
// className?: string;
|
|
// }
|
|
|
|
export interface DroppedItemProps {
|
|
selectedTag: DroppedItem
|
|
setDroppedItems: React.Dispatch<React.SetStateAction<DroppedItemsObj>>
|
|
selTagKey: string,
|
|
selTagIndx: number,
|
|
DirectionalControlsProps: {
|
|
onMove: (direction: 'up' | 'down' | 'left' | 'right', stepSize?: number) => void;
|
|
disabled?: boolean;
|
|
stepSize?: number;
|
|
className?: string;
|
|
}
|
|
}
|
|
|
|
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 defaultStyles = {
|
|
font: "",
|
|
italic: false,
|
|
bold: false,
|
|
underline: false,
|
|
color: "#000000",
|
|
textSize: 0
|
|
};
|
|
|
|
|
|
|
|
const RightSideBar: React.FC<DroppedItemProps> = ({ selectedTag, setDroppedItems, selTagKey, selTagIndx, DirectionalControlsProps }) => {
|
|
|
|
const selectedType = selectedTag.type in enumMap && enumMap[selectedTag.type as keyof typeof enumMap];
|
|
|
|
console.log("selectedTag", selectedTag, selectedType)
|
|
|
|
|
|
|
|
const [styles, setStyles] = useState(defaultStyles);
|
|
|
|
const [dropDownToggle, setDropDownToggle] = useState<DROPDOWNTOGGLE | null>(null);
|
|
const [decimalPlace, setDecimalPlace] = useState<number>(2)
|
|
const [styleOpen, setStyleOpen] = useState(false);
|
|
|
|
const handlePropertyChange = (changeTo: string, changeWith: string | boolean | number, is24Hrs = null) => {
|
|
|
|
console.log("changeTo", changeTo, "changeWith", changeWith)
|
|
if (changeTo === '' || changeWith === '') return
|
|
|
|
if (changeWith === "paragraph") {
|
|
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) => {
|
|
console.log("Temporal30", prev);
|
|
return {
|
|
...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
|
|
)
|
|
: [], // Fallback in case it's undefined or not an array
|
|
};
|
|
});
|
|
|
|
} else if (changeTo === "subType" && typeof changeWith === "string" && changeWith.toLowerCase() === "password") {
|
|
console.log("Second check")
|
|
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)) {
|
|
console.log("Third check")
|
|
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) {
|
|
console.log("Fourth Check")
|
|
let val = timeFormats[0].format;
|
|
if (!is24Hrs) {
|
|
val = timeFormats[1].format
|
|
}
|
|
console.log("val", val)
|
|
|
|
setDroppedItems((prev) => {
|
|
const updatedArray = Array.isArray(prev[selTagKey])
|
|
? prev[selTagKey].map((item, i) => {
|
|
if (i === selTagIndx) {
|
|
const updatedItem = { ...item, [changeTo]: changeWith + " " + val, update: true };
|
|
console.log('Updating item at index', i, 'with:', updatedItem);
|
|
return updatedItem;
|
|
}
|
|
return item;
|
|
})
|
|
: [];
|
|
|
|
return {
|
|
...prev,
|
|
[selTagKey]: updatedArray,
|
|
};
|
|
});
|
|
|
|
|
|
} else {
|
|
setDroppedItems((prev) => {
|
|
|
|
const updatedItems = Array.isArray(prev[selTagKey])
|
|
? prev[selTagKey].map((item, i) =>
|
|
i === selTagIndx ? { ...item, [changeTo]: changeWith, update: true } : item
|
|
)
|
|
: [];
|
|
|
|
console.log('Updated items:', updatedItems);
|
|
|
|
return {
|
|
...prev,
|
|
[selTagKey]: updatedItems,
|
|
};
|
|
});
|
|
|
|
}
|
|
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<HTMLInputElement>) => {
|
|
const val = Number(e.target.value)
|
|
setDecimalPlace(val)
|
|
handlePropertyChange("decimalPlace", val)
|
|
}
|
|
|
|
// useEffect(() => {
|
|
// if ("styles" in selectedTag) {
|
|
// console.log("styles" in selectedTag)
|
|
// const fontSize = selectedTag?.styles?.textSize;
|
|
// const tagHeight = selectedTag?.dimensions?.height - 18;
|
|
|
|
// console.log(fontSize)
|
|
|
|
// 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])
|
|
|
|
|
|
useEffect(() => {
|
|
if (!selectedTag) return;
|
|
|
|
if (!selectedTag.styles) {
|
|
handlePropertyChange("styles", defaultStyles);
|
|
setStyles(defaultStyles);
|
|
} else {
|
|
setStyles({ ...defaultStyles, ...selectedTag.styles });
|
|
}
|
|
|
|
// Optional subType logic
|
|
const fontSize = selectedTag?.styles?.textSize || defaultStyles.textSize;
|
|
const tagHeight = selectedTag?.dimensions?.height - 18;
|
|
|
|
if (
|
|
selectedTag.subType !== TEXT.PASSWORD &&
|
|
selectedTag.subType !== TEXT.PARAGRAPH &&
|
|
tagHeight > fontSize * 2
|
|
) {
|
|
handlePropertyChange("subType", TEXT.PARAGRAPH);
|
|
} else if (
|
|
selectedTag.subType !== TEXT.PASSWORD &&
|
|
selectedTag.subType !== TEXT.SINGLE_LINE &&
|
|
tagHeight <= fontSize * 2
|
|
) {
|
|
handlePropertyChange("subType", TEXT.SINGLE_LINE);
|
|
}
|
|
}, [selectedTag]);
|
|
|
|
const handleStyleChange = (key, value) => {
|
|
const updatedStyles = {
|
|
...(selectedTag.styles ?? defaultStyles),
|
|
[key]: value
|
|
};
|
|
setStyles(updatedStyles);
|
|
handlePropertyChange("styles", updatedStyles);
|
|
};
|
|
|
|
|
|
return (
|
|
<>
|
|
{/* Right Side Bar Start */}
|
|
<div className='col-span-2 w-full h-full bg-white text-sm overflow-y-auto'>
|
|
<p className="p-2 font-semibold text-md">Properties</p>
|
|
<hr className="text-slate-200" />
|
|
|
|
<div className="p-3 text-sm text-slate-600 flex flex-col gap-2">
|
|
|
|
{
|
|
<RecipientsAttrCon selectedRecipientId={selectedTag.recipientId} handlePropertyChange={handlePropertyChange} />
|
|
}
|
|
|
|
<DirectionalControls {...DirectionalControlsProps} selectedType={selectedTag.dimensions} />
|
|
|
|
|
|
{selectedTag.label &&
|
|
<LabelAttr label={selectedTag.label} handlePropertyChange={handlePropertyChange} />}
|
|
|
|
{(selectedTag.type !== TagsTypes.SIGNATURE && selectedTag.type !== TagsTypes.INITIALS) &&
|
|
|
|
<>
|
|
<RequiredAttr required={selectedTag.required ? selectedTag.required : false} handlePropertyChange={handlePropertyChange} />
|
|
</>
|
|
|
|
|
|
}
|
|
|
|
{selectedTag.type.toLowerCase() === TagsTypes.TEMPORAL &&
|
|
<CurrTimeStampAttr type={selectedTag.type} handlePropertyChange={handlePropertyChange} />}
|
|
|
|
{
|
|
selectedType && Object.keys(selectedType).length > 0 &&
|
|
<CommonAttrDropDown
|
|
selectedType={selectedType}
|
|
subType={selectedTag.subType}
|
|
dropDownToggle={dropDownToggle}
|
|
setDropDownToggle={setDropDownToggle}
|
|
handlePropertyChange={handlePropertyChange} />
|
|
}
|
|
|
|
{/* Mask Type */}
|
|
{
|
|
selectedTag?.subType === TEXT.PASSWORD &&
|
|
<MaskTypePassAttr
|
|
maskType={selectedTag.maskType ? selectedTag.maskType : MASKTYPE.ALL}
|
|
maskCharacter={selectedTag.maskCharacter ? selectedTag.maskCharacter : MASKCHARACTER.ASTERISK}
|
|
dropDownToggle={dropDownToggle}
|
|
setDropDownToggle={setDropDownToggle}
|
|
handlePropertyChange={handlePropertyChange} />
|
|
}
|
|
|
|
|
|
{/* TEMPORAL DATE FORMAT - START */}
|
|
{
|
|
(selectedTag?.subType === TEMPORAL.DATE ||
|
|
selectedTag?.subType === TEMPORAL.TIME ||
|
|
selectedTag?.subType === TEMPORAL.DATE_TIME) &&
|
|
<TemporalDateAttr
|
|
subType={selectedTag.subType}
|
|
format={selectedTag.format}
|
|
dropDownToggle={dropDownToggle}
|
|
setDropDownToggle={setDropDownToggle}
|
|
handlePropertyChange={handlePropertyChange} />
|
|
}
|
|
{/* TEMPORAL DATE FORMAT - END */}
|
|
|
|
{/* NUMBER - DECIMAL PLACES */}
|
|
{
|
|
selectedTag?.subType === NUMBER.DECIMAL &&
|
|
<div>
|
|
<label htmlFor="" className="">Decimal Places</label>
|
|
<input
|
|
type="number"
|
|
onChange={(e) => handleDecimalPlace(e)}
|
|
value={decimalPlace}
|
|
className="bg-slate-100 w-full outline-none p-2 rounded" />
|
|
</div>
|
|
}
|
|
|
|
{
|
|
(selectedTag?.subType === SELECT.SINGLE_SELECT || selectedTag?.subType === SELECT.MULTI_SELECT) &&
|
|
<SelectTagAttr
|
|
options={selectedTag.options}
|
|
selTagKey={selTagKey}
|
|
selTagIndx={selTagIndx}
|
|
setDroppedItems={setDroppedItems}
|
|
handlePropertyChange={handlePropertyChange} />
|
|
|
|
}
|
|
|
|
{
|
|
(selectedTag.type.toLowerCase() === TagsTypes.TEXT || selectedTag.type.toLowerCase() === TagsTypes.COMPANY) &&
|
|
<MaxMinLenAttr maxLength={selectedTag.maxLength} minLength={selectedTag.minLength} handlePropertyChange={handlePropertyChange} />
|
|
}
|
|
|
|
|
|
|
|
|
|
{(selectedTag.type.toLowerCase() !== TagsTypes.SIGNATURE && selectedTag.type.toLowerCase() !== TagsTypes.INITIALS) &&
|
|
<div className="">
|
|
<div className="flex items-center justify-between mr-2 cursor-pointer"
|
|
onClick={() => setStyleOpen(!styleOpen)}
|
|
>
|
|
<label
|
|
className="block mb-2">Styles</label>
|
|
<IoIosArrowDown className={`${styleOpen ? "rotate-[-90deg]" : ""} transition-all`} />
|
|
</div>
|
|
{
|
|
styleOpen && <>
|
|
{/* Font */}
|
|
<div className="mb-2">
|
|
<label className="mr-2">Font</label>
|
|
<input
|
|
type="text"
|
|
placeholder="e.g. Arial"
|
|
className="outline-none border-1 rounded px-2 py-1 border-slate-200"
|
|
value={styles.font}
|
|
onChange={(e) => handleStyleChange("font", e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
{/* Text Size */}
|
|
<div className="mb-2">
|
|
<label className="mr-2">Text Size</label>
|
|
<input
|
|
// value={}
|
|
type="number"
|
|
className="outline-none border-1 rounded px-2 py-1 border-slate-200"
|
|
value={styles.textSize}
|
|
onChange={(e) =>
|
|
handleStyleChange("textSize", parseInt(e.target.value, 10) || 0)
|
|
}
|
|
/>
|
|
</div>
|
|
|
|
{/* Color */}
|
|
<div className="mb-2">
|
|
<label className="mr-2">Color</label>
|
|
<input
|
|
type="color"
|
|
className="outline-none border-1 rounded px-2 py-1 border-slate-200 w-10 h-8"
|
|
value={styles.color}
|
|
onChange={(e) => handleStyleChange("color", e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
{/* Toggles for Bold, Italic, Underline */}
|
|
<div className="flex gap-4 items-center mt-2">
|
|
<label className="flex gap-1 items-center">
|
|
<input type="checkbox" checked={styles.bold}
|
|
onChange={(e) => handleStyleChange("bold", e.target.checked)} />
|
|
Bold
|
|
</label>
|
|
<label className="flex gap-1 items-center">
|
|
<input type="checkbox" checked={styles.italic} onChange={(e) => handleStyleChange("italic", e.target.checked)} />
|
|
Italic
|
|
</label>
|
|
<label className="flex gap-1 items-center">
|
|
<input type="checkbox" checked={styles.underline}
|
|
onChange={(e) =>
|
|
handleStyleChange("underline", e.target.checked)
|
|
} />
|
|
Underline
|
|
</label>
|
|
</div>
|
|
</>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
|
|
|
|
</div>
|
|
</div>
|
|
{/* Right Side Bar End */}
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default RightSideBar |